使用原型的Javascript类系统

使用原型的Javascript类系统,javascript,inheritance,prototype,Javascript,Inheritance,Prototype,我正在尝试使用函数和原型在JS中创建一个“类式”继承系统。 其思想是实现类似于ExtJS类系统的东西,而不需要整个框架的开销 所以现在我创建了一个ObjectBase函数,修改了它的原型以包含一些共享功能 并编写了一个injectProto()函数来合并两个函数原型(在一个循环中) 下面是injectProto()代码 /** * Injects a function's prototype into another function's prototype. * * @param {

我正在尝试使用函数和原型在JS中创建一个“类式”继承系统。 其思想是实现类似于ExtJS类系统的东西,而不需要整个框架的开销

所以现在我创建了一个
ObjectBase
函数,修改了它的原型以包含一些共享功能 并编写了一个
injectProto()
函数来合并两个函数原型(在一个循环中)

下面是
injectProto()
代码

/**
 * Injects a function's prototype into another function's prototype.
 * 
 * @param  {Function} fn1   The function to inject into
 * @param  {Function} fn2   The function to inject from
 * @return {Function}       The injected function
 */
function injectProto(fn1, fn2) {
    for (var m in fn2.prototype) {

        Object.defineProperty(fn1.prototype, m, {
            value: fn2.prototype[m]
        });
    }

    fn1.prototype.constructor = fn1;
    fn1.prototype.parent = fn2.prototype;

    return fn1;
}
/**
 * Base Object, provides shared functionalities.
 * 
 * [!] All functions extend this one
 * 
 */
var ObjectBase = function(){
};
var ObjectBase.prototype = {
    constructor: ObjectBase,
    parent: none,
    listeners: [],

    addListener: function(listener) {
        this.listeners.push(listener);
    },
    getListeners: function() {
        return this.listeners;
    },
    removeListener: function(listener) {
        for (var i = 0; i < this.listeners.length; i++) {
            if (listener === this.listeners[i]) {
                this.listeners.splice(i, 1);
                break;
            }
        }
    }
};
以及
ObjectBase
代码

/**
 * Injects a function's prototype into another function's prototype.
 * 
 * @param  {Function} fn1   The function to inject into
 * @param  {Function} fn2   The function to inject from
 * @return {Function}       The injected function
 */
function injectProto(fn1, fn2) {
    for (var m in fn2.prototype) {

        Object.defineProperty(fn1.prototype, m, {
            value: fn2.prototype[m]
        });
    }

    fn1.prototype.constructor = fn1;
    fn1.prototype.parent = fn2.prototype;

    return fn1;
}
/**
 * Base Object, provides shared functionalities.
 * 
 * [!] All functions extend this one
 * 
 */
var ObjectBase = function(){
};
var ObjectBase.prototype = {
    constructor: ObjectBase,
    parent: none,
    listeners: [],

    addListener: function(listener) {
        this.listeners.push(listener);
    },
    getListeners: function() {
        return this.listeners;
    },
    removeListener: function(listener) {
        for (var i = 0; i < this.listeners.length; i++) {
            if (listener === this.listeners[i]) {
                this.listeners.splice(i, 1);
                break;
            }
        }
    }
};
输出:

[function()]
[function()]  // Should be empty (?)
为什么呢?在
injectProto
中,我确实将每个属性从一个原型分配到了另一个原型。有人能帮我吗


感谢回答您的问题,您在原型上设置了属性
listeners
,因此它由所有实例共享。构造函数需要在每个实例对象上创建此属性

function ObjectBase() {
  this.listeners = [];
  this.parent = 'none'; // you have `parent: none` which will error as `none` is undefined
} 


另外,不要使用
delete
从数组中删除元素;你会把索引搞砸的。使用适当的数组方法,如
拼接
。另外,不要在数组上使用
for..in

为什么不使用ES6(它提供了伪类)或Resig的简单继承?或者我个人最喜欢的方法,停止尝试在原型语言中使用经典继承。正如你所知,类在ECMAScript 6()中正在标准化。我已经离开JS一段时间了,我将进入ES6,谢谢@数学“…停止尝试在原型语言中使用经典继承…”,这通常也是我的方法,直到我发现自己在做:)Mh。好啊“…使用正确的数组方法,如splice。另外,不要在数组中使用…”谢谢,我匆忙编写了这些代码片段,我将修改问题代码