instanceof Duplex如何既可写又可读

时间:2016-12-15 00:33:23

标签: javascript node.js

在nodejs环境中考虑这一点:
那么双工如何成为可写和可读的 instanceof

EDIT1: 如何在javascript中实现这一目标? (根据我的阅读,javascript不允许多重继承)

Edit2:似乎是节点v7.1.0 +

的情况
const {Readable, Writable, Duplex} = require('stream');

const r = new Readable();  
const w = new Writable();  
const d = new Duplex();

console.log(d instanceof Duplex);      // true  
console.log(d instanceof Readable);    // true  
console.log(d instanceof Writable);    // true

console.log(r instanceof Writable);    // false  
console.log(w instanceof Readable);    // false  
console.log(w instanceof Duplex);      // false  
console.log(r instanceof Duplex);      // false

console.log(d instanceof Transform);   // false  
console.log(d instanceof PassThrough); // false

console.log(w instanceof Writable);    // true  
console.log(r instanceof Readable);    // true

2 个答案:

答案 0 :(得分:0)

Duplex实现了Writable和Readable,但不是通过多重继承。

看看来源 lib/_stream_duplex.js

util.inherits(Duplex, Readable);

var keys = Object.keys(Writable.prototype);
for (var v = 0; v < keys.length; v++) {
  var method = keys[v];
  if (!Duplex.prototype[method])
    Duplex.prototype[method] = Writable.prototype[method];
}

它继承自Readable,但Writable原型的所有方法也被复制到Duplex的原型中。

instanceof运算符只是向上移动左侧操作数(d)的原型链,检查它是否包含右侧操作数(Writable)的原型。

因为方法是复制的,而不是继承的,所以它永远不会。因此d instanceof Writable应始终为假。

答案 1 :(得分:0)

Node使用全局Symbol.hasInstance在Writable构造函数上定义属性,以便Duplex流实例对instanceof Readableinstanceof Writable都返回true。您可以看到重要的代码here

// Test _writableState for inheritance to account for Duplex streams,
// whose prototype chain only points to Readable.
var realHasInstance;
if (typeof Symbol === 'function' && Symbol.hasInstance) {
  realHasInstance = Function.prototype[Symbol.hasInstance];
  Object.defineProperty(Writable, Symbol.hasInstance, {
    value: function(object) {
      if (realHasInstance.call(this, object))
        return true;

      return object && object._writableState instanceof WritableState;
    }
  });
} else {
  realHasInstance = function(object) {
    return object instanceof this;
  };
}

function Writable(options) {
  // Writable ctor is applied to Duplexes, too.
  // `realHasInstance` is necessary because using plain `instanceof`
  // would return false, as no `_writableState` property is attached.

  // Trying to use the custom `instanceof` for Writable here will also break the
  // Node.js LazyTransform implementation, which has a non-trivial getter for
  // `_writableState` that would lead to infinite recursion.
  if (!(realHasInstance.call(Writable, this)) &&
      !(this instanceof Stream.Duplex)) {
    return new Writable(options);
  }