javascript - 当通过 Object.setPrototypeOf() 向函数原型添加属性时,对象为空
问题描述
让我们考虑以下代码,
let f = function () {
this.a = 1;
this.b = 2;
}
let o = new f();
f.prototype.c = 3;
console.log(Object.getPrototypeOf(o));
印刷
[对象对象] { c: 3 }
但如果我使用 setPrototypeOf 而不是 f.prototype.c,则该对象为空。
let f = function () {
this.a = 1;
this.b = 2;
}
let o = new f();
Object.setPrototypeOf(f, {c: 3});
console.log(Object.getPrototypeOf(o));
印刷
[对象对象] { ... }
但是如果我使用
let f = function () {
this.a = 1;
this.b = 2;
}
let o = new f();
Object.setPrototypeOf(f, {c: 3});
console.log(Object.getPrototypeOf(f));
印刷
[对象对象] { c: 3 }
简而言之,问题是,当使用 Object.setPrototypeOf(o) 时,对象打印为空,而当使用 Object.setPrototypeOf(f) 时,对象打印添加的属性。在使用 f.prototype.c = 3 设置原型时,对象原型和函数原型都可以访问它。
解决方案
当你Object.setPrototypeOf(f, ... )
时,链条实际上是 3 长:
的原型o
是f
。的原型f
是{c:3}
。
所以你的例子并不等同:
1)
在第一个示例中,您将属性c
直接添加到实例f
将使用的原型中,因此o
contains的原型c
是f
的构造函数o
。
在最后两个示例中,您添加c
到 的 proto 中f
,因此创建了原型f
。请记住,函数也只是对象,并且您正在设置用作构造函数的函数的原型。所以 proto 的 proto包含o
的 proto 。f
c
2)
在第二个例子中,你 getPrototypeOf() o
。在第三个中,你 getPrototypeOf() f
。因此只有第三个例子c
再次显示。
3)
如果您检查 chrome 中的元素,您会看到第二个示例的构造函数是f
,因为您询问了 的原型o
。
在第三个示例中,您将看到构造函数是Object
,因为您询问f
已设置为对象{c}
的 proto 并跳过 proto from o
to f
。
PS:我知道这可能是一个令人困惑的解释。
PPS:如果你想要继承,坚持child.prototype = Object.create( parent.prototype ); child.constructor = child;
还是 ES6 类class child extends parent
什么时候可以使用它对我个人来说是最少的困惑。
var first = function first() {
this.value = 'first function';
};
// before .prototype.extra, first inherist from Function.
console.log( 'constructor of first before:', first.constructor );
first.prototype.extra = 'implemented with .prototype.extra';
// after .prototype.extra, first still inherits from Function, we did not change anything to first itself.
console.log( 'constructor of first after:', first.constructor );
// When first is used as a prototype, the instances will get "extra".
// Aka, everything that inherist from first.
var first_instance = new first();
console.log( 'extra on instance of first:', first_instance.extra );
// f itself does NOT have the extra property, only instances of first do.
console.log( 'extra on first itself:', first.extra );
console.log( '------' );
var second = function second() {
this.value = 'second function';
};
// before setPrototypeOf, second inherist from Function, like above.
console.log( 'constructor of second before:', second.constructor );
Object.setPrototypeOf( second, { extra: 'implemented with .setPrototypeOf()' });
// after setPrototypeOf, second inherist from Object, we broke the default inheritance chain.
console.log( 'constructor of second after:', second.constructor );
// BY doing this, we effectively turned second into an object.
// It no longer is a function, so we cannot use function methods like .call() or .apply()
console.log( 'second is object, not function: function.apply', second.apply );
console.log( 'second is object, not function: object.hasOwnProperty', second.hasOwnProperty );
// When second is used as a prototype, the instances will not get "extra".
var second_instance = new second();
console.log( 'extra on instance of second:', second_instance.extra );
// second itself Does have the extra property, sine we assigned it on the prototype used by second. not when second is used as the prototype.
console.log( 'extra on second itself:', second.extra );
推荐阅读
- react-native - react-native-elements 叠加边框透明度
- reactjs - Reactjs 在变量准备好之前不会渲染
- jquery - 如何读取 HTML 元素的 data-original-title 的值
- google-sheets - 如果在某个日期之前,将返回查询中的日期替换为文本
- typescript - TypeScript - 输入“数字”| undefined' 不可分配给类型 'number'
- arrays - 如何根据 jsonb 列值对数据进行排序
- javascript - Vue.js 在组件中使用本地 javascript 文件函数:Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_0__.writeSomething is not a function
- javascript - 在外部播放器中打开媒体文件
- bixby - 如何更改“搜索某事”文本?
- php - 如何使用数据表中选定项目的 id 作为按钮?