javascript - `util.inherits` 和扩展 NodeJS 原型(prototype)的区别

标签 javascript node.js inheritance stream

我从 0.11/0.12 开始就一直在使用 Node,所以如果这是一个来晚了的问题,请纠正我。

我试图理解使用 util.inherits(Son, Dad) 和简单地扩展 Son.prototype = [new] Dad() 的原型(prototype)之间的区别.

对于这个例子,我继承了一个 Transform stream首先使用 util.inherits:

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.js 中最常见的处理方式。下面的(扩展原型(prototype))同样有效(表面上),而且更简单:

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)

那么,Node 中 util.inherits 和扩展原型(prototype)的区别是什么?

最佳答案

如果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);
}

有关原型(prototype)和构造函数的更多信息,您可以阅读 this answer .

根据following ,您错误地对 Transform 进行了子类化:

In classes that extend the Transform class, make sure to call the constructor so that the buffering settings can be properly initialized.

所以正确的代码应该调用它的构造函数(你不是用 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)

关于javascript - `util.inherits` 和扩展 NodeJS 原型(prototype)的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29506670/

相关文章:

javascript - 使用 Mongoose 更新信息,对象内部的数组动态地更新

c# - 单例和继承 C#

javascript - 如何为用户制作独特的网址

javascript - 如何知道一个对象是否是使用javascript的Html文档

node.js - 在node.js中将include_type_name参数设置为true

Python子对象无法访问父属性

swift - print() 的长参数产生错误 "Expression was too complex to be solved"

Javascript 触发器 "right arrow"关键事件 - 强制取消选择标签

javascript - 最后延迟下载 .js 文件

javascript - Node.js 中 JSON 字符串的大小是否有限制?