【问题标题】:Javascript: How to append the prototype of a function to another one?Javascript:如何将函数的原型附加到另一个函数?
【发布时间】:2012-12-20 03:44:19
【问题描述】:

如何将一个函数的原型附加到另一个函数?比如:

// Foo
function foo(){};
foo.prototype.a = 'hello';

// Bar
function bar(){}
bar.prototype.b = 'world';

// Append Foo's prototype to Bar
bar.appendPrototype(foo);

// Print
console.log(bar.prototype) // -> { a: 'hello', b: 'world' }

【问题讨论】:

  • 我想你的意思是bar.appendPrototype(foo)

标签: javascript merge append prototype


【解决方案1】:

您可以迭代源原型的道具并将每个道具添加到目标原型中。这假设 src 原型的属性是可以复制的简单属性(如函数或简单值,而不是对象本身),通常是这种情况。如果要允许嵌套对象本身的原型属性,则需要克隆每个属性。通常这不是必需的,所以这里是更简单的版本:

bar.appendPrototype = function(src) {
    for (var prop in src.prototype) {
        this.prototype[prop] = src.prototype[prop];
    }
}

bar.appendPrototype(foo);

原型只是对象,因此您可以将一个原型的属性复制到另一个原型。


几年后更新。这种将方法从一个原型复制到另一个原型的一般概念创建了通常称为“混合”的东西,您可以将一个类的方法混合到另一个类中,以便您创建具有两个对象功能的新对象。这是一个interesting article,关于有助于解释的主题。

在实现 mixins 时,现在可以使用 Object.assign() 在一个函数调用中将属性从一个对象复制到另一个对象,而不是编写自己的循环。

您甚至可以对之前使用 ES6 class 语法声明的类进行混入。

一个相当常见的 mixin 示例是,您已经有一个类层次结构(因此您不能只继承),现在您希望叶类也是 eventEmitter 并具有该发射器的所有功能。您可以“混合” EventEmitter 对象,现在您之前声明的类也具有EventEmitter 的功能。您需要采取的一项预防措施(与子类化时相同)是您需要确保两个对象实现之间没有实例属性名称冲突,因为混合代码和您的代码都将访问同一个核心实例对象。

在上面的示例中,mixin 的替代方法是向叶类实例数据添加一个单独的 EventEmitter 对象。如this.emitter = newEventEmitter(). Then, to access the emitter, rather thanthis.emit(...), you would dothis.emitter.emit(...)`。这也有效,但通常不方便或简洁。

【讨论】:

  • 一些事情...首先,bar.appendPrototype 将是未定义的,因为您的函数是 bar.prototype.appendPrototype。其次,如果您将对象作为原型的属性,这种方法具有潜在的危险,因为在目标对象 (bar.prototype) 上修改它们也会在源对象 (foo.prototype) 上修改它们。例如,假设你有foo.prototype.a = [1, 2, 3],然后你有bar.appendPrototype(foo),然后是bar.prototype.a.push(4)。那么foo.prototype.a 现在是[1, 2, 3, 4]
  • 使用最新版本的 Chrome,我必须使用 src.__proto__[prop]this.__proto__[prop] 进行所有操作,否则会出现 .prototype 不是属性的错误。
  • @DevinCarpenter - .prototype 是构造函数或类的属性,而不是实例。如果你想要一个实例的原型,你可以使用Object.getPrototypeOf()。仅供参考,__proto__ 已弃用。
  • @DevinCarpenter - 嗯,它有很多用途。一个有用的原因是当你定义一个类并且你想从另一个对象“借用”一些或所有方法(但可能你已经从另一个对象继承,所以你不能轻易使用继承)时,就像在“混合”。如果 mixin 的概念对您来说是新的,那么有很多关于该主题的参考资料。这是one。仅供参考,这个答案真的很老,所以现在可能会使用Object.assign() 来复制属性。
  • @DevinCarpenter - 仅供参考,为了清楚起见,.__proto__ 是实例的属性。它访问由所有实例共享的原型对象。如果您想在现有对象上更改或添加方法而不影响其他实例,您只需为该实例分配一个属性,如obj.method = function() {...}。仅当您想影响所有实例时才弄乱原型,这通常是在定义类时。
【解决方案2】:

这很容易做到。

function foo(){};
foo.prototype.a =2;

function bar(){
    foo.call(this,null);
}
bar.prototype.b=4;
console.log(bar.prototype); //{a:2,b:4}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    相关资源
    最近更新 更多