Объединение нескольких объектов Javascript в один.Что делает Stream.call (это)? - PullRequest
0 голосов
/ 29 октября 2018

Я изучаю код потока NodeJS и этот пример из этой статьи Streams :

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, и пример кода объединяет два объекта вместе.

Поэтому я считаю, что объект Readable после вызова Stream.call(this) имеет все функции Stream и значения полей.

Это правильно?

Я предполагаю, что именно так Javascript выполнял функции, подобные наследованию, но без наследования. Я думаю, что это действительно эквивалентно объединению нескольких объектов Javascript.

Итак, чтобы подтвердить свое понимание, я написал пример кода JSFiddle , который показывает три функции fun1, fun2 и fun3 и MyMultiObj вызывает их, как показано ниже:

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

let myMulti = new MyMultiObj();

В этом коде объект myMulti обладает всеми функциями и полями 4 функций MyMultiObj, fun1, fun2 и fun3.

Я также заметил, что функции, определенные с помощью прототипирования (например, fun2.prototype.really2(), не были объединены / недоступны, что имеет смысл, потому что этот подход НЕ использует прототипирование).

Я думаю, что это довольно круто, и я вижу преимущества, но хочу

  • (a) убедитесь, что мое понимание верно, ... объект Readable после вызова Stream.call(this) имеет все функции Stream и значения полей, а

  • (б) выяснить, почему это делается вместо типичного прототипирования / наследования (если есть причина).

1 Ответ

0 голосов
/ 29 октября 2018

Использование call() просто выполняет функцию с this, являющимся переданным ей объектом, внутри конструктора это похоже на вызов super() в других языках (и ES6):

 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(); // <<
 }
}

Поэтому я считаю, что объект Readable после вызова Stream.call (this) имеет все функции Stream и значения полей.

Только те, которые установлены прямо в конструкторе.Не имеет значений / методов по прототипу

...