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

我写了以下内容:

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

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

该原型扩展正在破坏$.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 )时才为true。

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

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

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

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

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

这尤其成问题,因为当您迭代对象的属性时,会出现这些新属性,从而导致各种意外行为。

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

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

并像这样应用你的function:

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

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