最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Difference between `util.inherits` and extending the prototype in NodeJS - Stack Overflow

programmeradmin7浏览0评论

I have been using Node since 0.11/0.12 so correct me if this is a matter of ing relatively late to the party.

I am trying to understand the difference between using util.inherits(Son, Dad) and simply extending the prototype of Son.prototype = [new] Dad().

For this example I am subclassing a Transform stream using util.inherits first:

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)

The above seems to be the most mon way to go about this in Node. The following (extending the prototype) works just as well (seemingly), and it's simpler:

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)

For the record, I know there is through2, which has a very simple interface, and do help reducing a few lines of code (see below), but I am trying to understand what is going under the hood, hence the question.

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

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

So, what are the differences between util.inherits and extending the prototype in Node?

I have been using Node since 0.11/0.12 so correct me if this is a matter of ing relatively late to the party.

I am trying to understand the difference between using util.inherits(Son, Dad) and simply extending the prototype of Son.prototype = [new] Dad().

For this example I am subclassing a Transform stream using util.inherits first:

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)

The above seems to be the most mon way to go about this in Node. The following (extending the prototype) works just as well (seemingly), and it's simpler:

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)

For the record, I know there is through2, which has a very simple interface, and do help reducing a few lines of code (see below), but I am trying to understand what is going under the hood, hence the question.

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

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

So, what are the differences between util.inherits and extending the prototype in Node?

Share Improve this question asked Apr 8, 2015 at 5:31 j--j-- 5,6763 gold badges32 silver badges48 bronze badges 1
  • First of; you should not set the prototype of Child to an instance of Parent as it shows a lack of understanding what prototype is. Prototype is shared and Parent may have instance specific members that end up on Child.prototype. If these members are mutable and you don't re use Parent constructor (doing Parent.call(this) in Child constructor) you will have Child instances mutating a shared member that should be instance specific. Use Child.prototype = Object.create(Parend.prototype) instead. – HMR Commented Apr 8, 2015 at 7:56
Add a ment  | 

1 Answer 1

Reset to default 8

If this is the implementation of util.inherits it only does the following for you:

  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
    }

This is not a problem in Nodejs but in browsers that don't support a second argument to Object.create (because the polyfil does not allow it) you can repair the constructor in the following way:

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;

The extra thing it does is setting Child.super_ so in Child you can do:

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

For more information on prototype and constructor functions you can read this answer.

According to the following, you are sub classing Transform incorrectly:

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

So the correct code should call it's constructor (you are not calling Transform with new but maybe the constructor has a way of handling faulty calls).

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)
发布评论

评论列表(0)

  1. 暂无评论