我在页面中添加了一个简单的.js
文件,其中添加了一些非常普通的常见任务类型的函数添加到Object
和Array
原型中。
通过反复试验,我发现将任何函数添加到Object.prototype
,无论它的名称或它的作用是什么导致jQuery中的Javascript错误:
罪魁祸首?
Object.prototype.foo = function() {
/*do nothing and break jQuery*/
};
错误我在attr:function {}声明中获得了jquery-1.3.2.js
的第1056行:
/*Object doesn't support this property or method*/
name = name.replace(/-([a-z])/ig, function(all, letter) {
return letter.toUpperCase();
});
显然G.replace未定义。
虽然很明显有一些事情我只是没有用原型设计来解决问题,但我很难弄清楚它是什么。
要说清楚,我不是在寻找一种解决方法,我已经处理好了......我正在寻找的是为什么?的答案。为什么向Object.prototype
添加一个函数会破坏这段代码?
答案 0 :(得分:41)
如果它只是一个搞乱......循环的情况,你不能使用Object.defineProperty添加你的fn而不使它可枚举吗?
所以:
Object.defineProperty(Object.prototype, "foo", {
value: function() {
// do stuff
},
enumerable : false
});
似乎适合我。这还会被认为是不好的形式吗?
答案 1 :(得分:20)
你永远不应该延长Object.prototype
。它不仅仅是打破jQuery;它彻底打破了Javascript的“object-as-hashtables”功能。不要这样做。
你可以问John Resig,他会告诉你same thing。
答案 2 :(得分:5)
我同意,在Object.prototype
添加一些内容需要谨慎,应该避免。寻找其他解决方案,例如:
将其添加到Object,然后根据需要使用call
或apply
访问它。
例如:
Object.foo = function () { return this.whatever()}
然后通过以下方式在对象上调用它:
Object.foo.call(Objname); // this invokes the function as though it were a
// method of Objname. That is, its like Objname.foo()
为了好玩,你可以添加以下内容(是的,我知道它有点危险......):
Function.using = Function.call; // syntactic sugar
现在你可以写Object.foo.using(Objname)
,它看起来像是一个遗产。
但作为一项规则,远离改变任何大型原型。
答案 3 :(得分:1)
我想解决这个问题,因为我希望实施"真正的"我所有对象中的面向对象,如下所示:
interface Object
{
GetType: () => string;
ToString: () => string;
GetHashcode: () => number;
Equals: (obj: any) => boolean;
}
由于Object.prototype打破了JQuery,我默认使用了上面提到的解决方案来使用defineProperty,但是没有任何参数。
好消息是你可以入侵defineProperty并实际接受参数。这是我的实施:
Object.defineProperty(Object.prototype, "Equals",
{
value: function (obj: any)
{
return obj == null && this == null
? true
: obj != null && this == null
? false
: obj == null && this != null
? false
: this.GetHashcode() == obj.GetHashcode();
},
enumerable: false
});
这有效,并且不与JQuery冲突。
答案 4 :(得分:-1)
我怀疑向Object.prototype添加一个函数会直接破坏jQuery。只需确保整个站点中的每个for..in循环都包含在hasOwnProperty检查中,因为您已经全局添加了该函数,并且迭代它的结果可能是不可预测的:
Object.prototype.foo = function() {};
var myObject = {m1: "one", m2: "two" };
for(var i in myObject) { if(myObject.hasOwnProperty(i)) {
// Do stuff... but not to Object.prototype.foo
}}