Les types primitifs (nombre, chaîne, etc.) sont transmis par valeur, mais les objets sont inconnus, car ils peuvent tous deux être transmis par valeur (dans le cas où nous considérons qu'une variable contenant un objet est en fait une référence à l'objet ) et passé par référence (quand on considère que la variable de l'objet contient l'objet lui-même).
Bien que cela n'ait pas vraiment d'importance à la fin, je veux savoir quelle est la bonne façon de présenter les arguments en passant les conventions. Existe-t-il un extrait de la spécification JavaScript, qui définit quelle devrait être la sémantique à ce sujet?
javascript
pass-by-reference
pass-by-value
Danail Nachev
la source
la source
var x=3, y=x; f(x); alert(y === x);
alors la fonctionf()
peut faire le rapport d'alertefalse
et nontrue
. En JavaScript, ce n'est pas possible, donc ce n'est pas un passage par référence. C'est bien qu'il soit possible de passer des références à des objets modifiables, mais ce n'est pas ce que signifie "passer par référence". Comme je l'ai dit, c'est dommage que la terminologie soit si confuse.Réponses:
C'est intéressant en JavaScript. Considérez cet exemple:
Cela produit la sortie:
obj1
ne s'agissait pas du tout d'une référence, la modificationobj1.item
n'aurait aucun effet sur l'obj1
extérieur de la fonction.num
serait100
, etobj2.item
lirait"changed"
.Au lieu de cela, la situation est que l'élément transmis est transmis par valeur. Mais l'élément passé par valeur est lui - même une référence. Techniquement, cela s'appelle appel par partage .
Concrètement, cela signifie que si vous modifiez le paramètre lui-même (comme avec
num
etobj2
), cela n'affectera pas l'élément qui a été introduit dans le paramètre. Mais si vous modifiez les INTERNES du paramètre, cela se propagera (comme avecobj1
).la source
item
propriété de l'objet référencé par obj1, vous modifiez la valeur de la propriété d'élément qui était initialement définie sur "inchangée". Lorsque vous attribuez à obj2 une valeur de {item: "changed"}, vous changez la référence à un nouvel objet (qui sort immédiatement de la portée lorsque la fonction se termine). Il devient plus évident ce qui se passe si vous nommez les paramètres de fonction comme numf, obj1f et obj2f. Ensuite, vous voyez que les paramètres masquaient les noms var externes.ref
mot clé.) Habituellement, la fonction renvoie simplement le nouvel objet et fait l'affectation au point où vous appelez la fonction. Par exemple,foo = GetNewFoo();
au lieu deGetNewFoo(foo);
var obj1 = { item: 'unchanged' }; var obj2 = obj1; obj2.item = 'changed';
et observer le même effet que dans votre exemple. Par conséquent, je renvoie personnellement la réponse de Tim GoodmanElle passe toujours par valeur, mais pour les objets, la valeur de la variable est une référence. Pour cette raison, lorsque vous passez un objet et modifiez ses membres , ces modifications persistent en dehors de la fonction. Cela rend l' air comme passe par référence. Mais si vous modifiez réellement la valeur de la variable objet, vous verrez que la modification ne persiste pas, prouvant qu'elle passe vraiment par la valeur.
Exemple:
Production:
la source
changeObject
, j'ai changéx
pour contenir une référence au nouvel objet.x = {member:"bar"};
est équivalent àx = new Object(); x.member = "bar";
ce que je dis est également vrai de C #, soit dit en passant.ref
mot clé que vous pouvez passer la référence par référence ( au lieu de la valeur par défaut de passer la référence en valeur), puis le changement du point ànew Object()
vous persister .La variable ne "tient" pas l'objet; il détient une référence. Vous pouvez affecter cette référence à une autre variable, et maintenant les deux référencent le même objet. C'est toujours passer par valeur (même lorsque cette valeur est une référence ...).
Il n'y a aucun moyen de modifier la valeur détenue par une variable passée en paramètre, ce qui serait possible si JavaScript supportait le passage par référence.
la source
Mes deux cents ... C'est ainsi que je le comprends. (N'hésitez pas à me corriger si je me trompe)
Il est temps de jeter tout ce que vous savez sur le passage par valeur / référence.
Parce qu'en JavaScript, peu importe qu'il soit passé par valeur ou par référence ou autre. Ce qui compte, c'est la mutation vs l'affectation des paramètres passés dans une fonction.
OK, laissez-moi faire de mon mieux pour expliquer ce que je veux dire. Disons que vous avez quelques objets.
Ce que nous avons fait, c'est "affectation" ... Nous avons affecté 2 objets vides séparés aux variables "objet1" et "objet2".
Maintenant, disons que nous aimons mieux object1 ... Donc, nous "assignons" une nouvelle variable.
Ensuite, pour une raison quelconque, nous décidons que nous aimons mieux l'objet 2. Donc, nous faisons simplement une petite réaffectation.
Rien n'est arrivé à object1 ou à object2. Nous n'avons modifié aucune donnée. Tout ce que nous avons fait, c'est de réaffecter notre objet préféré. Il est important de savoir que object2 et favoriteObject sont tous deux affectés au même objet. Nous pouvons changer cet objet via l'une de ces variables.
OK, regardons maintenant les primitives comme les chaînes par exemple
Encore une fois, nous choisissons un favori.
Nos variables favoriteString et string1 sont affectées à «Hello world». Et maintenant, si nous voulons changer notre chaîne favorite ??? Que va-t-il se passer ???
Euh oh .... Qu'est-ce qui s'est passé. Nous ne pouvions pas changer string1 en changeant favoriteString ... Pourquoi ?? Parce que nous n'avons pas changé notre objet chaîne . Tout ce que nous avons fait, c'est "RE ASSIGNER" la variable favoriteString à une nouvelle chaîne. Cela l'a essentiellement déconnecté de string1. Dans l'exemple précédent, lorsque nous avons renommé notre objet, nous n'avons rien attribué. (Eh bien, pas à la variable elle - même , ... nous avons cependant assigné la propriété name à une nouvelle chaîne.) Au lieu de cela, nous avons simplement muté l'objet qui conserve les connexions entre les 2 variables et les objets sous-jacents. (Même si nous avions voulu modifier ou muter l'objet chaîne lui-même, nous ne pourrions pas l'avoir, car les chaînes sont en fait immuables en JavaScript.)
Passons maintenant aux fonctions et à la transmission de paramètres .... Lorsque vous appelez une fonction et passez un paramètre, ce que vous faites essentiellement est une "affectation" à une nouvelle variable, et cela fonctionne exactement de la même manière que si vous l'attribuiez simplement à l'aide de le signe égal (=).
Prenez ces exemples.
Maintenant, la même chose, mais avec une fonction
OK, donnons maintenant quelques exemples en utilisant des objets à la place ... d'abord, sans la fonction.
Maintenant, la même chose, mais avec un appel de fonction
OK, si vous lisez l'intégralité de cet article, vous avez peut-être maintenant une meilleure compréhension du fonctionnement des appels de fonction en JavaScript. Peu importe que quelque chose soit passé par référence ou par valeur ... Ce qui compte, c'est l'affectation vs la mutation.
Chaque fois que vous passez une variable à une fonction, vous "assignez" à quelque soit le nom de la variable de paramètre, comme si vous utilisiez le signe égal (=).
Rappelez-vous toujours que le signe égal (=) signifie affectation. Souvenez-vous toujours que passer un paramètre à une fonction en JavaScript signifie également une affectation. Ils sont identiques et les 2 variables sont connectées exactement de la même manière (c'est-à-dire qu'elles ne le sont pas, sauf si vous comptez qu'elles sont affectées au même objet).
Le seul moment où la "modification d'une variable" affecte une variable différente est lorsque l'objet sous-jacent est muté (auquel cas vous n'avez pas modifié la variable, mais l'objet lui-même.
Il est inutile de faire une distinction entre les objets et les primitives, car cela fonctionne exactement de la même manière que si vous n'aviez pas de fonction et que vous utilisiez simplement le signe égal pour attribuer à une nouvelle variable.
Le seul problème est que le nom de la variable que vous passez dans la fonction est le même que le nom du paramètre de fonction. Lorsque cela se produit, vous devez traiter le paramètre à l'intérieur de la fonction comme s'il s'agissait d'une toute nouvelle variable privée de la fonction (car elle l'est)
la source
foo(char *a){a="hello";}
ne fait rien, mais si vous le faites,foo(char *a){a[0]='h';a[1]='i';a[2]=0;}
il est modifié à l'extérieur car ila
s'agit d'un emplacement mémoire transmis par une valeur qui fait référence à une chaîne (tableau de caractères). Passer des structures (similaires aux objets js) par valeur en C est autorisé, mais non recommandé. JavaScript applique simplement ces meilleures pratiques et masque la corruption inutile et généralement indésirable ... et cela facilite la lecture.source = { "id":"1"}; copy = source /*this is wrong*/; copy.id="2"
cette source est toujours {"id": "1"}?Considérer ce qui suit:
Donc,
oubliez "passer par référence / valeur"ne vous raccrochez pas sur "passer par référence / valeur" car:Pour répondre à votre question: des pointeurs sont passés.
Quelques derniers commentaires:
la source
{'George', 1}
valeurs, mais n'utilise qu'une seule à la fois, comment les autres sont-elles gérées? Et que se passe-t-il lorsque j'attribue une variable à la valeur d'une autre variable? Suis-je alors pointé sur un pointeur, ou pointé sur la pointe de l'opérande droit? A pourvar myExistingVar = {"blah", 42}; var obj = myExistingVar;
résultat deobj
pointer vers{"blah", 42}
ou versmyExistingVar
?1)
j'ai exécuté un profil de mémoire dans les outils de développement du navigateur pour une fonction de boucle telle que celle que vous avez décrite et j'ai vu des pics d'utilisation de la mémoire tout au long du processus de boucle. Cela semble indiquer que de nouveaux objets identiques sont effectivement créés à chaque itération de la boucle. Lorsque les pointes tombent soudainement, le garbage collector vient de nettoyer un groupe de ces objets inutilisés.2)
Concernant quelque chose commevar a = b
, javascript ne fournit pas de mécanisme pour utiliser des pointeurs et donc une variable ne peut jamais pointer vers un pointeur (comme vous pouvez en C), bien que le moteur javascript sous-jacent les utilise sans aucun doute. Alors ...var a = b
pointeraa
"vers la pointe de l'opérande droit"Un objet en dehors d'une fonction est passé dans une fonction en donnant une référence à l'objet extérieur.
Lorsque vous utilisez cette référence pour manipuler son objet, l'objet extérieur est ainsi affecté. Cependant, si à l'intérieur de la fonction vous avez décidé de pointer la référence vers autre chose, vous n'avez pas affecté l'objet du tout, car vous n'avez fait que rediriger la référence vers autre chose.
la source
Pensez-y comme ceci: c'est toujours passer par la valeur. Cependant, la valeur d'un objet n'est pas l'objet lui-même, mais une référence à cet objet.
Voici un exemple, en passant un nombre (un type primitif)
La répétition de ceci avec un objet donne des résultats différents:
Un autre exemple:
la source
Une explication très détaillée sur la copie, le passage et la comparaison par valeur et par référence se trouve dans ce chapitre du livre "JavaScript: The Definitive Guide" .
la source
JavaScript est toujours pass-by-value ; tout est de type valeur.
Les objets sont des valeurs et les fonctions membres des objets sont des valeurs elles-mêmes (rappelez-vous que les fonctions sont des objets de première classe en JavaScript). En outre, concernant le concept selon lequel tout en JavaScript est un objet ; c'est faux. Les chaînes, symboles, nombres, booléens, nuls et non définis sont des primitives .
À l'occasion, ils peuvent tirer parti de certaines fonctions membres et propriétés héritées de leurs prototypes de base, mais ce n'est que pour plus de commodité. Cela ne signifie pas qu'ils sont eux-mêmes des objets. Essayez ce qui suit pour référence:
Dans les deux alertes, vous trouverez la valeur indéfinie.
la source
x = "teste"; x.foo = 12;
etc. Ce n'est pas parce qu'une propriété n'est pas persistante que ce n'est pas un objet. Comme le dit MDN: En JavaScript, presque tout est un objet. Tous les types primitifs, à l'exception de null et undefined, sont traités comme des objets. Des propriétés peuvent leur être attribuées (les propriétés attribuées de certains types ne sont pas persistantes) et elles ont toutes les caractéristiques des objets. linkEn JavaScript, le type de la valeur contrôle uniquement si cette valeur sera attribuée par copie de valeur ou par copie de référence .
Les valeurs primitives sont toujours attribuées / transmises par value-copy :
null
undefined
ES6
Les valeurs composées sont toujours attribuées / transmises par référence-copie
Par exemple
Dans l'extrait ci-dessus, car
2
est une primitive scalaire,a
contient une copie initiale de cette valeur etb
se voit attribuer une autre copie de la valeur. Lors de la modificationb
, vous ne modifiez en aucun cas la valeur ena
.Mais les deux
c
etd
sont des références distinctes à la même valeur partagée[1,2,3]
, qui est une valeur composée. Il est important de noter quec
nid
plus ni plus ne "possède" la[1,2,3]
valeur - les deux sont juste des références homologues égales à la valeur. Ainsi, lorsque vous utilisez l'une ou l'autre référence pour modifier (.push(4)
) laarray
valeur partagée réelle elle-même, cela affecte uniquement la seule valeur partagée, et les deux références feront référence à la valeur nouvellement modifiée[1,2,3,4]
.Lorsque nous faisons l'affectation
b = [4,5,6]
, nous ne faisons absolument rien pour affecter oùa
se réfère toujours ([1,2,3]
). Pour ce faire, ilb
faudrait être un pointeur versa
plutôt qu'une référence à laarray
- mais aucune telle capacité n'existe dans JS!Lorsque nous transmettons l'argument
a
, il affecte une copie de laa
référence àx
.x
eta
sont des références distinctes pointant vers la même[1,2,3]
valeur. Maintenant, à l'intérieur de la fonction, nous pouvons utiliser cette référence pour muter la valeur elle-même (push(4)
). Mais lorsque nous faisons l'affectationx = [4,5,6]
, cela n'affecte en rien où la référence initialea
pointe - pointe toujours sur la valeur (maintenant modifiée)[1,2,3,4]
.Pour transmettre efficacement une valeur composée (comme un
array
) par copie de valeur, vous devez en faire une copie manuellement, afin que la référence transmise ne pointe toujours pas vers l'original. Par exemple:Valeur composée (objet, tableau, etc.) qui peut être transmise par référence-copie
Ici,
obj
agit comme un wrapper pour la propriété primitive scalairea
. Une fois transmis àfoo(..)
, une copie de laobj
référence est transmise et définie sur lewrapper
paramètre. Nous pouvons maintenant utiliser lawrapper
référence pour accéder à l'objet partagé et mettre à jour sa propriété. Une fois la fonction terminée,obj.a
la valeur mise à jour s'affiche42
.La source
la source
eh bien, il s'agit de «performances» et de «vitesse» et dans le simple mot «gestion de la mémoire» dans un langage de programmation.
en javascript, nous pouvons mettre les valeurs en deux couches: type1 -
objects
et type2 -tous les autres types de valeurs tels questring
&boolean
& etcsi vous imaginez la mémoire comme des carrés ci-dessous qui, dans chacun d'eux, une seule valeur type2 peut être enregistrée:
chaque valeur de type2 (vert) est un seul carré tandis qu'une valeur de type1 (bleu) en est un groupe :
le fait est que si vous voulez indiquer une valeur type2, l'adresse est simple mais si vous voulez faire la même chose pour la valeur type1 ce n'est pas facile du tout! :
et dans une histoire plus compliquée:
alors ici les références peuvent nous sauver:
alors que la flèche verte ici est une variable typique, la violette est une variable objet, donc parce que la flèche verte (variable typique) n'a qu'une seule tâche (et cela indique une valeur typique), nous n'avons pas besoin de séparer sa valeur de nous déplaçons donc la flèche verte avec la valeur de celle-ci partout où elle va et dans toutes les affectations, fonctions et ainsi de suite ...
mais nous ne pouvons pas faire la même chose avec la flèche violette, nous pouvons vouloir déplacer la cellule 'john' ici ou bien d'autres choses ..., donc la flèche violette restera à sa place et juste les flèches typiques qui lui ont été assignées se déplaceront ...
une situation très déroutante est où vous ne pouvez pas réaliser comment votre variable référencée change, jetons un coup d'œil à un très bon exemple:
la source
C'est un peu plus d'explication pour passer par valeur et passer par référence (JavaScript). Dans ce concept, ils parlent de passer la variable par référence et de passer la variable par référence.
Passer par valeur (type primitif)
Passer par référence (objets)
c
et pointe vers de la mémoire, par exemple (0x012).d
pointe vers le même emplacement (0x012).Cas particulier, passer par référence (objets)
la source
c
est définie sur une copie de la référence du nouvel objet.En JavaScript, lors de l'affectation d'un objet à une variable, la valeur affectée à la variable est une référence à l'objet:
la source
Sémantique!! Définir des définitions concrètes rendra nécessairement certaines réponses et commentaires incompatibles car ils ne décrivent pas la même chose même lorsque vous utilisez les mêmes mots et phrases, mais il est essentiel de surmonter la confusion (en particulier pour les nouveaux programmeurs).
Tout d'abord, il existe plusieurs niveaux d'abstraction que tout le monde ne semble pas comprendre. Les programmeurs plus récents qui ont appris sur les langages de 4e ou 5e génération peuvent avoir du mal à se concentrer sur des concepts familiers à l'assemblage ou sur des programmeurs C non organisés par des pointeurs vers des pointeurs vers des pointeurs. Le passage par référence ne signifie pas simplement la possibilité de modifier un objet référencé à l'aide d'une variable de paramètre de fonction.
Variable : concept combiné d'un symbole qui fait référence à une valeur à un emplacement particulier dans la mémoire. Ce terme est généralement trop chargé pour être utilisé seul dans la discussion des détails.
Symbole : chaîne de texte utilisée pour faire référence à une variable (c'est-à-dire le nom de la variable).
Valeur : bits particuliers stockés en mémoire et référencés à l'aide du symbole de variable.
Emplacement de mémoire : où la valeur d'une variable est stockée. (L'emplacement lui-même est représenté par un nombre distinct de la valeur stockée à l'emplacement.)
Paramètre de fonction : variable déclarée dans une définition de fonction, utilisée pour référencer les variables passées à la fonction.
Argument de fonction : Variable en dehors de la fonction qui est transmise à la fonction par l'appelant.
Variable d'objet : variable dont la valeur sous-jacente de base n'est pas "l'objet" lui-même, mais plutôt sa valeur est un pointeur (valeur d'emplacement de mémoire) vers un autre emplacement en mémoire où les données réelles de l'objet sont stockées. Dans la plupart des langages de génération supérieure, l'aspect "pointeur" est effectivement masqué par le dé-référencement automatique dans divers contextes.
Variable primitive : variable dont la valeur EST la valeur réelle. Même ce concept peut être compliqué par la mise en boîte automatique et les contextes similaires à des objets de divers langages, mais l'idée générale est que la valeur de la variable EST la valeur réelle représentée par le symbole de la variable plutôt qu'un pointeur vers un autre emplacement de mémoire.
Les arguments de fonction et les paramètres ne sont pas la même chose. De plus, la valeur d'une variable n'est pas l'objet de la variable (comme l'ont déjà souligné diverses personnes, mais apparemment ignoré). Ces distinctions sont essentielles à une bonne compréhension.
Pass-by-value ou Call-by-sharing (pour les objets): La valeur de l'argument de fonction est COPIÉE vers un autre emplacement mémoire qui est référencé par le symbole de paramètre de la fonction (qu'il soit sur la pile ou sur le tas). En d'autres termes, le paramètre de fonction a reçu une copie de la valeur de l'argument passé ... ET (critique) la valeur de l'argument N'EST JAMAIS MISE À JOUR / MODIFIÉE / MODIFIÉE par la fonction appelante. N'oubliez pas que la valeur d'une variable objet n'est PAS l'objet lui-même, mais plutôt le pointeur vers l'objet, donc le passage d'une variable objet par valeur copie le pointeur vers la variable de paramètre de fonction. La valeur du paramètre de fonction pointe vers exactement le même objet en mémoire. Les données d'objet elles-mêmes peuvent être modifiées directement via le paramètre de fonction, MAIS la valeur de l'argument de fonction N'EST JAMAIS MISE À JOUR, il continuera donc à pointer vers le mêmeobjet tout au long et même après l'appel de fonction (même si les données de son objet ont été modifiées ou si le paramètre de fonction est affecté à un autre objet). Il est incorrect de conclure que l'argument de fonction a été transmis par référence uniquement parce que l'objet référencé peut être mis à jour via la variable de paramètre de fonction.
Appel / Pass-by-reference : La valeur de l'argument de fonction peut / sera mise à jour directement par le paramètre de fonction correspondant. Si cela aide, le paramètre de fonction devient un "alias" efficace pour l'argument - ils se réfèrent effectivement à la même valeur au même emplacement de mémoire. Si un argument de fonction est une variable d'objet, la possibilité de modifier les données de l'objet n'est pas différente de la casse de valeur car le paramètre de fonction pointera toujours vers le même objet que l'argument. Mais dans le cas de la variable objet, si le paramètre de la fonction est défini sur un objet complètement différent, l'argument pointera également vers l'objet différent - cela ne se produit pas dans le cas du passage par valeur.
JavaScript ne passe pas par référence. Si vous lisez attentivement, vous vous rendrez compte que toutes les opinions contraires comprennent mal ce que l'on entend par valeur de passage et ils concluent à tort que la possibilité de mettre à jour les données d'un objet via le paramètre de fonction est synonyme de "valeur de passage".
Clonage / copie d' objet: un nouvel objet est créé et les données de l'objet d'origine sont copiées. Cela peut être une copie complète ou une copie superficielle, mais le fait est qu'un nouvel objet est créé. La création d'une copie d'un objet est un concept distinct de la valeur de passage. Certains langages font la distinction entre l'objet de classe et les structures (ou similaires), et peuvent avoir un comportement différent pour transmettre des variables de différents types. Mais JavaScript ne fait rien de tel automatiquement lors du passage de variables d'objet. Mais l'absence de clonage d'objet automatique ne se traduit pas par un passage par référence.
la source
JavaScript transmet les types primitifs par valeur et les types d'objets par référence
- Brian Bi - Quels langages de programmation sont passés par référence?
Mise à jour
Voici une réfutation de ceci:
Il n'y a pas de "passe par référence" disponible en JavaScript.
la source
Ma façon simple de comprendre cela ...
Lorsque vous appelez une fonction, vous transmettez le contenu (référence ou valeur) des variables d'argument, pas les variables elles-mêmes.
À l'intérieur de la fonction, les variables de paramètre
inVar1
etinVar2
reçoivent le contenu transmis.Depuis que vous avez
inVar2
reçu la référence de{ prop: 2 }
, vous pouvez modifier la valeur de la propriété de l'objet.la source
Passer des arguments à une fonction en JavaScript est analogue à passer des paramètres par valeur de pointeur en C:
la source
Pour les avocats en langage de programmation, j'ai parcouru les sections suivantes d'ECMAScript 5.1 (qui est plus facile à lire que la dernière édition), et je suis allé jusqu'à le demander sur la liste de diffusion ECMAScript.
TL; DR : Tout est passé par valeur, mais les propriétés des objets sont des références, et la définition de l'objet fait cruellement défaut dans la norme.
Construction de listes d'arguments
La section 11.2.4 «Listes d'arguments» indique ce qui suit sur la production d'une liste d'arguments composée d'un seul argument:
La section énumère également les cas où la liste d'arguments a 0 ou> 1 arguments.
Ainsi, tout est passé par référence.
Accès aux propriétés des objets
Section 11.2.1 "Accesseurs de propriété"
Ainsi, les propriétés des objets sont toujours disponibles comme référence.
Sur référence
Il est décrit dans la section 8.7 «Le type de spécification de référence», que les références ne sont pas de vrais types dans le langage - elles sont uniquement utilisées pour décrire le comportement de la suppression, du typeof et des opérateurs d'affectation.
Définition d '"objet"
Il est défini dans l'édition 5.1 que "Un objet est une collection de propriétés". Par conséquent, nous pouvons en déduire que la valeur de l'objet est la collection, mais quant à la valeur de la collection est mal définie dans la spécification et nécessite un peu d' effort pour la comprendre.
la source
Les documents MDN l'expliquent clairement, sans être trop verbeux:
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Description
la source
Dans un langage de bas niveau, si vous souhaitez passer une variable par référence, vous devez utiliser une syntaxe spécifique dans la création de la fonction:
La
&age
est une référence àmyAge
, mais si vous voulez la valeur, vous devez convertir la référence en utilisant*age
.Javascript est un langage de haut niveau qui effectue cette conversion pour vous. Ainsi, bien que les objets soient passés par référence, le langage convertit le paramètre de référence en valeur. Vous n'avez pas besoin d'utiliser
&
, sur la définition de la fonction, pour la passer par référence, ni*
sur le corps de la fonction, pour convertir la référence en valeur, JS le fait pour vous.C'est pourquoi lorsque vous essayez de changer un objet à l'intérieur d'une fonction, en remplaçant sa valeur (ie
age = {value:5}
), le changement ne persiste pas, mais si vous changez ses propriétés (ieage.value = 5
), il le fait.Apprendre encore plus
la source
J'ai lu ces réponses plusieurs fois, mais je ne les ai VRAIMENT pas obtenues jusqu'à ce que j'apprenne la définition technique de "Appeler en partageant", comme l'a dit Barbara Liskov.
Autrement dit, les références de paramètres sont modifiables si vous accédez à la valeur du paramètre elle-même. En revanche, l'affectation à un paramètre disparaîtra après évaluation et ne sera pas accessible à l'appelant de fonction.
la source
Moyen le plus simple
la source
JSON.parse( JSON.stringify( obj ) )
est un moyen horrible de cloner des objets en profondeur. Non seulement il est non seulement lent, mais il peut également entraîner une perte de données.J'ai trouvé la méthode extend de la bibliothèque Underscore.js très utile lorsque je veux passer un objet en tant que paramètre qui peut être soit modifié, soit remplacé entièrement.
la source
L'explication la plus succincte que j'ai trouvée était dans le guide de style AirBNB :
Primitives : lorsque vous accédez à un type primitif, vous travaillez directement sur sa valeur
Par exemple:
Complexe : lorsque vous accédez à un type complexe, vous travaillez sur une référence à sa valeur
Par exemple:
Autrement dit, les types primitifs sont passés par valeur et les types complexes sont passés par référence.
la source
Je dirais que c'est copie par copie -
Considérez que les arguments et les objets variables sont des objets créés pendant le contexte d'exécution créé au début de l'invocation de la fonction - et votre valeur / référence réelle transmise à la fonction est simplement stockée dans ces arguments + objets variables.
En termes simples, pour les types primitifs, les valeurs sont copiées au début de l'appel de fonction, pour le type d'objet, la référence est copiée.
la source
Il y a une discussion sur l'utilisation du terme "passer par référence" en JavaScript ici , mais pour répondre à votre question:
(D'après l'article mentionné ci-dessus.)
la source
Un moyen facile de déterminer si quelque chose est "passer par référence" est de savoir si vous pouvez écrire une fonction "swap". Par exemple, en C, vous pouvez faire:
Si vous ne pouvez pas faire l'équivalent de cela en JavaScript, ce n'est pas "passer par référence".
la source
Array and Object est passé en tant que passage par référence ou passage par valeur en fonction de ces deux conditions.
si vous modifiez la valeur de cet objet ou tableau avec un nouvel objet ou tableau, il est passé par valeur.
object1 = {item: "car"}; array1=[1,2,3];
ici, vous affectez un nouvel objet ou un tableau à l'ancien. vous ne modifiez pas la valeur de la propriété de l'ancien objet. il est donc transmis par valeur.
si vous modifiez une valeur de propriété d'un objet ou d'un tableau, elle est transmise par référence.
object1.key1= "car"; array1[0]=9;
ici, vous modifiez une valeur de propriété de l'ancien objet. vous n'affectez pas un nouvel objet ou un tableau à l'ancien. il est donc transmis par référence.
Code
la source
la source
Les valeurs simples à l'intérieur des fonctions ne changeront pas ces valeurs en dehors de la fonction (elles sont transmises par valeur), tandis que les valeurs complexes le seront (elles sont transmises par référence).
la source