web-dev-qa-db-fra.com

Javascript par référence et par valeur

Je cherche du matériel de lecture complet et complet sur le moment où Javascript transmet quelque chose par valeur et par référence et lorsque la modification d'un élément passé affecte la valeur en dehors d'une fonction et quand elle ne l'est pas. Je m'intéresse également à l'affectation à une autre variable, soit par référence ou par valeur, et si elle suit des règles différentes de celles définies en tant que paramètre de fonction.

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

De plus, existe-t-il des moyens dans le langage de contrôler si quelque chose est passé par référence ou par valeur?

Voici certains types de questions que je veux comprendre. Ce ne sont que des exemples - je cherche en fait à comprendre les règles du langage, 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 le contenu de x, y et z change-t-il 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 entièrement indépendante d'un objet (sans aucune référence), quel est le meilleur moyen de le faire?

359
jfriend00

Je crois comprendre que c'est en réalité très simple:

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

Alors, pour travailler sur 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"
616
nrabinowitz

Javascript toujours passe par valeur. Toutefois, si vous transmettez un objet à une fonction, la "valeur" est en réalité une référence à cet objet. La fonction peut donc modifier les propriétés de cet objet mais ne permet pas à la variable en dehors de la fonction de pointer sur 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 = ...
54
nnnnnn

Oui, Javascript passe toujours par valeur, mais dans un tableau ou un objet, la valeur est une référence, ce qui vous permet de "changer" le contenu.

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

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

27
  1. Variable de type primitif telle que chaîne, nombre sont toujours passés comme passe par valeur.
  2. Array and Object est passé comme passe par référence ou passe par valeur en fonction de ces deux conditions.

    • si vous modifiez la valeur de cet objet ou de ce tableau avec un nouvel objet ou un nouveau tableau, il est transmis par valeur.

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

    ici, vous attribuez un nouvel objet ou un nouveau tableau à l’ancien. Vous ne modifiez pas la valeur de la propriété de old object.

    • si vous modifiez une valeur de propriété d'un objet ou d'un tableau, il est passé par référence.

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

    ici, vous modifiez une valeur de propriété de old object.vous n'attribuez pas de nouvel objet ni de nouveau tableau à l'ancien.

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
15
Mukund Kumar