将原型添加到现有对象

时间:2014-05-07 21:32:25

标签: javascript oop inheritance prototype

我想使用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() {};

我该怎么做/写得更好?

3 个答案:

答案 0 :(得分:5)

而不是:

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
    };
})();

答案 1 :(得分:3)

首先,你实际上并没有从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();

答案 2 :(得分:0)

您可以使用jQuery.extend():

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

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

请参阅:http://jsfiddle.net/dd6UC/

jQuery.extend()docs:http://api.jquery.com/jquery.extend/