Je crée un plugin en utilisant la bibliothèque jQuery.
Ici, je stocke String.prototype dans une variable puis j'utilise cette variable pour étendre mon objet Sting. Et cela fonctionne bien.
// String Prototyping store in a variable // Save bytes in the minified version of js var StrProto = String.prototype; String.prototype.toProperCase = function () { return this.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); }; // working fine alert("yogesh kumar".toProperCase());
Dans le cas suivant, je crée la fonction m xyz qui est stockée en variable abc et cela fonctionne aussi bien.
function xyz(x){ alert(x) } var abc = xyz; // working fine abc("yogesh kumar");
Dans le dernier cas, je stocke document.createElement dans une balise variable et j'utilise une balise pour créer un bouton. mais ça ne fonctionne pas.
var tag=document.createElement; $(document.createElement("button")).html("document.Element").appendTo("#myDiv"); // not working $(tag("button")).html("tag").appendTo("#myDiv");
Veuillez vérifier le lien sur jsFiddle:
cliquez ici
Erreur:
En Chrome
Dans Firefox
Pourquoi cette erreur?
Quelle est la solution?
Vous obtenez une référence à une fonction qui est membre du document. Lorsque vous appelez directement cette référence, son contexte est maintenant la fenêtre plutôt que le document. Voici un exemple:
var foo = { createElement: function(tagname) { if (this._secretvarthatisneeded) { console.log(tagname + " Element Created!"); } }, _secretvarthatisneeded: true } foo.createElement("FOOBAR"); // works var bar = foo.createElement; bar("BARFOO"); // doesn't work bar.call(foo,"BARBAR") // works
Comme le contexte a été perdu, l'appel bar()
n'a pas abouti à une console.log();
Évidemment, ce n'est qu'une simplification à démontrer.
Mise à jour: pour l'utilisation que vous faites, je suggérerais de le faire:
$.createElement = function(tagName,attributes){ return $( document.createElement(tagName), attributes ? attributes : {} ) }
Maintenant, vous pouvez simplement $.createElement("button").html("tag").appendTo("#myDiv");
Il est rapide et toujours facile à lire. Notez cependant que IE a des problèmes avec les entrées, si vous créez des éléments de saisie, je suggère d'utiliser $("<input type='text' />")
plutôt que cela.
JQuery peut créer de nouveaux éléments pour vous aussi simple que:
$("<button />").html("document.Element").appendTo("#myDiv");
Pour avoir une raison pour laquelle votre approche ne fonctionne pas, lisez le commentaire de @ Kevin ci-dessous.
Utilisez la méthode bind()
pour "affecter" la méthode JS native à une variable:
var ce = document.createElement.bind(document); var elem = ce('div'); alert(elem.nodeName);
Fonctionne dans des navigateurs modernes, y compris IE9 +. Pour les navigateurs plus anciens, utilisez une fonction wrapper.
Cela se produit car document.createElement
utilise this
intérieur. Lorsque vous l'appelez comme document.createElement()
this
dépend du document
. Mais, lorsque vous l'enregistrez en tant que variable, this
n'est plus un document
, c'est une window
.
Vous devez l'appeler avec le contexte.
var tag = document.createElement; // you are saving the function, not its context var btn = tag.call(document, 'button'); // you need to set the context
Si votre navigateur le prend en charge, vous pouvez également utiliser .bind
:
var tag = document.createElement.bind(document); var btn = tag('button');
La raison de cette erreur est que la méthode a perdu son contexte. La méthode createElement()
doit être appelée dans le contexte d'un objet document
.
Essayez ceci dans une console:
var tag = document.createElement; tag.call(document, "div"); // no error tag("div"); // error
Les détails spécifiques de pourquoi createElement()
doivent être appelés dans le contexte du document
sont spécifiques à la mise en œuvre, mais peuvent être facilement devinés.
Donc, pour maintenir le contexte, créez un wrapper de fonction pour document.createElement()
:
function tag(tagName) { return document.createElement(tagName); }
Bien sûr, jQuery va également créer des éléments pour vous:
$("<div>"); // new div element