我试图将一个length()方法原型化为Object并打破jQuery - 怎么样?

时间:2010-04-14 15:00:26

标签: javascript jquery prototype object methods

我写了以下内容:

Object.prototype.length = function(){
    var count = -1;
    for(var i in this) count++;
    return count;
}

有效。但是当我执行我的页面时,即使不使用这个函数,Firebug告诉我jQuery的.appendTo()不再是一个函数。为什么会这样?

2 个答案:

答案 0 :(得分:7)

该原型扩展正在破坏$.each方法,因为此方法使用length属性(在jQuery 1.4.2中)检测数组和对象之间:

// core.js Line 533
each: function( object, callback, args ) {
    var name, i = 0,
        length = object.length, // <--- your function from Object.prototype
        isObj = length === undefined || jQuery.isFunction(object);
//...

如您所见,isObj变量只有在不包含length属性(或属性值为undefined)时才会为真。

如果isObj为false,jQuery将尝试使用普通for循环进行迭代:

for ( var value = object[0];
    i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}

然后,appendTo方法是使用$.each创建的,这就是为什么没有定义:

//...
jQuery.each({
    appendTo: "append",
    prependTo: "prepend",
    insertBefore: "before",
    insertAfter: "after",
    replaceAll: "replaceWith"
},
//...

我将始终建议远离扩展Object.prototype,当您扩展此原型时所有对象会接收这些附加属性。

这是特别有问题的,因为当您迭代对象的属性时 这些新属性出现,导致各种意外行为。

答案 1 :(得分:4)

这可能是因为jQuery的.appendTo(间接)依赖Object.length,它是用JavaScript构建的,并不是一个函数。
如果您确实要将该方法添加到Object,请将其称为不会干扰预先存在的方法的内容;类似objLength或obj_length(或其他)的东西 您也可以执行类似的操作来检查要添加到对象的属性是否已存在于该对象中(直接从Crockford解除):

Object.prototype.method = function (name, func) {
    if (!this.prototype[name]){
        this.prototype[name] = func;
        return this;
    }
};

并像这样应用你的功能:

Object.method('myLength', function () {
    var count = -1;
    for (var i in this) {
        count += 1;
    }
    return count;
});

我知道我的循环在整个声明中有括号,但它提高了可读性和可维护性。我听说这些都是好事。