Document.createElement ne fonctionne pas

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

  • Uncaught TypeError: Invocation illégale

Dans Firefox

  • Erreur: NS_ERROR_XPC_BAD_CONVERT_JS: Impossible de convertir l'argument JavaScript

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:

http://jsfiddle.net/DeCNx/

 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