javascript - 为什么要使用 Object.create?

标签 javascript node.js inheritance prototype prototypal-inheritance

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

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)

The prototype of constructor will be set to a new object created from superConstructor.

As an additional convenience, superConstructor will be accessible through the constructor.super_ property.

由此我假设这意味着所有 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)。我想这比定义构造函数并设置其 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
    }
  });
};

总结

新的 superCtor 不会消除在 MyStream 中执行 events.EventEmitter.call(this) 的需要吗?为什么让原型(prototype)相同然后在 MyStream 创建的实际实例上运行 EventEmitter 构造函数而不只是拥有 prototype< 为什么如此重要EventEmitter 的实际实例吗?

此外,向ctor 的原型(prototype)添加constructor 属性的目的是什么?这是我不知道的 JavaScript 东西吗?

最佳答案

第一个 parent 可能需要参数。设置 Child.prototype 时,您正在定义对象,可能还没有准备好创建实例。

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

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

关于javascript - 为什么要使用 Object.create?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21369432/

相关文章:

javascript - 如何将动态创建的复选框添加到 Bootstrap 行

C++ 继承和隐藏不需要的继承函数

c++ - 在 OMNeT++ 中使用多重继承时是否存在任何已知问题?

javascript - Google App Engine "Multiline"和 JavaScript 数组问题

javascript - 无法为nodejs安装express和socket.io

javascript - 使用javascript对结果进行编号时如何用字母代替数字

javascript - 将 promise 转换为 Bluebird

node.js - 如何循环遍历链接并为 PhantomJS 中的每个站点执行 jQuery javascript

mysql - SailsJS - 如何在创建记录时指定字符串属性长度而不会出错?

JavaScript 在子类中设置构造函数?