web-dev-qa-db-ja.com

util.inherits-代替または回避策

私はノードのn00bであり、元のオブジェクトのプロトタイプ全体を置き換えるように見えるという事実を除いて、util.inherits()は非常に便利です。例えば:

var myClass = function(name){
    this._name = name;  
};

myClass.prototype = {
    (...)
};

util.inherits(myClass, require('events').EventEmitter);

元のプロトタイプを消去しているようです。

それは私に2つの不便をもたらします:
1-inheritsを呼び出した後、プロトタイプにプロパティを追加することを宣言する必要があります。

var myClass = function(name){
    this._name = name;  
};

util.inherits(myClass, require('events').EventEmitter);

myClass.prototype.prop1 = function(){...};
myClass.prototype.prop2 = function(){...};

そして、最も重要なのは、2つ以上の異なるクラスから継承できないと思います。

誰かが私にこれが理にかなっている理由とこれを回避するための良い方法は何であるかを説明できますか?

ありがとう

19

ノードバージョン5.0.0以降、 til.inherits は、 setPrototypeOf メソッドを使用して探している動作をサポートするように変更されました。

FirstBase.js

function FirstBase(firstBaseProp){
    this.firstBaseProp = firstBaseProp;
}

FirstBase.prototype.getFirstBaseProp = function(){
    return this.firstBaseProp;
};


module.exports = FirstBase;

SecondBase.js

var FirstBase = require('./FirstBase.js'),
    util = require('util');

function SecondBase(firstBaseProp, secondBaseProp){
    this.secondBaseProp = secondBaseProp;
    SecondBase.super_.apply(this, arguments);
}

SecondBase.prototype.getSecondBaseProp = function(){
    return this.secondBaseProp;
};

util.inherits(SecondBase, FirstBase);

module.exports = SecondBase;

ThirdBase.js

var SecondBase = require('./SecondBase.js'),
    util = require('util');

function ThirdBase(firstBaseProp, secondBaseProp, thirdBaseProp){
    this.thirdBaseProp = thirdBaseProp;
    ThirdBase.super_.apply(this, arguments);
}

ThirdBase.prototype.getThirdBase = function(){
    return this.thirdBaseProp;
};

util.inherits(ThirdBase, SecondBase);

module.exports = ThirdBase;

instance.js

var ThirdBase = require('./ThirdBase.js');

var instance = new ThirdBase('first', 'second', 'third');

// With node < 5.0.0 (Object.create)
console.log(instance.getFirstBaseProp()); // first
console.log(instance.getSecondBaseProp()); // undefined
console.log(instance.getThirdBase()); // undefined

// With node >= 5.0.0 (Object.setPrototypeOf)
console.log(instance.getFirstBaseProp()); // first
console.log(instance.getSecondBaseProp()); // second
console.log(instance.getThirdBase()); // third

setPrototypeOfをサポートする古いバージョンのノードを実行している場合(0.12.xはサポートします)、exporttil.inherits だけで、内部として使用できます。効用関数。

4
LifeQuery

notutil.inherits()の後にプロトタイプを宣言する必要があることは理にかなっています。私の推測では、util.inheritsは内部使用のみの方法として作成され、当初意図されていた限られた内部ユースケースのみに合わせて調整され、ある時点で一般的な使用のために公開されました。 utilモジュールは純粋なJSで記述されているため、プロトタイプを保持する独自のバージョンのutil.inheritを実装するのは非常に簡単です。元のutil.inheritソースは次のとおりです。

exports.inherits = function(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
};

多重継承に関しては、Javascriptのプロトタイプ継承は多重継承にはまったく適していないため、これは取り組むのがはるかに難しい問題になります。各インスタンスには、実際のインスタンスにないメンバーを検索するために使用される1つの内部[[Prototype]]プロパティのみがあります。 could 2つの別々の「親クラス」のプロトタイプを1つのプロトタイプにマージしますが、その後、theirの親への継承が失われ、変更する機能が失われます。親のプロトタイプを作成し、すべての子に変更を確認してもらいます。

12
lanzz

関数定義の後に最初に継承し、次にオブジェクトを実装する必要があります。また、クラスのコンストラクターでスーパークラスコンストラクターを呼び出すことを忘れないでください。

Function A(y){
  this.y = x;
}

Function B(x,y){
  this.x = x;
  A.call(this,y);
}

util.inherits(B,A);

B.prototype.mythodA = function() {
    //do something
}
9
Delio

私は同じことを非常に望んでいて、extendに不満を持っていたので、すでに便利なutil.inheritsメソッドにこの拡張機能を作成しました。

var util = require('util');

module.exports = {
    inherits : function(sub, sup, proto) {
        util.inherits(sub, sup);
        if (typeof proto !== 'undefined') {
            Object.keys(proto).forEach(function(key) {
                sub.prototype[key] = proto[key];
            });
        }
    }
};

これをプロジェクトの./util/index.jsに入れてから、これを実行して使用します。

var EventEmitter = require('events').EventEmitter;
var util = require('./util');

function Foo() {
    EventEmitter.call(this);
}

util.inherits(Foo, EventEmitter, {
    bar : function(){
        console.log(this instanceof EventEmitter); // true
    }
});

堅牢で便利だと思ったら、これを公開するかもしれません。自分で実装することはほとんどなかったので、テストを実行します。

どう考えているか教えてください!

注:これはdoesいずれかのクラスのメソッドを、最後にプロトハッシュで定義されているメソッドでオーバーライドします。ただそれに注意してください。

2
jedmao