使用相同的构造函数创建对象
重要性:5
假设我们有一个由构造函数创建的任意对象 obj
- 我们不知道是哪个构造函数,但我们想用它创建一个新对象。
我们可以这样吗?
let obj2 = new obj.constructor();
给出一个 obj
的构造函数示例,它可以让这样的代码正常工作。再给出一个使它无法正常工作的示例。
如果我们确定 "constructor"
属性具有正确的值,则可以使用这种方法。
例如,如果我们不触碰默认的 "prototype"
,那么这段代码肯定可以正常工作
function User(name) {
this.name = name;
}
let user = new User('John');
let user2 = new user.constructor('Pete');
alert( user2.name ); // Pete (worked!)
它起作用了,因为 User.prototype.constructor == User
。
…但是,如果有人,这么说吧,覆盖了 User.prototype
并忘记重新创建 constructor
来引用 User
,那么它就会失败。
例如
function User(name) {
this.name = name;
}
User.prototype = {}; // (*)
let user = new User('John');
let user2 = new user.constructor('Pete');
alert( user2.name ); // undefined
为什么 user2.name
是 undefined
?
以下是 new user.constructor('Pete')
的工作原理
- 首先,它在
user
中查找constructor
。没有。 - 然后它沿着原型链向上查找。
user
的原型是User.prototype
,它也没有constructor
(因为我们“忘记”设置它了!)。 - 继续向上查找,
User.prototype
是一个普通对象,它的原型是内置的Object.prototype
。 - 最后,对于内置的
Object.prototype
,有一个内置的Object.prototype.constructor == Object
。所以它被使用了。
最后,我们得到了 let user2 = new Object('Pete')
。
可能,这不是我们想要的。我们想创建 new User
,而不是 new Object
。这就是缺少 constructor
的结果。
(如果你好奇,new Object(...)
调用会将它的参数转换为一个对象。这是一个理论上的东西,在实践中没有人用一个值调用 new Object
,而且通常我们根本不使用 new Object
来创建对象)。