3

我有一个问题问你

据我所知,new操作员以这种方式工作

function fakeNew(Ctor) {
  var instance = Object.create(Ctor.prototype);
  instance.constructor();
  // I skip the conditional for simplicity
  return instance;
}

这一切都是从我做Object.createpolifill 开始的,这样我就可以在不使用new.

Object.create = function(proto) {
  function F() { }
  F.prototype = proto;
  return new F();
}

我开始创建很多对象并对它们进行原型设计,但是多次需要初始化它的属性我.init()对它们做了一个方法

var base = {
  init: function() {
    EmitterMixin.call(this);
    return this;
  }
};

var obj = Object.create(base).init();

this但是,当然,我必须记住总是从那里回来,.init()而且很多时候我都忘记了,或者最糟糕的是,我忘了打电话.init()。因此,为了简化对象初始化,我想创建一个全局帮助器来完成它:invoke Object.create,调用初始化函数并返回它。

function create(proto) {
  var child = Object.create(proto);
  child.init();
  return child;
}

然后当我意识到我正在做的实际上是new操作员所做的事情时,我想用头撞墙,但要慢得多。如果 polifill 适用,我什至会new在引擎盖下使用。

所以我问自己,投掷有什么好处new?它在主要浏览器上明显更快,并且由于 javascript 的性质,我们通常需要调用一个 initualizer 函数,而不是new从一开始就做的事情。

最糟糕的是,我注意到比我使用两种不同类型的对象,“抽象”和“实例”,更大的区别是我必须调用的实例,.init()而抽象是不必要的,因为它们只会被用来其他对象的原型。而且我在使用时已经看到了这种模式new

function Foo() { }
Foo.prototype.method = function() { ... };

function Bar() { }
// "abstract" doesnt invoke initializer
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.other = function() { ... };

// "instance", the constructor is called as initializer
var obj = new Bar();

如果我们停止观看真的有好处new吗?我们确定它不是一个比简化我们必须做的事情更高级的工具吗?您认为new和有哪些优点/缺点Object.create

4

1 回答 1

1

我已经尝试了这两种方法,我个人认为传统方法使用new. 的主要论点Object.create是它使原型继承更加清晰 - 您不必了解prototype函数构造函数上属性的复杂性以及它与对象的实际原型的关系。但它确实要求初始化是一个单独的步骤。

我首选的方法是结合这两种方法,例如:

function Animal(name) {
    this.name = name || null;
}
Animal.prototype.eat = function() {
    console.log('yum');
}

function Cat(name) {
    Animal.call(this, name);
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;

Cat.prototype.meow = function() {
    console.log('meow');
}

var garfield = new Cat('garfield');
garfield.eat();
garfield.meow();

Object.create这里比继承更好,Cat.prototype = new Animal()原因有两个:

  1. 如果您想要求该name参数(如果未传递则抛出异常),您可以这样做,并且继承 ( Cat.prototype = Object.create(Animal.prototype)) 仍然有效。
  2. Cat如果你忘记从构造函数中调用构造Animal函数,那么所有应该由构造函数创建的属性都Animal将是未定义的,让你快速意识到错误。

尽管这种方法(使用构造函数和new)不太“纯粹”原型,但它仍然是原型继承,只要您了解如何正确使用它,它就可以正常工作,并且比该Object.create方法需要更少的输入。

我在我的 Javascript OO 库simpleoo的文档中写了一些关于此的其他说明。(注意:我可能很快会更改该库的 API;我链接到它主要是因为文档更详细地讨论了其中一些概念。)

于 2013-05-06T16:15:22.797 回答