如何在没有类的情况下生成对象的新实例?

Kai*_*izo 4 javascript

问题:

如何从该类的实例生成该类的新实例?

我发现了什么:

考虑下一个类及其实例:

// Create a new class
var Foo = function Foo () {
  console.log('New instance of FOO!');
};

Foo.prototype.generate = function(first_argument) {
  this.arr = [1,2,3,4,5];
};

var foo = new Foo();

foo.generate();
console.log(foo.arr); // [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

请注意,它foo是一个实例 fo Foo,我将在示例中使用该实例。

对象.创建

使用 Object.create 我可以生成 foo 实例的新副本,但它们将共享状态数据:

var bar = Object.create(foo);
console.log(bar.arr); // [1,2,3,4,5]

bar.arr.push(6);
console.log(foo.arr); // [1,2,3,4,5,6]
console.log(bar.arr); // [1,2,3,4,5,6]
Run Code Online (Sandbox Code Playgroud)

如果某些逻辑位于构造函数中,则不会调用它。

原型继承

这与对象创建类似,但它调用构造函数。它仍然存在相同的状态数据问题:

var Bar = function () {
  foo.constructor.call(this);
};

Bar.prototype = foo;

var bar = new Bar();
console.log(bar.arr); // [1,2,3,4,5]

bar.arr.push(6);
console.log(foo.arr); // [1,2,3,4,5,6]
console.log(bar.arr); // [1,2,3,4,5,6]
Run Code Online (Sandbox Code Playgroud)

火狐原型

这是我想要做的事情的一个例子,但它只适用于 Firefox:

// Create Bar class from foo
var Bar = foo.constructor;
Bar.prototype = foo.__proto__; // Firefox only
Run Code Online (Sandbox Code Playgroud)

这里我有 Bar 类,它是 Foo 类的副本,我可以生成新实例。

var bar = new Bar();

console.log(bar.arr); // undefined

bar.generate();
console.log(bar.arr); // [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

有没有其他方法可以实现在所有浏览器中都有效的相同目标?

Gam*_*ist 5

1)出于明显的原因必须避免proto ,您可以使用 Object.getPrototypeOf 以标准方式读取对象的原型。
2)你没有构造函数来完成所有的工作,而是有一种带有generate的init方法。因此,在构造函数末尾调用 this.generate 会更有意义。这就是原型继承不起作用的原因:构造函数不起作用。同样的想法,你不能责怪 Object.create 因为它既不构造函数,也不在你的示例中生成,所以你基本上构建了一个具有相同原型的对象,仅此而已。

如果您确实向构造函数添加了对 this.generate 的调用,也许最简单的方法是使用 foo 的构造函数属性来构建一个新对象:

var bar = new foo.constructor();
Run Code Online (Sandbox Code Playgroud)

这会给你一个全新的项目。

所以回答你的问题:是的,还有另一种方法,使用对象实例的构造函数属性来构建一个新项目。

但是没有继承方案能够“猜测”应该使用这样那样的方法来执行完整的初始化。初始化是构造函数的工作。我们可能会想象,例如,您this.arr = [];在构造函数中构建了一个新数组,并且generate()将在该数组中push()项,这将是一种有效的方法。但是,为了优化和清晰起见,您必须避免通过方法添加属性:在构造函数中设置所有实例属性,也许还有原型上的共享属性,并且仅在方法中使用这些属性。