0

我有一个基本上是原生 Javascript 数组的类,但它会在添加或删除项目时引发事件。

hb.extend( {
Classes: {
    Collection: hbClass.inherit({
        init: function (arr) {
            // get the functions we want to retain
            var _on = this.on,
                _trigger = this.trigger,
                _push = this.push,
                _remove = this.remove,
                _reset = this.reset,
                _from = this.fromArray,
                _watch = this.watch;

            // Set the object up as an Array
            this.__proto__ = Array.prototype;

            // get the Array functions we want to use
            this.arrPush = this.push;

            // reapply the old functions
            this.push = _push;
            this.remove = _remove;
            this.reset = _reset;
            this.fromArray = _from;
            this.on = _on;
            this.trigger = _trigger;
            this.watch = _watch;

            if (arr && (arr.length && typeof arr !== "string")) this.fromArray(arr, true);
        },

        fromArray: function (arr, stopEvent) {
            this.reset();
            for (var i = 0, len = arr.length; i < len; i++) {
                this.arrPush(arr[i]);
            }
            if (!stopEvent) this.trigger('change', this);
        },

        push: function () {
            this.arrPush.apply(this, arguments);
            this.trigger('add', this);
            this.trigger('change', this);
            return this;
        },

        remove: function (from, to) {
            var rest = this.slice((to || from) + 1 || this.length);
            this.length = from < 0 ? this.length + from : from;

            this.arrPush.apply(this, rest);
            this.trigger('remove', this);
            this.trigger('change', this);
            return this;
        },

        reset: function () {
            this.length = 0;
            this.trigger('change', this);
            this.trigger('remove', this);
        }
    })
}
});

可能有更好的方法来做到这一点,但它适用于我.......除了在 IE 中。
在 IE 中的方法this.arrPush.appy(this, arguments);下的行中push,它会遇到 Stack Overflow 错误。
具体来说:

SCRIPT28:堆栈空间不足

但这不会发生在 Firefox 或 Chrome 中。
有人有什么建议吗?
编辑
触发代码:

this.hbClass.prototype.trigger = function(type, data, context) {
    var listeners, handlers, i, n, handler, scope;
    if (!(listeners = this.listeners)) {
        return;
    }
    if (!(handlers = listeners[type])){
        return;
    }
    for (i = 0, n = handlers.length; i < n; i++){
        handler = handlers[i];

        if (handler.method.call(
            handler.context, this, type, data
        )===false) {
            return false;
        }
    }
    return true;
}
4

1 回答 1

1

问题可能是这一行:

this.__proto__ = Array.prototype;

__proto__某些版本的 IE 不支持as 。它已被编入 ES6 规范,但在某些版本的 IE 中并未实现。我不完全了解您的代码是如何工作的,但是设置原型的安全方法是这样的:

工作演示:http: //jsfiddle.net/jfriend00/ff99G/

function myClass() {
    // add new methods to this instance in the constructor
    this.fromArray = function() {};
};
// become an array and get all its methods
myClass.prototype = Array.prototype;


var x = new myClass();

.prototype这是您在 IE 中使用的那种事情的示例:

function log(msg) {
    var result = document.getElementById("result");
    var div = document.createElement("div");
    div.innerHTML = msg;
    result.appendChild(div);
}

function myClass() {
    var _push = this.push;
    this.count = function() {
        return this.length;
    }
    this.trigger = function(type, name) {
        var str = type;
        if (name) {
            str += ", " + name;
        }
        log(str);
    }
    this.push = function() {
        var retVal = _push.apply(this, arguments);
        this.trigger("change", "push");
        return retVal;
    }
};

// become an array and get all its methods
myClass.prototype = Array.prototype;


var x = new myClass();

x.push("foo");
x.push("whatever");
log(x.count());
于 2013-01-18T16:25:36.147 回答