English 中文(简体)
Prototyping Object in Javascript breaks jQuery?
原标题:

I have added a simple .js file to my page that has some pretty mundane common-task sort of functions added to the Object and Array prototypes.

Through trial and error, I ve figured out that adding any function to Object.prototype, no matter it s name or what it does causes Javascript errors in jQuery:

The culprit?

Object.prototype.foo = function() {
    /*do nothing and break jQuery*/
};

The error I m getting line 1056 of jquery-1.3.2.js, in the attr:function { } declaration:

/*Object doesn t support this property or method*/
name = name.replace(/-([a-z])/ig, function(all, letter) {
            return letter.toUpperCase();
        });

Apparently G.replace is undefined.

While it s obvious that there s something I m just not wrapping my head around with prototyping, I m failing miserably to figure out what it is.

To be clear, I m not looking for a workaround, I have that handled... what I m looking for is an answer to Why?. Why does adding a function to Object.prototype break this bit of code?

最佳回答

You should never extend Object.prototype. It does far more than break jQuery; it completely breaks the "object-as-hashtables" feature of Javascript. Don t do it.

You can ask John Resig, and he ll tell you the same thing.

问题回答

If it s simply a case of messing up for...in loops, can t you use Object.defineProperty to add your fn without making it enumerable?

So:

Object.defineProperty(Object.prototype, "foo", { 
    value: function() {
        // do stuff
    },
    enumerable : false
});

Seems to work for me. Would this still be considered bad form?

I agree, adding something to Object.prototype demands caution and should be avoided. Look for other solutions such as:

Adding it to Object and then accessing it with a call or apply, as needed. For example:

Object.foo = function () { return this.whatever()}

Then call that on an object by:

Object.foo.call(Objname);  // this invokes the function as though it were a
                           // method of Objname.  That is, its like Objname.foo()

For fun, you can add the following (yes, I know its a bit dangerous...):

Function.using = Function.call; // syntactic sugar

Now you can write Object.foo.using(Objname) and it reads like a sentance.

But as a rule, stay away from altering any of the big prototypes.

I banged my head around this problem as I wished to implement "real" object orientation in all of my objects, like this:

interface Object
{
    GetType: () => string;
    ToString: () => string;
    GetHashcode: () => number;
    Equals: (obj: any) => boolean;
}

Since Object.prototype breaks JQuery, I defaulted to the abovementioned solution to make use of defineProperty but that does not take any arguments.

The good news is that you can hack into defineProperty and actually accept parameters. Here is my implementation:

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
    });

This works and does not clash with JQuery.

I doubt adding a function to Object.prototype breaks jQuery directly. Just make sure each for..in loop you have throughout your site is wrapped in a hasOwnProperty check, since you ve add the function globally and the result of iterating over it can be unpredictable:

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
}}




相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签