【问题标题】:Merging multiple Javascript objects into one. What does Stream.call(this) do?将多个 Javascript 对象合并为一个。 Stream.call(this) 做什么?
【发布时间】:2018-10-29 05:29:46
【问题描述】:

我正在研究这个Streams article中的NodeJS Stream代码和这个例子:

const { Readable } = require('stream');

const inStream = new Readable({
  read() {}
});

inStream.push('ABCDEFGHIJKLM');
inStream.push('NOPQRSTUVWXYZ');

inStream.push(null); // No more data

inStream.pipe(process.stdout);

当我进入new Readable() 调用时,我看到如下代码:

const Stream = require('stream');

function Readable(options) {
   // ... 
   Stream.call(this);
}

Stream.call(this) 是做什么的?我以前从未见过这样的代码。

我知道 Javascript Object.call() 方法的作用,并且通常在另一个函数中看到它。

myObj.myFunc.call(this);

我阅读了 MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call,示例代码将两个对象组合在一起。

所以我认为调用Stream.call(this) 后的Readable 对象具有所有Stream 函数和字段值。

这是正确的吗?

我猜这是 Javascript 实现类继承功能的方式,但没有继承。我认为这真的相当于合并多个 Javascript 对象。

为了证明我的理解,我写了一个JSFiddle code example,其中显示了三个函数 fun1、fun2 和 fun3,并让 MyMultiObj 调用它们,如下所示:

function MyMultiObj() {
   fun1.call(this);
   fun2.call(this);
   fun3.call(this);
}

let myMulti = new MyMultiObj();

在此代码中,myMulti 对象具有 MyMultiObj、fun1、fun2 和 fun3 4 个函数的所有功能和字段。

我还注意到通过原型定义的函数(例如,fun2.prototype.really2() 没有合并/可用,这是有道理的,因为这种方法不使用原型)。

我觉得这很酷,而且可以看到好处,但是想

  • (a) 验证我的理解是否正确,...调用Stream.call(this) 后的Readable 对象具有所有Stream 函数和字段值,并且

  • (b) 找出为什么这样做而不是典型的原型设计/继承(如果有原因的话)。

【问题讨论】:

  • 它正在调用父构造函数。 Readable 继承自 Stream,因此它将其原型设置为从 Stream 的原型继承,并进行此调用以初始化自身。对于 ES6 类,它看起来像 class Readable extends Stream { constructor() { super(); } }(尽管如果它只调用 super(),你可以省略 constructor())。
  • @Ry,我认为它确实不是父构造函数,因为它没有使用class extendsStream.prototype.func2,这是正确的。我确实同意它在概念上与您描述的相似。就是说把这个函数附加到我自己(我的this)。
  • 不,它实际上只是常规继承,以最令人困惑的方式编写,因为文件滥用了提升。这里是原型设置的地方:github.com/nodejs/node/blob/…

标签: javascript node.js node-streams


【解决方案1】:

使用call() 只是执行一个函数,其中this 是传递给它的对象,在构造函数内部它就像其他语言(和ES6)中的super() 调用:

 function Stream() {
   this.something = 1;
 }

 function Readable () {
   Stream.call(this);
 }

 (new Readable()).something // 1

等于:

 class Stream {
  constructor() {
     this.something = 1;
 }
}

class Stream extends Readable {
 constructor() {
  super(); // <<
 }
}

所以我认为调用 Stream.call(this) 后的 Readable 对象具有所有 Stream 函数和字段值。

只有那些直接在构造函数中设置的。它没有原型的值/方法

【讨论】:

  • 我认为它类似于继承,但并不完全相同,因为它确实是将多个对象合并为一个。你同意我的观点吗?
  • @pats 是的,虽然只有一个对象。
  • 是的。我应该说,一个对象具有其他功能添加到它的功能(带有字段的功能)。从概念上讲,如果每个函数 fun1、fun2、fun3 代表三种对象的构造函数,那么fun1.call(this) 使当前对象现在具有fun1() 构造函数添加的能力。
猜你喜欢
  • 2018-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 2018-10-15
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
相关资源
最近更新 更多