474 votes

Est-ce que JavaScript passe par référence?

JavaScript passe-t-il par références ou par valeurs? Voici un exemple de JavaScipt: The Good Parts . Je suis très confus à propos du paramètre my pour la fonction rectangle. Il est en fait undefined et redéfini à l'intérieur de la fonction. Il n'y a pas de référence d'origine. Si je le supprime du paramètre de fonction, la fonction de zone interne ne peut pas y accéder.

Est-ce une fermeture? Mais aucune fonction n'est renvoyée.

 var shape = function (config) {
    var that = {};
    that.name = config.name || "";
    that.area = function () {
        return 0;
    };
    return that;
}
var rectangle = function (config, my) {
    my = my || {};
    my.l = config.length || 1;
    my.w = config.width || 1;
    var that = shape(config);
    that.area = function () {
        return my.l * my.w;
    }
    return that;
};
myShape = shape({
    name: "Unhnown"
});
myRec = rectangle({
    name: "Rectangle",
    length: 4,
    width: 6
});
console.log(myShape.name + " area is " + myShape.area() + " " + myRec.name + " area is " + myRec.area());
 

873voto

Alnitak Points 143355

Les Primitives sont passés par valeur, les Objets sont passés par "copie d'une référence".

Plus précisément, lorsque vous passez un objet (ou un tableau) vous êtes (invisible) de passer une référence à cet objet, et il est possible de modifier le contenu de l'objet, mais si vous essayez de remplacer la référence qu'il n'affectera pas la copie de la référence détenues par l'appelant, c'est à dire la référence elle-même est passé par valeur:

function replace(ref) {
    ref = {};           // this code does _not_ affect the object passed
}

function update(ref) {
    ref.key = 'newvalue';  // this code _does_ affect the _contents_ of the object
}

var a = { key: 'value' };
replace(a);  // a still has its original value - it's unmodfied
update(a);   // the _contents_ of 'a' are changed

Comparer avec C++ où le changement d'un type de référence peut entièrement remplacer l'objet passé en l'appelant:

void replace(mytype& ref) {
    ref = *new mytype();  // ignoring the memory leak for the purposes of this example
}

mytype a;
replace(a);   // a is now a _different_ object

73voto

jAndy Points 93076

Pensez-y comme ça:

Chaque fois que vous créez un objet dans ECMAscript, cet objet est formé dans une mystique ECMAscript universelle endroit où aucun homme ne sera jamais en mesure d'obtenir. Tout ce que vous obtenez en retour est une référence à l'objet dans ce lieu mystique.

var obj = { };

Même obj n'est qu'une référence à l'objet (qui se trouve sur ce lieu merveilleux) et, par conséquent, vous ne pouvez passer cette référence autour. Effectivement, n'importe quel morceau de code qui accède à des obj va modifier l' objet qui est loin, loin.

70voto

Ray Perea Points 525

Mes 2 Cents.... Il est sans importance de savoir si Javascript transmet des paramètres par référence ou la valeur. Ce qui est vraiment important est d'affectation vs mutation.

J'ai écrit une plus longue explication plus détaillée ici (JavaScript Est un passage par référence ou par valeur de la langue?)

Lorsque vous passer quoi que ce soit (qu'il S'agisse d'un objet ou d'une primitive), tous le javascript n'est d'assigner une nouvelle variable tandis que l'intérieur de la fonction... tout comme avec le signe égal (=)

Comment ce paramètre se comporte à l'intérieur de la fonction est exactement le même que celui-ci se comporte si vous venez d'affecter une nouvelle variable à l'aide du signe égal.. Prendre ces exemples simples.

var myString = 'Test string 1';

// Assignment - A link to the same place as myString
var sameString = myString;

// If I change sameString, it will not modify myString, 
// it just re-assigns it to a whole new string
sameString = 'New string';

console.log(myString); // logs 'Test string 1';
console.log(sameString); // logs 'New string';

Si je devais passer myString comme paramètre à une fonction, il se comporte comme si j'simplement assigné à une nouvelle variable. Maintenant, laissez-nous faire la même chose, mais avec une fonction au lieu d'une simple affectation

function myFunc(sameString) {

    // Re assignment.. again, it will not modify myString
    sameString = 'New string';
}

var myString = 'Test string 1';

// This behaves the same as if we said sameString = myString
myFunc(myString);

console.log(myString); // Again, logs 'Test string 1';

La seule raison pour laquelle vous pouvez modifier les objets lorsque vous les transmettre à une fonction est parce que vous n'êtes pas réaffectation des... au Lieu de cela, les objets peuvent être modifiés ou muté.... Encore une fois, il fonctionne de la même manière.

var myObject = { name: 'Joe'; }

// Assignment - We simply link to the same object
var sameObject = myObject;

// This time, we can mutate it. So a change to myObject affects sameObject and visa versa
myObject.name = 'Jack';
console.log(sameObject.name); // Logs 'Jack'

sameObject.name = 'Jill';
console.log(myObject.name); // Logs 'Jill'

// If we re-assign it, the link is lost
sameObject = { name: 'Howard' };
console.log(myObject.name); // Logs 'Jill'

Si je devais passer myObject comme paramètre à une fonction, il se comporte comme si j'simplement assigné à une nouvelle variable. Encore une fois, la même chose avec exactement le même comportement, mais avec une fonction.

function myFunc(sameObject) {

    // We mutate the object, so the myObject gets the change too... just like before.
    sameObject.name = 'Jill';

    // But, if we re-assign it, the link is lost
    sameObject = { name: 'Howard' };
}

var myObject = { name: 'Joe'; }

// This behaves the same as if we said sameObject = myObject;
myFunc(myObject);
console.log(myObject.name); // Logs 'Jill'

Chaque fois que vous passez une variable à une fonction, vous êtes "Affectation" quel que soit le nom du paramètre est, tout comme si vous avez utilisé le signe égal ( = ).

Rappelez-vous toujours que le signe égal (=) des moyens d'affectation. Et le passage d'un paramètre à une fonction aussi des moyens d'affectation. Ils sont les mêmes et les 2 variables sont connectés exactement de la même manière.

La seule fois que la modification d'une variable affecte une variable différente, c'est quand l'objet sous-jacent est muté.

Il est inutile de faire une distinction entre les objets et les primitives, car il fonctionne de la même manière exacte comme si vous n'aviez pas une fonction et juste utilisé le signe égal pour affecter à une nouvelle variable.

22voto

jmoreno Points 6995

Comme avec C, finalement, tout est passé par valeur. Contrairement à C, vous ne pouvez pas sauvegarder et passer l’emplacement d’une variable, car elle ne contient pas de pointeurs, mais seulement des références.

Et les références à des objets, pas à des variables. Il y a plusieurs manières d'obtenir le même résultat, mais elles doivent être faites à la main, pas seulement en ajoutant un mot-clé sur le site d'appel ou de déclaration.

4voto

Pete Campbell Points 11

En termes pratiques, Alnitak est correct et facile à comprendre, mais finalement, en JavaScript, tout est transmis par valeur.

Quelle est la "valeur" d'un objet? C'est la référence de l'objet.

Lorsque vous passez un objet, vous obtenez une copie de cette valeur (d'où la copie d'une référence décrite par Alnitak). Si vous modifiez cette valeur, vous ne modifiez pas l'objet d'origine, vous modifiez votre copie de cette référence.

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