util.inherits - 替代或解决方法

时间:2012-11-20 13:51:54

标签: javascript node.js inheritance

我是节点中的n00b,并且发现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(){...};

而且,最重要的是,我认为我不能从两个或更多不同的类继承。

任何人都可以向我解释为什么这有意义,以及解决这个问题的好方法是什么?

由于

5 个答案:

答案 0 :(得分:12)

确实需要在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]]属性,用于查找在实际实例中找不到的成员。你可以将两个独立的“父类”的原型合并到一个原型中,但是你将失去对他们的父母的继承,你将失去改变的能力父母原型,让所有孩子看到变化。

答案 1 :(得分:9)

您应该首先在函数定义之后继承,然后实现您的对象。另外,不要忘记在类的构造函数中调用超类构造函数。

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
}

答案 2 :(得分:4)

自节点版本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

如果您运行的是支持setPrototypeOf(0.12.x)的旧版本节点,则可以export util.inherits并将其用作内部实用程序功能。< / p>

答案 3 :(得分:2)

我非常想要同样的事情而且对扩展感到不满意,所以我为已经很有用的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
    }
});

如果我发现它越来越强大且有用,我可能会发布这个。我自己几乎没有实现它,所以我给它一个测试运行。

让我知道你的想法!

注意:此执行覆盖任一类上的方法,其中包含末尾proto哈希中定义的方法。请注意这一点。

答案 4 :(得分:0)

Inherits-ex 库是浏览器友好的增强继承,完全兼容标准 node.js 继承,动态继承或创建。

  • 静态继承
  • 多继承(继承链)支持
  • 随时继承——这是您想要的
    • 您不能在以标准方式继承之前声明方法/属性,因为它将替换原型对象。
  • 重复继承检查
  • Es6 类支持
  • 更多辅助功能
    • isInheritedFrom(ctor, superCtor|superCtorName) 检查ctor是否继承自superCtor
    • mixin(ctor, superCtor|superCtor[]) 混合SuperCtor的方法和属性:Clone(Copy) superCtor的所有属性(方法)到ctor。
    • isMixinedFrom
    • createCtor
    • createObject
    • createFunction