返回课程

使用相同的构造函数创建对象

重要性: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.nameundefined

以下是 new user.constructor('Pete') 的工作原理

  1. 首先,它在 user 中查找 constructor。没有。
  2. 然后它沿着原型链向上查找。user 的原型是 User.prototype,它也没有 constructor(因为我们“忘记”设置它了!)。
  3. 继续向上查找,User.prototype 是一个普通对象,它的原型是内置的 Object.prototype
  4. 最后,对于内置的 Object.prototype,有一个内置的 Object.prototype.constructor == Object。所以它被使用了。

最后,我们得到了 let user2 = new Object('Pete')

可能,这不是我们想要的。我们想创建 new User,而不是 new Object。这就是缺少 constructor 的结果。

(如果你好奇,new Object(...) 调用会将它的参数转换为一个对象。这是一个理论上的东西,在实践中没有人用一个值调用 new Object,而且通常我们根本不使用 new Object 来创建对象)。