417 votes

JavaScript par référence ou par valeur

Je suis à la recherche d'un bon matériel de lecture complet pour savoir quand JavaScript passe quelque chose par valeur et quand par référence et quand la modification d'un élément passé affecte la valeur en dehors d'une fonction et quand non. Je suis également intéressé par le fait de savoir quand l'assignation à une autre variable est par référence ou par valeur et si cela suit des règles différentes de celles du passage en tant que paramètre de fonction.

J'ai fait beaucoup de recherches et j'ai trouvé de nombreux exemples spécifiques (dont beaucoup ici sur SO) à partir desquels je peux commencer à rassembler des morceaux des vraies règles, mais je n'ai pas encore trouvé de document unique et bien écrit qui décrive tout cela.

Par ailleurs, existe-t-il des moyens dans le langage pour contrôler si un élément est transmis par référence ou par valeur ?

Voici quelques-uns des types de questions que je veux comprendre. Ce ne sont que des exemples - je cherche en fait à comprendre les règles de la langue, et pas seulement les réponses à des exemples spécifiques. Mais voici quelques exemples :

function f(a,b,c) {
   a = 3;
   b.push("foo");
   c.first = false;
}

var x = 4;
var y = ["eeny", "miny", "mo"];
var z = {first: true};
f(x,y,z);

Quand les contenus de x, y et z sont-ils modifiés en dehors de la portée de f pour tous les différents types ?

function f() {
    var a = ["1", "2", "3"];
    var b = a[1];
    a[1] = "4";
    // what is the value of b now for all possible data types that the array in "a" might hold?
}

function f() {
    var a = [{yellow: "blue"}, {red: "cyan"}, {green: "magenta"}];
    var b = a[1];
    a[1].red = "tan";
    // what is the value of b now and why?
    b.red = "black";
    // did the value of a[1].red change when I assigned to b.red?
}

Si je veux faire une copie totalement indépendante d'un objet (sans aucune référence), quelle est la meilleure façon de le faire ?

710voto

nrabinowitz Points 27991

D'après ce que j'ai compris, c'est en fait très simple :

  • Javascript est toujours passer par valeur, mais lorsqu'une variable fait référence à un objet (y compris les tableaux), la "valeur" est une référence à l'objet.
  • Changer la valeur d'une variable jamais change la primitive ou l'objet sous-jacent, elle fait simplement pointer la variable vers une nouvelle primitive ou un nouvel objet.
  • Cependant, la modification d'un propriété d'un objet référencé par une variable change l'objet sous-jacent.

Donc, pour travailler à travers certains de vos exemples :

function f(a,b,c) {
    // Argument a is re-assigned to a new value.
    // The object or primitive referenced by the original a is unchanged.
    a = 3;
    // Calling b.push changes its properties - it adds
    // a new property b[b.length] with the value "foo".
    // So the object referenced by b has been changed.
    b.push("foo");
    // The "first" property of argument c has been changed.
    // So the object referenced by c has been changed (unless c is a primitive)
    c.first = false;
}

var x = 4;
var y = ["eeny", "miny", "mo"];
var z = {first: true};
f(x,y,z);
console.log(x, y, z.first); // 4, ["eeny", "miny", "mo", "foo"], false

Exemple 2 :

var a = ["1", "2", {foo:"bar"}];
var b = a[1]; // b is now "2";
var c = a[2]; // c now references {foo:"bar"}
a[1] = "4";   // a is now ["1", "4", {foo:"bar"}]; b still has the value
              // it had at the time of assignment
a[2] = "5";   // a is now ["1", "4", "5"]; c still has the value
              // it had at the time of assignment, i.e. a reference to
              // the object {foo:"bar"}
console.log(b, c.foo); // "2" "bar"

73 votes

Bien que techniquement vrai, je préfère dire que JavaScript est Partage de l'objet de Pass By . Il évite une telle confusion et passe à une vue de "haut niveau".

2 votes

@pst - C'est logique, mais notez les problèmes soulevés dans la page Wikipedia référencée - la plupart des gens n'utilisent pas le terme, et la (grande) communauté Java appelle cela "pass-by-value". Néanmoins, je suis d'accord pour dire que c'est un peu confus.

