Javascript по ссылке и по значению [дубликат]

этот вопрос уже есть ответ здесь:

Я ищу хороший всеобъемлющий материал для чтения, когда Javascript передает что-то по значению и когда по ссылке и при изменении переданного элемента влияет на значение вне функция и когда нет. Меня также интересует, когда присваивание другой переменной по ссылке или по значению и следует ли это каким-либо другим правилам, чем передача в качестве параметра функции.

Я сделал много поиска и нашел много конкретных примеров (многие из них здесь, на SO), из которых я могу начать собирать кусочки реальных правил, но я еще не нашел ни одного хорошо написанного документа, который описывает все это.

кроме того, есть ли способы язык, чтобы контролировать, передается ли что-то по ссылке или по значению?

вот некоторые из типов вопросов, которые я хочу понять. Это всего лишь примеры - я действительно хочу понять правила, по которым идет язык, а не только ответы на конкретные примеры. Но, вот несколько примеров:

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);

когда содержимое x, y и z изменяется за пределами области f для всех разных типов?

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?
}

Если я хочу сделать полностью независимая копия объекта (без каких-либо ссылок), каков наилучший способ сделать это?

4 ответов


Я понимаю, что это на самом деле очень просто:

  • Javascript - это всегда pass by value, но когда переменная ссылается на объект (включая массивы), "value" является ссылкой на объект.
  • изменение значения переменной никогда изменяет базовый примитив или объект, он просто указывает переменную на новый примитив или объект.
  • изменение свойства объекта ссылка на переменную изменяет базовый объект.

Итак, чтобы проработать некоторые из ваших примеров:

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

Пример 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"

на JavaScript всегда проходит по значению. Однако, если вы передаете объект функции, "значение" действительно является ссылкой на этот объект, поэтому функция может изменять свойства этого объекта но не заставляйте переменную вне функции указывать на какой-либо другой объект.

пример:

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 = ...

да, Javascript всегда проходит по значению, но в массиве или объекте значение является ссылкой на него, поэтому вы можете "изменить" содержимое.

но, я думаю, вы уже читали это на SO;здесь у вас есть документация, которую вы хотите:

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


  1. переменная примитивного типа как строка, номер всегда проходит как пропуск по значению.
  2. массив и объект передаются как pass by reference или pass by value на основе этих двух условий.

    • если вы изменяете значение этого объекта или массива с новым объектом или массивом, то он передается по значению.

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

    здесь вы назначаете новый объект или массив старому.ты не изменишь стоимость имущества старого предмета.так что это pass by value.

    • если вы изменяете значение свойства объекта или массива, то он перейдет по ссылке.

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

    здесь вы меняете значение свойства старого объекта.вы не назначаете новый объект или массив старому.так это проходит по ссылке.

код

    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