`util.inherits`与NodeJS中的原型扩展之间的区别

时间:2015-04-08 05:31:10

标签: javascript node.js inheritance stream

我一直在使用Node自0.11 / 0.12,所以如果这是一个相对迟到的问题,请纠正我。

我想了解使用util.inherits(Son, Dad)与简单扩展Son.prototype = [new] Dad()原型之间的区别。

对于此示例,我首先使用util.inherits继承Transform stream

var util = require('util')
var Transform = require('stream').Transform

util.inherits(TStream, Transform)

function TStream () {
  Transform.call(this)
}

TStream.prototype._transform = function(chunk, encoding, done) {
  this.push(/* transform chunk! */)
  done()
}

process.stdin.pipe(new TStream()).pipe(process.stdout)

以上似乎是在Node中最常见的解决方法。以下(扩展原型)同样有效(看似),而且更简单:

function TStream() {}
TStream.prototype = require("stream").Transform()

TStream.prototype._transform = function (chunk, encoding, done) {
  this.push(/* transform chunk! */)
  done()
}

process.stdin.pipe(new TStream()).pipe(process.stdout)

为了记录,我知道有through2,它有一个非常简单的界面,并帮助减少几行代码(见下文),但我试图了解引擎盖下的内容,因此问题。

var thru = require("through2")(function (chunk, encoding, done) {
  this.push(/* transform chunk! */)
  done()
})

process.stdin.pipe(stream).pipe(process.stdout)

那么,util.inherits和在Node中扩展原型有什么不同?

1 个答案:

答案 0 :(得分:5)

如果this是util.inherits的实现,它只会为您执行以下操作:

  Child.super_ = Parent;
  //set prototype using Object.create
  Child.prototype = Object.create(Parent.prototype, {
    constructor: {//repair the prototype.constructor
      value: Child,
      enumerable: false,
      writable: true,
      configurable: true
    }

这不是Nodejs中的问题,但是在不支持Object.create的第二个参数的浏览器中(因为polyfil不允许),您可以通过以下方式修复构造函数:

Child.prototype = Object.create(Parent.prototype);//if you polyfilled Object.create
//Child.prototype.constructor is now Parent so we should repair it
Child.prototype.constructor = Child;

它做的额外的事情是设置Child.super_所以在Child中你可以这样做:

function Child(){
  Child.super_.call(this);//re use parent constructor
  //same as Parent.call(this);
}

有关原型和构造函数的更多信息,请阅读this answer

根据following,您正在分类转换错误:

  

在扩展Transform类的类中,请确保调用   构造函数,以便缓冲设置可以正常   初始化。

所以正确的代码应该调用它的构造函数(你不是用new调用Transform,但是构造函数可能有办法处理错误的调用)。

var Transform = require("stream").Transform;
function TStream() {
  Transform.call(this);//you did not do that in your second example
}
//your code sets prototype to an INSTANCE of Transform
//  and forgets to call the constructor with new
//TStream.prototype = require("stream").Transform()
TStream.prototype = Object.create(Transform.prototype);
TStream.prototype.constructor = TStream;
TStream.prototype._transform = function (chunk, encoding, done) {
  this.push(/* transform chunk! */)
  done()
}
process.stdin.pipe(new TStream()).pipe(process.stdout)