我们为什么要使用Object.create?

时间:2014-01-26 21:26:25

标签: javascript node.js inheritance prototype prototypal-inheritance

我一直在努力理解为什么我一直在节点中看到这样的代码:

var util = require("util");
var events = require("events");

function MyStream() {
    events.EventEmitter.call(this);
}

util.inherits(MyStream, events.EventEmitter);

MyStream.prototype.write = function(data) {
    this.emit("data", data);
}

我去了文档以便更好地理解。

util.inherits(constructor, superConstructor)
  

构造函数的原型将设置为从superConstructor创建的新对象。

     

作为额外的便利,可以通过constructor.super_属性访问superConstructor。

由此我认为这意味着所有util.inherits都是这样的:

exports.inherits = function (constructor, superConstructor) {
    constructor.super_ = superConstructor;
    constructor.prototype = new superConstructor();
}

似乎对我有意义,但后来我在MyStream构造函数中注意到它们调用了event.EventEmitter.call(this);,以便EventEmitter构造函数在正在创建的MyStream实例上运行。我对此完全感到困惑,因为constructor.prototype = new superConstructor();应该是它所需要的一切吗?好吧,我去了源码,发现了实际的功能签名。

exports.inherits = function(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
};

一旦我看到这一点,我就会在弄清Object.create在这里做什么时感到困惑。为什么这样做而不只是new superCtor()?我试着the documentation查看Object.create,但我仍然感到困惑。让我试着看看我是否可以清楚地表达我想法正在发生什么,你们可以纠正我:)

Object.create(proto [, propertiesObject ])的第一个参数是您希望这个新对象拥有的原型。我想这比定义构造函数和设置其prototype属性的经典方法更容易?第二个参数是一个带有属性的简单哈希,应该添加到它将返回的新创建的对象中?所以,这......

var myInstance = Object.create(somePrototype, { someProp: someVal, someProp2: someVal2);

......而不是这个?

function MyClass () {
    this.prop = someVal;
    this.prop2 = someVal2;
    // etc
}
MyClass.prototype = somePrototype;
var myInstance = new MyClass();

我不确定我对Object.create的理解是否完全准确,所以希望你们能澄清一下。假设我现在理解Object.create为什么util.inherits函数看起来不像这样?

exports.inherits = function(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(new superCtor, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
};

总结

new superCtor不会消除events.EventEmitter.call(this)MyStream的需要吗?为什么我们使原型相同然后在EventEmitter正在创建的实际实例上运行MyStream构造函数而不是让prototype成为{的实际实例,这一点非常重要{1}}?

另外,为EventEmitter的原型添加constructor属性的目的是什么?这是一个我不知道的JavaScript事情吗?

1 个答案:

答案 0 :(得分:1)

第一位家长可能需要参数。在设置Child.prototype时,您正在定义对象,但可能尚未准备好创建实例。

第二个父实例特定值(this.someval)放在子项的原型上,然后在所有子实例之间共享,或者当Parent.apply(this,arguments)在子实体中执行并遮蔽它们时变得无用。 / p>

有关构造函数和原型的更多信息:https://stackoverflow.com/a/16063711/1641941