Prototypage objet en Javascript casse jQuery?
-
11-09-2019 - |
Question
J'ai ajouté un simple fichier .js
à ma page qui a une sorte de-tâche commune assez banale des fonctions ajoutées aux prototypes de Object
et Array
.
Par essais et erreurs, j'ai compris que l'ajout d'une fonction à Object.prototype
, peu importe son nom ou ce qu'il fait provoque des erreurs javascript jQuery:
Le coupable?
Object.prototype.foo = function() {
/*do nothing and break jQuery*/
};
L'erreur que je reçois la ligne 1056 de jquery-1.3.2.js
, dans la attr: fonction {} déclaration:
/*Object doesn't support this property or method*/
name = name.replace(/-([a-z])/ig, function(all, letter) {
return letter.toUpperCase();
});
Apparemment G.replace est indéfini.
Alors il est évident qu'il ya quelque chose que je ne suis pas envelopper ma tête avec le prototypage, j'échoue lamentablement à comprendre ce qu'il est.
Pour être clair, je ne suis pas à la recherche d'une solution, je ... qui a traité ce que je suis à la recherche est une réponse à Pourquoi? . Pourquoi ajouter une fonction à Object.prototype
briser ce morceau de code?
La solution
Vous ne devriez jamais étendre Object.prototype
. Il fait beaucoup plus que briser jQuery; il se casse complètement la fonction de Javascript « objet-en-hashage ». Ne pas le faire.
Vous pouvez demander à John Resig, et il vous dira même chose .
Autres conseils
Si c'est tout simplement un cas de déconner pour ... en boucle, ne pouvez-vous utiliser Object.defineProperty pour ajouter votre fn sans en faire dénombrable?
Object.defineProperty(Object.prototype, "foo", {
value: function() {
// do stuff
},
enumerable : false
});
Semble travailler pour moi. Serait-ce encore être considéré comme une mauvaise forme?
Je suis d'accord, ajouter quelque chose à Object.prototype
exige une attention et devrait être évitée. Cherchez d'autres solutions telles que:
Ajout à objet, puis d'y accéder avec un call
ou apply
, au besoin.
Par exemple:
Object.foo = function () { return this.whatever()}
Ensuite, appelez que sur un objet par:
Object.foo.call(Objname); // this invokes the function as though it were a
// method of Objname. That is, its like Objname.foo()
Pour le plaisir, vous pouvez ajouter ce qui suit (oui, je sais que un peu dangereux ...):
Function.using = Function.call; // syntactic sugar
Maintenant, vous pouvez écrire Object.foo.using(Objname)
et il se lit comme un Sentance.
Mais en règle générale, rester à l'écart de modifier l'un des grands prototypes.
Je me suis cogné la tête autour de ce problème que je voulais mettre en œuvre l'orientation de l'objet « réel » dans tous mes objets, comme ceci:
interface Object
{
GetType: () => string;
ToString: () => string;
GetHashcode: () => number;
Equals: (obj: any) => boolean;
}
Depuis casse Object.prototype JQuery, je DEFAILLANTE à la solution mentionnée ci-dessus à utiliser DefineProperty mais qui ne prend pas d'arguments.
Les bonnes nouvelles sont que vous pouvez pirater DefineProperty et accepter en fait des paramètres. Voici mon implémentation:
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
});
Cela fonctionne et ne pas en conflit avec JQuery.
Je doute l'ajout d'une fonction de casse Object.prototype jQuery directement. Assurez-vous que chaque boucle for..in vous avez tout au long de votre site est enveloppé dans un chèque de hasOwnProperty, puisque vous avez ajouter la fonction à l'échelle mondiale et le résultat de itérez peut être imprévisible:
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
}}