Disons que j'ai une options
variable et que je veux définir une valeur par défaut.
Quels sont les avantages / inconvénients de ces deux alternatives?
Utilisation de la propagation d'objets
options = {...optionsDefault, ...options};
Ou en utilisant Object.assign
options = Object.assign({}, optionsDefault, options);
C'est l' engagement qui m'a fait me demander.
javascript
ecmascript-6
Olivier Tassinari
la source
la source
Réponses:
Ce n'est pas nécessairement exhaustif.
Syntaxe de propagation
Avantages:
Si vous créez du code pour une exécution dans des environnements sans prise en charge native, vous pourrez peut-être simplement compiler cette syntaxe (par opposition à l'utilisation d'un polyfill). (Avec Babel, par exemple.)
Moins verbeux.
Désavantages:
Lorsque cette réponse a été écrite à l'origine, il s'agissait d'une proposition , non standardisée. Lorsque vous utilisez des propositions, tenez compte de ce que vous feriez si vous écrivez du code avec celui-ci maintenant et qu'il n'est pas standardisé ou ne change pas à mesure qu'il se dirige vers la standardisation. Cela a depuis été normalisé dans ES2018.
Littéral, pas dynamique.
Object.assign()
Avantages:
Standardisé.
Dynamique. Exemple:
Désavantages:
Ce n'est pas directement lié à ce que vous demandez. Ce code n'utilisait pas
Object.assign()
, il utilisait le code utilisateur (object-assign
) qui fait la même chose. Ils semblent compiler ce code avec Babel (et le regrouper avec Webpack), ce dont je parlais: la syntaxe que vous pouvez simplement compiler. Ils ont apparemment préféré cela à l'obligation d'inclureobject-assign
comme dépendance qui irait dans leur build.la source
Object.assign()
. Ou vous pouvez parcourir manuellement un tableau d'objets et leurs propres accessoires en les affectant manuellement à une cible et le rendre encore plus détaillé: PPour le reste / la répartition de l'objet de référence est finalisé dans ECMAScript 2018 comme étape 4. La proposition peut être trouvée ici .
Pour la plupart, la réinitialisation et la répartition des objets fonctionnent de la même manière, la principale différence est que la répartition définit les propriétés, tandis que Object.assign () les définit . Cela signifie que Object.assign () déclenche des setters.
Il convient de se rappeler qu'à part cela, le repos / propagation d'objet 1: 1 correspond à Object.assign () et agit différemment de la propagation de tableau (itérable). Par exemple, lors de la propagation d'un tableau, les valeurs nulles sont réparties. Cependant, l'utilisation de valeurs nulles réparties sur un objet est silencieusement répartie sur rien.
Exemple de propagation en tableau (itérable)
Exemple de propagation d'objet
Ceci est cohérent avec la façon dont Object.assign () fonctionnerait, les deux excluent silencieusement la valeur nulle sans erreur.
la source
Object.assign
utiliser des setters.Object.assign({set a(v){this.b=v}, b:2}, {a:4}); // {b: 4}
vs{...{set a(v){this.b=v}, b:2}, ...{a:4}}; // {a: 4, b: 2}
const x = {c: null};
. Dans ce cas, autant que je sache, nous verrions un comportement tout comme le tableau://{a: 1, b: 2, c: null}
.Je pense qu'une grande différence entre l'opérateur de diffusion et
Object.assign
qui ne semble pas être mentionnée dans les réponses actuelles est que l'opérateur de diffusion ne copiera pas le prototype de l'objet source vers l'objet cible. Si vous voulez ajouter des propriétés à un objet et que vous ne voulez pas changer de quelle instance il s'agit, alors vous devrez utiliserObject.assign
. L'exemple ci-dessous devrait le démontrer:la source
errorExtendedUsingAssign === error
maiserrorExtendedUsingSpread
c'est un nouvel objet (et le prototype n'a pas été copié).let target = Object.create(source); Object.assign(target, source);
Comme d'autres l'ont mentionné, à ce moment de la rédaction, il
Object.assign()
faut un polyfill et la propagation d'objet...
nécessite un transpilage (et peut-être aussi un polyfill) pour fonctionner.Considérez ce code:
Ces deux produisent la même sortie.
Voici la sortie de Babel, vers ES5:
Telle est ma compréhension jusqu'à présent.
Object.assign()
est en fait standardisé, alors que la propagation des objets...
ne l'est pas encore. Le seul problème est la prise en charge du navigateur pour les premiers et à l'avenir, les seconds aussi.Jouez avec le code ici
J'espère que cela t'aides.
la source
{}
devrait corriger l'incohérence.L'opérateur de propagation d'objet (...) ne fonctionne pas dans les navigateurs, car il ne fait pas encore partie d'une spécification ES, juste une proposition. La seule option est de le compiler avec Babel (ou quelque chose de similaire).
Comme vous pouvez le voir, c'est juste du sucre syntaxique sur Object.assign ({}).
Pour autant que je puisse voir, ce sont les différences importantes.
...
pour les objets n'est pas standardisé...
vous protège contre la mutation accidentelle de l'objet...
polyfill Object.assign dans les navigateurs sans elle...
a besoin de moins de code pour exprimer la même idéela source
Object.assign
, car l'opérateur de propagation vous donnera toujours un nouvel objet.Je voudrais résumer l'état de la fonctionnalité ES "fusion d'objets dispersés", dans les navigateurs et dans l'écosystème via des outils.
Spec
Navigateurs: dans Chrome, dans SF, Firefox bientôt (ver 60, IIUC)
Outils: Node 8.7, TS 2.1
Liens
Exemple de code (sert également de test de compatibilité)
Encore une fois: au moment de la rédaction de cet exemple, il fonctionne sans transpilation dans Chrome (60+), Firefox Developer Edition (préversion de Firefox 60) et Node (8.7+).
Pourquoi répondre?
J'écris ceci 2,5 ans après la question d'origine. Mais j'avais la même question, et c'est là que Google m'a envoyé. Je suis esclave de la mission de SO d'améliorer la longue queue.
Puisqu'il s'agit d'une extension de la syntaxe de «propagation de tableau», j'ai trouvé qu'il était très difficile de google, et difficile à trouver dans les tableaux de compatibilité. Le plus proche que j'ai pu trouver est Kangax "propagation de propriété" , mais ce test n'a pas deux spreads dans la même expression (pas une fusion). De plus, le nom dans les pages de propositions / brouillons / état du navigateur utilise tous "propriété répartie", mais il me semble que c'était un "premier principe" auquel la communauté est arrivée après les propositions d'utiliser la syntaxe répartie pour "fusion d'objets". (Ce qui pourrait expliquer pourquoi il est si difficile de google.) Je documente donc mes résultats ici afin que d'autres puissent afficher, mettre à jour et compiler des liens sur cette fonctionnalité spécifique. J'espère que ça va continuer. Aidez-nous à diffuser la nouvelle de son atterrissage dans la spécification et dans les navigateurs.
Enfin, j'aurais ajouté cette information en tant que commentaire, mais je n'ai pas pu les modifier sans casser l'intention originale des auteurs. Plus précisément, je ne peux pas modifier le commentaire de @ ChillyPenguin sans perdre son intention de corriger @RichardSchulte. Mais des années plus tard, Richard s'est avéré avoir raison (à mon avis). J'écris donc cette réponse à la place, en espérant qu'elle finira par gagner du terrain sur les anciennes réponses (cela pourrait prendre des années, mais c'est de cela qu'il s'agit après tout).
la source
REMARQUE: la propagation n'est PAS seulement du sucre syntaxique autour d'Object.assign. Ils fonctionnent très différemment en coulisses.
Object.assign applique des setters à un nouvel objet, Spread ne le fait pas. De plus, l'objet doit être itérable.
Copier Utilisez ceci si vous avez besoin de la valeur de l'objet telle qu'elle est en ce moment et que vous ne voulez pas que cette valeur reflète les modifications apportées par d'autres propriétaires de l'objet.
Utilisez-le pour créer une copie superficielle de l'objet bonne pratique pour toujours définir des propriétés immuables sur copier - parce que les versions mutables peuvent être passées en propriétés immuables, la copie garantira que vous aurez toujours affaire à un objet immuable
Assigner Assigner est quelque peu l'opposé de copier. Assign génère un setter qui affecte directement la valeur à la variable d'instance, plutôt que de la copier ou de la conserver. Lors de l'appel du getter d'une propriété assign, il renvoie une référence aux données réelles.
la source
Les autres réponses sont anciennes, impossible d'obtenir une bonne réponse.
L'exemple ci-dessous concerne les littéraux d'objets, explique comment les deux peuvent se compléter et comment ils ne peuvent pas se compléter (donc la différence):
Plusieurs autres petits exemples ici, également pour tableau et objet:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
la source
Cela fait maintenant partie d'ES6, est donc normalisé et est également documenté sur MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
Il est très pratique à utiliser et a beaucoup de sens à côté de la déstructuration d'objets.
Le dernier avantage répertorié ci-dessus est les capacités dynamiques d'Object.assign (), mais cela est aussi simple que de répartir le tableau à l'intérieur d'un objet littéral. Dans la sortie babel compilée, il utilise exactement ce qui est démontré avec Object.assign ()
Donc, la bonne réponse serait d'utiliser la diffusion d'objets car elle est désormais standardisée, largement utilisée (voir react, redux, etc.), est facile à utiliser et possède toutes les fonctionnalités d'Object.assign ()
la source
Je voudrais ajouter cet exemple simple lorsque vous devez utiliser Object.assign.
Cela peut ne pas être clair lorsque vous utilisez JavaScript. Mais avec TypeScript, il est plus facile de créer une instance d'une classe
la source