【问题标题】:util.inherits - alternative or workaroundutil.inherits - 替代或解决方法
【发布时间】:2012-11-08 14:37:09
【问题描述】:

我是node中的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(){...};

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

谁能向我解释为什么这是有意义的,以及解决这个问题的好方法是什么?

谢谢

【问题讨论】:

标签: javascript node.js inheritance


【解决方案1】:

你必须在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]] 属性,用于查找在实际实例中未找到的成员。您可以将两个单独的“父类”的原型合并为一个原型,但是您将失去对它们的父类的继承,并且您将失去更改的能力父原型,并让所有孩子都看到更改。

【讨论】:

  • 好的,那么有没有办法扩展一个对象,类似于jQUery的$.extend?
  • 谢谢,有机会我会试试的
【解决方案2】:

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

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
}

【讨论】:

  • 你错过了这里的重点。这正是他试图避免的事情(即,每次他想向原型添加另一个方法时都输入 B.prototype.xxx)。
【解决方案3】:

我非常想要同样的东西并且对扩展不满意,所以我为已经有用的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 哈希中定义。请注意这一点。

【讨论】:

  • 谢谢,似乎是对的。推送到github,社区可以试用。我只能在下周尝试,但我会给你反馈。谢谢
【解决方案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 并将其用作内部实用程序函数。

【讨论】:

    【解决方案5】:

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

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

    【讨论】:

      猜你喜欢
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-13
      相关资源
      最近更新 更多