Является ли JavaScript языком передачи по ссылке или передачей по значению? - PullRequest
1259 голосов
/ 06 февраля 2009

Примитивные типы (Number, String и т. Д.) Передаются по значению, но объекты неизвестны, поскольку они могут быть оба переданы по значению (в случае, если мы считаем, что переменная, содержащая объект, на самом деле является ссылкой к объекту) и передается по ссылке (если учесть, что переменная объекта содержит сам объект).

Хотя в конце это и не имеет значения, я хочу знать, как правильно представлять аргументы, передающие соглашения. Есть ли выдержка из спецификации JavaScript, которая определяет, какой должна быть семантика относительно этого?

Ответы [ 30 ]

1 голос
/ 17 мая 2014

Самое краткое объяснение, которое я нашел, было в Руководстве по стилю AirBNB :

  • Примитивы : При доступе к типу примитива вы работаете непосредственно с его значение

    • строка
    • номер
    • логическое
    • нуль
    • неопределенный

например:.

var foo = 1,
    bar = foo;

bar = 9;

console.log(foo, bar); // => 1, 9
  • Сложный : при доступе к сложному типу вы работаете со ссылкой на его значение

    • объект
    • массив
    • функция

например:.

var foo = [1, 2],
    bar = foo;

bar[0] = 9;

console.log(foo[0], bar[0]); // => 9, 9

т.е. эффективно примитивные типы передаются по значению, а сложные типы передаются по ссылке.

0 голосов
/ 20 апреля 2019

Документы MDN объясняют это ясно, не будучи слишком многословным:

Параметрами вызова функции являются аргументы функции . Аргументы передаются в функции по значению . Если функция меняется значение аргумента, это изменение не отражается глобально или в вызывающая функция. Однако ссылки на объекты тоже являются значениями, и они особенные: если функция изменяет объект свойства, которые видны вне функции, (...)

Источник: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Description

0 голосов
/ 06 февраля 2009

Простой способ определить, является ли что-то «передачей по ссылке», заключается в том, можно ли написать функцию «своп». Например, в C вы можете сделать:

void swap(int *i, int *j)
{
    int t;
    t = *i;
    *i = *j;
    *j = t;
}

Если вы не можете сделать эквивалент этого в Javascript, это не «передача по ссылке».

0 голосов
/ 21 августа 2009

Примитивы передаются по значению, а объекты передаются по ссылке. Это сильно отличается от других языков, таких как C, VB или Delphi. Я не могу сказать, как они точно обрабатывают объекты и примитивы, но я знаю о VB и Delphi, что он может (и должен) быть указан.

php делает то же самое, начиная с версии 5: все объекты передаются по ссылке, но все примитивы могут передаваться по ссылке, если перед ними стоит амперсанд (&). В противном случае примитивы передаются по значению.

Так, в javascript, если я передам объект X в функцию через параметр, это все равно будет X. Если вы изменяете данные внутри функции (или любого другого объекта, но это не важно ) это новое значение также доступно вне функции.

0 голосов
/ 05 мая 2012

Я нашел метод расширения библиотеки Underscore.js очень полезным, когда я хочу передать объект в качестве параметра, который можно либо изменить, либо заменить целиком.

function replaceOrModify(aObj) {
  if (modify) {

    aObj.setNewValue('foo');

  } else {

   var newObj = new MyObject();
   // _.extend(destination, *sources) 
   _.extend(newObj, aObj);
  }
}
0 голосов
/ 25 февраля 2013
  1. Примитивы (Number, Boolean) передаются по значению.
    • Строки неизменны, поэтому для них это не имеет значения.
  2. Объекты передаются по ссылке (ссылка передается по значению)
0 голосов
/ 27 апреля 2013

Простые значения внутри функций не будут изменять эти значения вне функции (они передаются по значению), тогда как сложные значения будут (они передаются по ссылке).

function willNotChange(x) {

x = 1;

}

var x = 1000;

willNotChange(x);

document.write('After function call, x = ' + x + '<br>'); //still 1000

function willChange(y) {

y.num = 2;

}

var y = {num: 2000}; 

willChange(y);
document.write('After function call y.num = ' + y.num + '<br>'); //now 2, not 2000
0 голосов
/ 09 января 2015

Я бы сказал, что это копия за копией -

Учтите, что аргументы и переменные объекты - это объекты, созданные во время контекста выполнения, созданного в начале вызова функции, а фактическое значение / ссылка, переданные в функцию, просто сохраняются в этих аргументах + переменных объектах.

Проще говоря, для примитивных типов значения копируются в начале вызова функции, для типа объекта - копируется ссылка.

0 голосов
/ 27 июня 2013

В некоторых случаях это может быть полезно для изменения anArg:

function alterMyArg(func) {
    // process some data
    // ...
    func(data);
}

alertMyArg(function(d) {anArg = d;});
0 голосов
/ 28 октября 2014
  1. переменная типа примитива, такая как строка, число всегда передается как проход по значению.
  2. Массив и Объект передаются как передача по ссылке или передача по значению на основе этих двух условий.

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

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

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

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

      object1.key1= "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
...