28 votes

Existe-t-il un moyen à l'épreuve du temps d'ajouter des propriétés aux objets du navigateur natif avec un comportement "utiliser strict"?

J'ai remarqué récemment que lorsqu' "use strict"; mode dans les navigateurs de nombreuses propriétés sur les objets deviennent unsettable.

Par exemple

function() {
  "use strict";
  var div = document.createElement("div");
  div.offsetLeft = 0;  
}();

Ignorer le fait que la fixation d' offsetLeft est stupide. Ce n'est pas le point.

Si vous exécutez ce code dans Chrome ou Firefox, vous recevrez un message d'erreur

Uncaught TypeError: Cannot set property offsetLeft of #<HTMLElement> which has only
a getter(…)

Supprimer l' "use strict"; et l'erreur disparaît.

Alors, voici le problème. Changeons offsetLeft de quelque chose que je pourrais utiliser dans mon propre code

function createElementAndAssociateData(data) {
  "use strict";
  var div = document.createElement("div");
  div.userdata = data;  
};

Cela fonctionne très bien, à l'exception de 2 ans à partir d'un nouveau spec HTML5 arrive et décide que tous les Élémentshtml ont userdata attribut en lecture seule. Tout à coup, mon code s'arrête partout, j'ai utilisé "use strict";.

Est-ce une bombe à retardement, car de plus en plus de propriétés sont ajoutées à HTML5 native des objets?

Est-il un moyen sûr d'utiliser "use strict"; et d'ajouter des propriétés personnalisées natif HTML5 objets ou devrait l'ajout de tout type de biens à un natif du navigateur d'objet ne jamais être fait?

Remarque: je ne crois pas obfusticating les noms de propriété est une solution acceptable. Sûr que je pourrais changer d' userdata de mycompanyname_myappname_userdata mais c'est un peu à côté de la question. Est-il une autre solution ou est l'ajout de propriétés personnalisées natif HTML5 objets en mode strict, un anti-modèle?

21voto

Oriol Points 20803

Oui: ES6 symboles

Le problème avec les propriétés, c'est que leur nom est une chaîne de caractères. Ensuite, deux codes différents peuvent choisir d'utiliser le même nom pour des raisons différentes, et le résultat peut être désastreux.

Pour résoudre ce problème, ECMAScript 6 introduit un nouveau type: le Symbole.

Vous pouvez l'utiliser comme ceci:

var s1 = Symbol("My property");
object[s1] = "Some data 1";
object[s1]; // "Some data 1"

Alors, même si d'autres codes décide d'utiliser un symbole avec la même description, il n'y aura pas de collision:

var s2 = Symbol("My property"); // Same description :S
object[s2] = "Some data 2";
object[s2]; // "Some data 2"
object[s1]; // "Some data 1" -- No problem :)

8voto

Xufox Points 3719

La manière prévue d'ajouter des propriétés personnalisées est avec HTMLElement.dataset .

 var div = document.createElement("div");
div.dataset.yourCustomProperty = 'some data';
div; // <div data-your-custom-property="some data">
div.dataset.yourCustomProperty; // "some data"
 

Cela reflète les attributs personnalisés data-* .

Notez que .dataset.camelCase reflète data-camel-case et vice versa.

8voto

alexander farkas Points 3450

En général, votre code peut également se briser si vous retirez - "use strict";, parce que votre bien n'a pas la valeur que vous désirez avoir.

En général, l'extension des objets natifs est pas une si bonne idée.

Voici quelques options:

  1. Utiliser un nom espacés de clé par exemple _myframeworkElemID, ce n'est pas spécifié.

  2. Créer une dynamique de clé (similaire à la 1.): jQuery par exemple crée une clé comme ceci: $.expando = 'jQuery' + Date.now();

  3. Utilisation de jQuery.de données ou de mettre en œuvre une solution similaire.

  4. des moyens modernes

    a) les Symboles (couverts dans cette réponse)

    b) WeakMap:

window.elementData = new WeakMap();

//later than
//set data
elementData.set(element, data)

//get data
elementData.get(element);

Tout cela est dit. De mon point de vue la actuellement la meilleure façon de le faire, il ressemble à ceci:

var expando = window.Symbol && Symbol() || '_myId' + Date.now();

//set data
element[expando] = data;

//get data
var data = element[expando];

De cette façon, vous utilisez l'ES6 Symbole de fonction dans les navigateurs qui le supportent et dans les anciens navigateurs, vous obtenez une chaîne unique, qui ne sera jamais spécifié.

Bien sûr, vous pouvez également écrire un helper, qui renvoie le symbole.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X