【问题标题】:Add prototype to existing object将原型添加到现有对象
【发布时间】:2014-05-07 21:32:24
【问题描述】:

我想使用 Javascript 进行一些继承。问题是我不知道如何将 A 类原型保留在继承的对象上。

这是我的代码:

function Base() {
    this.attribute1 = null;
}

Base.prototype = {
    baseFunction: function() {}
};

function SubBase()
{
    Base.call(this); // Constructor call
    this.baseFunction();
    this.subBaseFunction();
}

SubBase.prototype = Base.prototype;
SubBase.prototype = {
    subBaseFunction: function() {},
    subBaseOtherFunction: function() {}
}

这样我会删除Base.prototype,但我不想这样做。

我试过SubBase.prototype.__proto__ = Base.prototype;it is apparently too slow

我知道我能做到(但写得太长而且对我来说不是那么干净):

SubBase.prototype.subBaseFunction = function() {};
SubBase.prototype.subBaseOtherFunction = function() {};

我怎样才能做得更好/写得更好?

【问题讨论】:

  • 您可能需要考虑使用SubBase.prototype = new Base(); 而不是SubBase.prototype = Base.prototype;
  • 我想我会使用最后一种方式

标签: javascript oop inheritance prototype


【解决方案1】:

首先,您实际上并没有从 Base 继承...您只是向它添加函数。

SubBase.prototype = Base.prototype;
SubBase.prototype.foo = true;
alert(Base.prototype.foo);

要建立继承链,你需要分配一个base的实例作为原型:

SubBase.prototype = new Base();

然后你增加它,就像你在你的帖子中一样:

SubBase.prototype.newFunction = function () { };

以这种方式进行继承的一个缺点是您的基类构造函数无法接收参数。如果需要,则需要使用Object.create 设置继承,并手动调用基类构造函数:

function Base(x) {
    alert(x);
};
Base.prototype.baseFunction = function () {
    alert('called method from base class');
};

function SubBase(x) {
    Base.call(this, x);
};
SubBase.prototype = Object.create(Base.prototype);

var instance = new SubBase(1);
instance.baseFunction();

【讨论】:

  • 通过new Base(),我还得到了对象的属性,如何从原型中删除它们?
  • 如果您不希望它们被继承,请不要将它们添加到 Base.prototype 并且不要将它们设置在构造函数中。不幸的是,将参数传递给基类构造函数并不容易。您必须显式调用该构造函数
  • 我已经编辑了我的答案,以展示如何将参数传递给基类构造函数。
  • 有了SubBase.prototype = Object.create(Base.prototype),我继承自Base ?
  • 是的,您可以使用 new SubBase(x).baseFunction() 进行测试 - baseFunction 是继承的。我在答案中添加了一个示例。
【解决方案2】:

而不是这个:

SubBase.prototype = Base.prototype;
SubBase.prototype = {
    subBaseFunction: function() {},
    subBaseOtherFunction: function() {}
}

您需要将每个附加方法添加到现有原型对象中,以避免覆盖您刚刚放在那里的Base.prototype

// establish the prototype we're inheriting from
// make a new object into the prototype so when we change it, it 
// doesn't change the original
SubBase.prototype = Object.create(Base.prototype);

// now add more methods onto the inherited prototype
SubBase.prototype.subBaseFunction = function() {};
SubBase.prototype.subBaseOtherFunction = function() {};

注意:您也不想只分配Base.prototype,因为当您更改SubBase.prototype 时,您实际上会更改两个对象(对象分配只是一个参考)。所以在这里,我使用Object.create(Base.prototype) 来创建该原型的副本。


许多库支持某种extend() 函数,该函数将属性从一个对象复制到另一个对象。这使您可以定义一个单独的方法对象,然后将其“添加”到现有原型中,但此功能不是内置于普通 javascript 中。

例如在 jQuery 中,你可以这样做:

// establish the prototype we're inheriting from
SubBase.prototype = Object.create(Base.prototype);

jQuery.extend(SubBase.prototype, {
    subBaseFunction: function() {},
    subBaseOtherFunction: function() {}
});

或者,2016 年更新,ES6 包含一个Object.assign() function,它将属性从一个对象复制到另一个对象:

Object.assign(SubBase.prototype, {
    subBaseFunction: function() {},
    subBaseOtherFunction: function() {}
});

或者,您可以创建自己的函数,只需几行代码即可将属性从一个对象复制到另一个对象。


或者,用纯javascript编写相同的代码:

// copy properties from src to target
function copyProperties(target, src) {
    for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
            target[prop] = src[prop];
        }
    }
    return(target);
}

// establish the prototype we're inheriting from
SubBase.prototype = Object.create(Base.prototype);

copyProperties(SubBase.prototype, {
    subBaseFunction: function() {},
    subBaseOtherFunction: function() {}
});

这是我通常使用的样式:

function Base() {
    this.attribute1 = null;
}

Base.prototype = {
    baseFunction: function() {}
};

function SubBase()
{
    Base.apply(this, arguments); // Constructor call with arguments
}

(function() {
    var proto = SubBase.prototype = Object.create(Base.prototype);
    proto.constructor = SubBase;
    proto.subBaseFunction = function() {
        // code here
    };
    proto.subBaseOtherFunction = function() {
        // code here
    };
})();

【讨论】:

  • 是的,我认为这是让它发挥作用的唯一方法! 编辑:我不会使用 jQuery
  • @thomash - jQuery 没问题。我只是在说明一个extend() 类型的方法,它将属性从一个对象复制到另一个对象。自己编写这样一个函数只需要大约 10 行代码——不需要 jQuery 使用那种风格。
  • @thomash - 看看我通常使用的样式,我添加到我的答案末尾。
  • 添加了 Object.assign(),现在出现在 ES6 中。
【解决方案3】:

您可以为此使用 jQuery.extend():

SubBase.prototype = {
    subBaseFunction: function() {},
    subBaseOtherFunction: function() {}
};

$.extend(SubBase.prototype, Base.prototype);

见:http://jsfiddle.net/dd6UC/

jQuery.extend() 文档:http://api.jquery.com/jquery.extend/

【讨论】:

    猜你喜欢
    • 2017-01-12
    • 2017-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 2021-11-12
    • 1970-01-01
    相关资源
    最近更新 更多