最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - I tried to prototype a length() method to Object and broke jQuery – how? - Stack Overflow

programmeradmin0浏览0评论

I wrote the following:

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

It works. But when I execute my page, even without using this function, Firebug tells me that jQuery's .appendTo() is no longer a function. Why would this be?

I wrote the following:

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

It works. But when I execute my page, even without using this function, Firebug tells me that jQuery's .appendTo() is no longer a function. Why would this be?

Share Improve this question asked Apr 14, 2010 at 15:00 BarneyBarney 631 silver badge5 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

That prototype extension is breaking the $.each method, because this method detects between arrays and objects using the length property (in 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);
//...

As you can see, the isObj variable will be true only if it doesn't contains a length property (or the property value is undefined).

If isObj is false, jQuery will try to iterate using a normal for loop:

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

Then, the appendTo method is created using $.each, that's why is not defined:

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

I will always remend to stay away from extending Object.prototype, when you extend this prototype ALL objects receive those additional properties.

This is especially problematic since when you iterate over the properties of the object these new properties appear, causing all sorts of unexpected behavior.

It's probably because jQuery's .appendTo depends (indirectly) on Object.length, which is builtin in JavaScript, and isn't a function.
If you really want to add that method to Object, call it something that won't interfere with pre-existing methods; something like objLength or obj_length (or whatever).
You can also do something like this to check if the attribute you want to add to an object already exists for that object (lifted straight from Crockford):

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

And apply your function like so:

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

And I know my loop has brackets around a whole one statement, but it improves readability and maintainability. I have heard those are good things.

发布评论

评论列表(0)

  1. 暂无评论