2016-12-15 64 views
0

在nodejs環境中考慮這個:
那麼雙工怎麼可能是實例都可寫和可讀?instanceof Duplex如何可寫和可讀

編輯1: 而這怎麼能在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

因爲'複式流是實現兩者的讀取和寫入interfaces.'流 - [文件](https://nodejs.org/api/stream.html#stream_class_stream_duplex ) –

+0

我以爲JavaScript不允許多重繼承。對不起,我應該修改我的問題。 – thierry

+1

JavaScript允許原型鏈的深度超過1級。你不能在每個關卡上繼承多件事,但是你可以擁有任意數量的關卡。 – 4castle

回答

0

節點使用全局Symbol.hasInstance在Writable構造函數上定義一個屬性,以便雙工流實例對於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); 
    } 
+0

Thnx。基本上,可寫有它自己的instanceof方法,並將自己附加到任何誰調用可寫?我想我得到了一般概念。我可能需要再次閱讀代碼才能完全理解它的實現。 – thierry

+0

@thierry基本上當你調用'foo instanceof Constructor'時,發生了什麼就像'Constructor [Symbol.hasInstance](foo)'。 – idbehold

+0

那部分沒問題。但主要是如何使用realHasInstance防止無限遞歸。 – thierry

0

複式實現可讀寫的,而不是通過多重繼承。

看看源代碼 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]; 
} 

它從讀繼承,而是全部來自可寫的原型方法也被複制到複式的原型。 (d),檢查它是否包含右側操作數(Writable)的原型。

因爲方法被複制,而不是繼承,它永遠不會。因此d instanceof Writable應始終爲false。

+0

但是當我做一個'd instanceof Writable'我真的 – thierry

+0

你確定嗎?我在本地嘗試使用Node的最新版本,我肯定會得到'false'。 –

+0

是的。但我在7.1.0上。我運行完全相同的代碼。但我有進口頂端。 const {Readable,Writable,Duplex} = require('stream'); – thierry