Prototyping Object in JavaScript Breaks Jquery

Prototyping Object in Javascript breaks jQuery?

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.

Object Prototype Function Breaking in jQuery

By passing a value to the descriptor, you've just overwritten the method with that empty function (which is the one doing nothing and returning undefined). If you really want to define a method on Object.prototype (which you absolutely should not do), you'd need to use

Object.defineProperty(Object.prototype, 'multiparter', {
value: function(route) {
return route.reduce(function(newObj, key) {
return newObj[key]
}, this);
},
enumerable: false,
configurable: true
});

object.prototype breaking javascript

Extending built-in prototypes is bad practice. It can break scripts that expect that doesn't happen, such as jQuery.

There is no reason for you to do this. Create a normal function instead:

function getKey(obj, value) {
// ...
}

and use getKey(playlistids, playing) instead of playlistids.getKey(playing).

Why does this JavaScript prototype function break jQuery?

Because this is going to add an enumerable item to every single object. Sizzle (which jQuery uses) uses object literals to configure their selector parsing. When it loops these config objects to get all tokens, it doesn't expect your function. In this case, it's probably trying to use your function as a RegExp.

Imagine this scenario:

var obj = { a: 1, b: 2, c: 3 };
var result = 0;
for (var prop in obj) {
// On one of these iterations, `prop` will be "allKeys".
// In this case, `obj[prop]` will be a function instead of a number.
result += obj[prop] * 2;
}
console.log(result);

If you have added anything to Object's prototype that can't be used as a number, you will get NaN for your result.

A good solution to this problem is to add the allKeys function to Object instead of Object.prototype. This mimics Object.keys:

Object.allKeys = function (obj) {
var keys = [];
for (var key in obj)
{
// Very important to check for dictionary.hasOwnProperty(key)
// otherwise you may end up with methods from the prototype chain..
if (obj.hasOwnProperty(key))
{
keys.push(key);
//alert(key);
} // End if (dict.hasOwnProperty(key))

} // Next key

keys.sort();
return keys;
}; // End Extension Function allKeys

jQuery conflict with native prototype

You can avoid these problems by making your extensions to the native prototypes as non-enumerable:

Object.defineProperty(Object.prototype, 'myVeryGreatFunction',{
value : function() {},
enumerable : false
});

Object.defineProperty documentation on MDN

As Jan Dvorak mentioned, this solution does not work for old browsers (IE8-).

jQuery error when extending object prototype

In this report they say they don't want to fix that. So don't use Object.prototype when working with jquery.

Assigning Object.prototype causes issues with jQuery

Don't monkey patch Object.prototype.

Object.prototype.replace = "lol";

for (var i in { "bar": 42 }) {
alert(i);
}
// "bar"
// "replace" :(

Basically for ... in loops iterate over all properties in an object including ones defined on the prototype. This is why it's really bad practice to extend or change Object.prototype.

Some people also go as far as "Don't monkey patch Array, String, Function, ...".

You should never mess with the Object.prototype. The rest of the native prototypes are a style choice.

Define your function on Object.

Object.replace = function() { ... };

var o = Object.replace(p);

ES5:

With ecmascript 5 you can set properties as non-enumerable

Object.defineProperty(Object.prototype, "replace", {
value: function() { }
});

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

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 recommend 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.

Alternative methods for extending object.prototype when using jQuery

By not including the descriptor in Object.defineProperty(obj, prop, descriptor) JavaScript defaults all the Boolean descriptor attributes to false. Namely
writable, enumerable, and configurable. Your new property is hidden from the for in iterators because your _init property is enumerable:false.

I am not a fan of JQuery so will not comment on why in regard to JQuery

There is no absolute rule to adding properties to JavaScript's basic type and will depend on the environment that your code is running. Adding to the basic type will add it to the global namespace. If your application is sharing the namespace with 3rd party scripts you can potentially get conflicts, causing your code or the third party code or both to fail.

If you are the only code then conflicts will not be an issues, but adding to object.prototype will incur an addition overhead on all code that uses object.

I would strongly suggest that you re examine the need for a global _init. Surely you don't use it every time you need a new object. I am a fan of the add hock approach to JavaScript data structures and try to keep away from the formal OOP paradigms

JS Object this.method() breaks via jQuery

The identity of this is a common problem in javascript. It would also break if you tried to create a shortcut to doSomething:

var do = Bob.doSomething;
do(); // this is no longer pointing to Bob!

It's good practice to not rely on the identity of this. You can do that in a variety of ways, but the easiest is to explicitly reference Bob instead of this inside of doSomething. Another is to use a constructor function (but then you lose the cool object-literal syntax):

var createBob = function() {
var that = {};

that.Stuff = '';
that.init = function() {
that.Stuff = arguments[0];
};

that.doSomething = function() {
console.log( that.Stuff );
};

return that;
}

var bob = createBob();


Related Topics



Leave a reply



Submit