将原型添加到现有对象

tho*_*ron 1 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() {}
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式我擦除Base.prototype但我不想.

我试过SubBase.prototype.__proto__ = Base.prototype;显然太慢了.

我知道我可以做(但是写的时间太长而对我来说不是那么干净):

SubBase.prototype.subBaseFunction = function() {};
SubBase.prototype.subBaseOtherFunction = function() {};
Run Code Online (Sandbox Code Playgroud)

我该怎么做/写得更好?

jfr*_*d00 5

而不是这个:

SubBase.prototype = Base.prototype;
SubBase.prototype = {
    subBaseFunction: function() {},
    subBaseOtherFunction: function() {}
}
Run Code Online (Sandbox Code Playgroud)

你需要将每个额外的方法添加到现有的原型对象上,以避免覆盖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() {};
Run Code Online (Sandbox Code Playgroud)

注意:您也不想只是分配,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() {}
});
Run Code Online (Sandbox Code Playgroud)

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

Object.assign(SubBase.prototype, {
    subBaseFunction: function() {},
    subBaseOtherFunction: function() {}
});
Run Code Online (Sandbox Code Playgroud)

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


或者,普通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() {}
});
Run Code Online (Sandbox Code Playgroud)

这是我通常使用的风格:

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
    };
})();
Run Code Online (Sandbox Code Playgroud)


And*_*mie 5

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

SubBase.prototype = Base.prototype;
SubBase.prototype.foo = true;
alert(Base.prototype.foo);
Run Code Online (Sandbox Code Playgroud)

要设置继承链,您需要指定一个 base 实例作为原型:

SubBase.prototype = new Base();
Run Code Online (Sandbox Code Playgroud)

然后你对其进行扩充,就像你在帖子中所做的那样:

SubBase.prototype.newFunction = function () { };
Run Code Online (Sandbox Code Playgroud)

以这种方式进行继承的一个弱点是基类构造函数无法接收参数。如果您需要它,那么您需要使用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();
Run Code Online (Sandbox Code Playgroud)