Подтвердить что ты не робот

Util.inherits - альтернативный или обходной путь

Я n00b в node и нахожу util.inherits() очень полезным, за исключением того факта, что он, кажется, заменяет весь прототип исходного объекта. Например:

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

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

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

похоже, стирает мой оригинальный прототип.

Это приносит мне два неудобства:
1 - Мне нужно объявить свойства добавления моему прототипу после вызова inherits,

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

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

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

и, самое главное, я думаю, что не могу наследовать от двух или более разных классов.

Может кто-нибудь объяснить мне, почему это имеет смысл и что будет хорошим способом обойти это?

Спасибо

4b9b3361

Ответ 1

Начиная с версии node версии 5.0.0, util.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

Если вы используете более старую версию node, которая поддерживает setPrototypeOf (0.12.x), вы можете просто export использовать. наследует и использует его как функцию внутренней полезности.

Ответ 2

Не имеет смысла, что вы должны объявить свой прототип после util.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 на самом деле не подходит для множественного наследования вообще. Каждый экземпляр имеет только одно внутреннее свойство [[Prototype]], которое используется для поиска членов, которые не найдены в фактическом экземпляре. Вы можете объединить прототипы двух отдельных "родительских классов" в один прототип, но затем вы потеряете наследование для своих родителей, и вы потеряете возможность изменить родительский прототип и увидите, что все дети видят изменение.

Ответ 3

Сначала вы должны наследовать, после определения функции, а затем реализовать свой объект. Также не забудьте вызвать конструктор суперкласса в свой конструктор класса.

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
}

Ответ 4

Мне очень хотелось того же самого и было недовольно расширением, поэтому я создал это расширение для уже полезного метода 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
    }
});

Возможно, я опубликую это, если я нахожу его надежным и полезным все больше и больше. Я просто реализовал его сам, поэтому я даю ему пробный прогон.

Дайте мне знать, что вы думаете!

ПРИМЕЧАНИЕ. Это переопределяет методы в любом из классов с теми, которые определены в прото-хэш в конце. Просто имейте это в виду.