11 votes

À quelle "confusion" faites-vous référence ? Pour moi, "pass-by-value" est parfaitement clair.

60voto

nnnnnn Points 70578

Javascript toujours passe par valeur. Toutefois, si vous passez un objet à une fonction, la "valeur" est en réalité une référence à cet objet, de sorte que la fonction peut modifier les propriétés de cet objet. mais ne pas faire en sorte que la variable en dehors de la fonction pointe vers un autre objet .

Un exemple :

function changeParam(x, y, z) {
  x = 3;
  y = "new string";
  z["key2"] = "new";
  z["key3"] = "newer";

  z = {"new" : "object"};
}

var a = 1,
    b = "something",
    c = {"key1" : "whatever", "key2" : "original value"};

changeParam(a, b, c);

// at this point a is still 1
// b is still "something"
// c still points to the same object but its properties have been updated
// so it is now {"key1" : "whatever", "key2" : "new", "key3" : "newer"}
// c definitely doesn't point to the new object created as the last line
// of the function with z = ...

6 votes

Array est un objet et va donc changer aussi.

0 votes

Sauf que presque tout en JavaScript est un objet.

2 votes

@Hritik - Sauf pour toutes les valeurs primitives qui ne sont pas des objets.

28voto

Oui, Javascript passe toujours par la valeur, mais dans un tableau ou un objet, la valeur est une référence à celui-ci, de sorte que vous pouvez "changer" le contenu.

Mais, je pense que tu l'as déjà lu sur SO ; aquí vous avez la documentation que vous voulez :

http://snook.ca/archives/javascript/javascript_pass

2 votes

Bien que techniquement vrai, je préfère dire que JavaScript est Partage de l'objet de Pass By . Il évite une telle confusion et passe à une vue de "haut niveau".

1 votes

J'ai fait un violon pour jouer un peu avec ça : jsfiddle.net/tkane2000/7weKS/1

19voto

Mukund Kumar Points 736
  1. Les variables de type primitif comme les chaînes de caractères, les nombres sont toujours passés en tant que tels. par valeur.
  2. Les tableaux et les objets sont transmis par référence ou par valeur en fonction de ces deux conditions.

    • Si vous changez la valeur d'un objet ou d'un tableau avec un nouvel objet ou tableau, il s'agit d'un passage par valeur.

      object1 = {item: "car"}; array1=[1,2,3];

    Ici, vous assignez un nouvel objet ou tableau à l'ancien. Vous ne changez pas la valeur de la propriété de l'ancien objet. de l'ancien objet. Il s'agit donc d'un passage par valeur.

    • si vous changez la valeur d'une propriété d'un objet ou d'un tableau, vous passez par référence.

      object1.item= "car"; array1[0]=9;

    Ici, vous changez la valeur d'une propriété de l'ancien objet. Vous n'assignez pas le nouvel objet ou le tableau à l'ancien, il s'agit donc d'un passage par référence.

Code

    function passVar(object1, object2, number1) {

        object1.key1= "laptop";
        object2 = {
            key2: "computer"
        };
        number1 = number1 + 1;
    }

    var object1 = {
        key1: "car"
    };
    var object2 = {
        key2: "bike"
    };
    var number1 = 10;

    passVar(object1, object2, number1);
    console.log(object1.key1);
    console.log(object2.key2);
    console.log(number1);

Output: -
    laptop
    bike
    10

0 votes

Nope. Tout passe par la valeur, toujours.

2 votes

Mettez juste le code ci-dessus dans votre console et voyez...la valeur est changée...

12 votes

Il y a un débat terminologique très ancien sur le fait d'appeler ce que Javascript fait "passer par référence". Je préfère passer outre ce débat et appeler ce que JS fait pour les objets et les tableaux "pass by pointer". Les tableaux et les objets sont toujours passés par un pointeur. Si vous modifiez ce qui a été transmis (en accédant au pointeur), l'original est modifié. Si vous assignez un tableau ou un objet différent à la variable du pointeur, l'original n'est pas modifié car votre variable "pointe" maintenant vers un tableau ou un objet différent. Il s'agit en grande partie d'un "débat terminologique", car il n'y a pas de débat sur ce qui se passe réellement.

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