Подтвердить что ты не робот

Является ли JavaScript перекрестной ссылкой или языком с переходом?

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

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

4b9b3361

Ответ 1

Это интересно в JavaScript. Рассмотрим этот пример:

function changeStuff(a, b, c)
{
  a = a * 10;
  b.item = "changed";
  c = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);
console.log(obj1.item);
console.log(obj2.item);

Ответ 2

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

Пример:

function changeObject(x) {
  x = { member: "bar" };
  console.log("in changeObject: " + x.member);
}

function changeMember(x) {
  x.member = "bar";
  console.log("in changeMember: " + x.member);
}

var x = { member: "foo" };

console.log("before changeObject: " + x.member);
changeObject(x);
console.log("after changeObject: " + x.member); /* change did not persist */

console.log("before changeMember: " + x.member);
changeMember(x);
console.log("after changeMember: " + x.member); /* change persists */

Ответ 3

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

Не существует способа изменить значение, хранящееся в переменной, переданной в качестве параметра, что было бы возможно, если бы JavaScript поддерживал передачу по ссылке.

Ответ 4

Мои два цента... Я так понимаю. (Не стесняйтесь поправлять меня, если я ошибаюсь)

Пришло время выбросить все, что вы знаете о передаче по значению/ссылке.

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

Хорошо, позвольте мне сделать все возможное, чтобы объяснить, что я имею в виду. Допустим, у вас есть несколько объектов.

var object1 = {};
var object2 = {};

Что мы сделали, так это "присваивание"... Мы присвоили 2 отдельных пустых объекта переменным "object1" и "object2".

Теперь, давайте скажем, что нам нравится object1 лучше... Итак, мы "назначаем" новую переменную.

var favoriteObject = object1;

Затем, по какой-либо причине, мы решаем, что нам нравится объект 2 лучше. Итак, мы просто делаем небольшое переназначение.

favoriteObject = object2;

Ничего не случилось с object1 или object2. Мы не изменили никаких данных вообще. Все, что мы сделали, это переназначили наш любимый объект. Важно знать, что object2 и FavoritesObject назначены одному и тому же объекту. Мы можем изменить этот объект с помощью любой из этих переменных.

object2.name = 'Fred';
console.log(favoriteObject.name) // Logs Fred
favoriteObject.name = 'Joe';
console.log(object2.name); // Logs Joe

Хорошо, теперь давайте посмотрим на примитивы как строки, например

var string1 = 'Hello world';
var string2 = 'Goodbye world';

Опять выбираем любимую.

var favoriteString = string1;

Обе переменные favouriteString и string1 присвоены "Hello world". А что если мы захотим изменить нашу любимую строку??? Что случится???

favoriteString = 'Hello everyone';
console.log(favoriteString); // Logs 'Hello everyone'
console.log(string1); // Logs 'Hello world'

Э-э-э... Что случилось? Мы не могли изменить string1, изменив favourString... Почему?? Потому что мы не изменили наш строковый объект. Все, что мы сделали, это "RE ASSIGN" переменную favourString для новой строки. Это по существу отключило его от string1. В предыдущем примере, когда мы переименовали наш объект, мы ничего не назначали. (Ну, не самой переменной, но мы присвоили свойство name новой строке.) Вместо этого мы просто мутировали объект, который поддерживает связи между двумя переменными и базовыми объектами. (Даже если бы мы хотели изменить или изменить сам строковый объект, мы не смогли бы этого сделать, потому что строки на самом деле неизменны в JavaScript.)

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

Возьмите эти примеры.

var myString = 'hello';

// Assign to a new variable (just like when you pass to a function)
var param1 = myString;
param1 = 'world'; // Re assignment

console.log(myString); // Logs 'hello'
console.log(param1);   // Logs 'world'

Теперь то же самое, но с функцией

function myFunc(param1) {
    param1 = 'world';

    console.log(param1);   // Logs 'world'
}

var myString = 'hello';
// Calls myFunc and assigns param1 to myString just like param1 = myString
myFunc(myString);

console.log(myString); // logs 'hello'

Хорошо, теперь давайте приведем несколько примеров использования объектов вместо... во-первых, без функции.

var myObject = {
    firstName: 'Joe',
    lastName: 'Smith'
};

// Assign to a new variable (just like when you pass to a function)
var otherObj = myObject;

// Let mutate our object
otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl

console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Sue'

// Now, let reassign the variable
otherObj = {
    firstName: 'Jack',
    lastName: 'Frost'
};

// Now, otherObj and myObject are assigned to 2 very different objects
// And mutating one object has no influence on the other
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Jack';

Теперь то же самое, но с вызовом функции

function myFunc(otherObj) {

    // Let mutate our object
    otherObj.firstName = 'Sue';
    console.log(otherObj.firstName); // Logs 'Sue'

    // Now let re-assign
    otherObj = {
        firstName: 'Jack',
        lastName: 'Frost'
    };
    console.log(otherObj.firstName); // Logs 'Jack'

    // Again, otherObj and myObject are assigned to 2 very different objects
    // And mutating one object doesn't magically mutate the other
}

var myObject = {
    firstName: 'Joe',
    lastName: 'Smith'
};

// Calls myFunc and assigns otherObj to myObject just like otherObj = myObject
myFunc(myObject);

console.log(myObject.firstName); // Logs 'Sue', just like before

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

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

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

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

Нет смысла проводить различие между объектами и примитивами, потому что он работает точно так же, как если бы у вас не было функции, а просто использовали знак равенства для присвоения новой переменной.

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

function myFunc(myString) {
    // myString is private and does not affect the outer variable
    myString = 'hello';
}

var myString = 'test';
myString = myString; // Does nothing, myString is still 'test';

myFunc(myString);
console.log(myString); // Logs 'test'

Ответ 5

Рассмотрим следующее:

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

Итак, забудьте о "pass by reference/value" , не зацикливайтесь на "pass by reference/value", потому что:

  • Термины используются только для описания поведения языка, а не для фактической базовой реализации. В результате этой абстракции теряются критические детали, которые необходимы для достойного объяснения, что неизбежно приводит к текущей ситуации, когда один термин не описывает адекватное описание фактического поведения и дополнительной информации.
  • Эти понятия изначально не были определены с целью описания javascript в частности, и поэтому я не чувствую себя вынужденным использовать их, когда они только добавляют к путанице.

Чтобы ответить на ваш вопрос: указатели передаются.


// code
var obj = {
    name: 'Fred',
    num: 1
};

// illustration
               'Fred'
              /
             /
(obj) ---- {}
             \
              \
               1


// code
obj.name = 'George';


// illustration
                 'Fred'


(obj) ---- {} ----- 'George'
             \
              \
               1


// code
obj = {};

// illustration
                 'Fred'


(obj)      {} ----- 'George'
  |          \
  |           \
 { }            1


// code
var obj = {
    text: 'Hello world!'
};

/* function parameters get their own pointer to 
 * the arguments that are passed in, just like any other variable */
someFunc(obj);


// illustration
(caller scope)        (someFunc scope)
           \             /
            \           /
             \         /
              \       /
               \     /
                 { }
                  |
                  |
                  |
            'Hello world'

Некоторые заключительные комментарии:

  • Заманчиво думать, что примитивы выполняются специальными правилами, а объекты - нет, но примитивы - это просто конец цепочки указателей.
  • В качестве окончательного примера рассмотрим, почему общая попытка очистить массив не работает должным образом.


var a = [1,2];
var b = a;

a = [];
console.log(b); // [1,2]
// doesn't work because `b` is still pointing at the original array

Ответ 6

Объект вне функции передается в функцию путем предоставления ссылки на внешний объект.

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

Ответ 7

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

Вот пример, передающий число (примитивный тип)

function changePrimitive(val) {
    // At this point there are two '10 in memory.
    // Changing one won't affect the other
    val = val * 10;
}
var x = 10;
changePrimitive(x);
// x === 10

Повторение этого с помощью объекта дает разные результаты:

function changeObject(obj) {
    // At this point there are two references (x and obj) in memory,
    // but these both point to the same object.
    // changing the object will change the underlying object that
    // x and obj both hold a reference to.
    obj.val = obj.val * 10;
}
var x = { val: 10 };
changeObject(x);
// x === { val: 100 }

Еще один пример:

function changeObject(obj) {
    // Again there are two references (x and obj) in memory,
    // these both point to the same object.
    // now we create a completely new object and assign it.
    // obj reference now points to the new object.
    // x reference doesn't change.
    obj = { val: 100 };
}
var x = { val: 10 };
changeObject(x);
// x === { val: 10}

Ответ 8

JavaScript всегда передается по значению; все имеет значение типа.

Объекты являются значениями, а функции-члены объектов сами являются значениями (помните, что функции являются первоклассными объектами в JavaScript). Кроме того, относительно концепции, что все в JavaScript является объектом; это не верно. Строки, символы, числа, логические значения, значения NULL и неопределенные значения являются примитивами.

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

x = "test";
alert(x.foo);
x.foo = 12;
alert(x.foo);

В обоих оповещениях вы найдете значение, которое не определено.

Ответ 9

В JavaScript тип значения определяет только то, будет ли это значение присвоено значение-копия или ссылка-копия.

Примитивные значения всегда присваиваются/передаются по-копии:

  • null
  • undefined
  • строка
  • номер
  • булева
  • символ ES6

Составные значения всегда назначаются/передаются с помощью ссылки-копии

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

Например

var a = 2;
var b = a; // `b` is always a copy of the value in `a`
b++;
a; // 2
b; // 3

var c = [1,2,3];
var d = c; // `d` is a reference to the shared `[1,2,3]` value
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]

В приведенном выше фрагменте, поскольку 2 является скалярным примитивом, a содержит одну начальную копию этого значения, а b присваивается другая копия значения. При изменении b вы никоим образом не изменяете значение в a.

Но оба c и d являются отдельными ссылками на одно и то же общее значение [1,2,3], которое является составным значением. Важно отметить, что ни c, ни d больше не владеет значением [1,2,3] - оба равны равным равным ссылкам на значение. Таким образом, при использовании любой ссылки для изменения (.push(4)) фактического общего значения array оно влияет только на одно общее значение, и обе ссылки будут ссылаться на вновь измененное значение [1,2,3,4].

var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]

// later
b = [4,5,6];
a; // [1,2,3]
b; // [4,5,6]

Когда мы делаем назначение b = [4,5,6], мы ничего не делаем, чтобы влиять на то, где a все еще ссылается ([1,2,3]). Для этого b должен быть указателем на a, а не ссылкой на array - но такой возможности не существует в JS!

function foo(x) {
    x.push( 4 );
    x; // [1,2,3,4]

    // later
    x = [4,5,6];
    x.push( 7 );
    x; // [4,5,6,7]
}

var a = [1,2,3];

foo( a );

a; // [1,2,3,4]  not  [4,5,6,7]

Когда мы передаем аргумент a, он присваивает копию ссылки a на x. x и a - отдельные ссылки, указывающие на то же значение [1,2,3]. Теперь, внутри функции, мы можем использовать эту ссылку для мутации самого значения (push(4)). Но когда мы делаем назначение x = [4,5,6], это никоим образом не влияет на то, где указывается начальная ссылка a, - все еще указывает на (теперь измененное) значение [1,2,3,4].

Чтобы эффективно передать составное значение (например, array) с помощью копии значения, вам нужно вручную сделать его копию, чтобы переданная ссылка не все еще указывала на оригинал. Например:

foo( a.slice() );

Компонентное значение (объект, массив и т.д.), которое может быть передано с помощью ссылки-копии

function foo(wrapper) {
    wrapper.a = 42;
}

var obj = {
    a: 2
};

foo( obj );

obj.a; // 42

Здесь obj действует как обертка для скалярного примитивного свойства a. Когда передано foo(..), копия ссылки obj передается и устанавливается в параметр wrapper. Теперь мы можем использовать ссылку wrapper для доступа к общему объекту и обновления его свойства. После завершения функции obj.a будет отображаться обновленное значение 42.

Источник

Ответ 10

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

Прежде чем мы оставим тему управления объектами и массивами по ссылке, нам нужно прояснить пункт номенклатуры.

Фраза "передать по ссылке" может иметь несколько значений. Для некоторых читателей эта фраза относится к технике вызова функции, которая позволяет функции назначать новые значения своим аргументам и отображать эти измененные значения вне функции. Это не то, как термин используется в этой книге.

Здесь мы просто подразумеваем, что ссылка на объект или массив, а не сам объект, передается функции. Функция может использовать ссылку для изменения свойств объекта или элементов массива. Но если функция перезаписывает ссылку ссылкой на новый объект или массив, эта модификация не видна за пределами функции.

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

Ответ 11

JavaScript передает примитивные типы по значению и типы объектов по ссылке

Теперь людям нравится бесконечно спорить о том, является ли "передача по ссылке" правильным способом описания того, что Java et al. на самом деле Дело в следующем:

  1. Передача объекта не копирует объект.
  2. Объект, переданный в функцию, может иметь свои члены, модифицированные функцией.
  3. Примитивное значение, переданное функции, не может быть изменено функцией. Копия сделана.

В моей книге это называется передачей по ссылке.

- Брайан Би - Какие языки программирования передаются по ссылке?


Обновить

Вот опровержение этого:

В JavaScript нет "передачи по ссылке".

Ответ 12

Там некоторые дискуссии по поводу использования термина "передать по ссылке" в JavaScript здесь, но ответить на ваш вопрос:

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

(Из статьи, упомянутой выше.)

Ответ 13

Передача аргументов функции в JavaScript аналогична передаче параметры по значению указателя в C:

/*
The following C program demonstrates how arguments
to JavaScript functions are passed in a way analogous
to pass-by-pointer-value in C. The original JavaScript
test case by @Shog9 follows with the translation of
the code into C. This should make things clear to
those transitioning from C to JavaScript.

function changeStuff(num, obj1, obj2)
{
    num = num * 10;
    obj1.item = "changed";
    obj2 = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);    
console.log(obj2.item);

This produces the output:

10
changed
unchanged
*/

#include <stdio.h>
#include <stdlib.h>

struct obj {
    char *item;
};

void changeStuff(int *num, struct obj *obj1, struct obj *obj2)
{
    // make pointer point to a new memory location
    // holding the new integer value
    int *old_num = num;
    num = malloc(sizeof(int));
    *num = *old_num * 10;
    // make property of structure pointed to by pointer
    // point to the new value
    obj1->item = "changed";
    // make pointer point to a new memory location
    // holding the new structure value
    obj2 = malloc(sizeof(struct obj));
    obj2->item = "changed";
    free(num); // end of scope
    free(obj2); // end of scope
}

int num = 10;
struct obj obj1 = { "unchanged" };
struct obj obj2 = { "unchanged" };

int main()
{
    // pass pointers by value: the pointers
    // will be copied into the argument list
    // of the called function and the copied
    // pointers will point to the same values
    // as the original pointers
    changeStuff(&num, &obj1, &obj2);
    printf("%d\n", num);
    puts(obj1.item);
    puts(obj2.item);
    return 0;
}

Ответ 14

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

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

Переменная: комбинированная концепция символа, который ссылается на значение в определенном месте в памяти. Этот термин обычно слишком загружен для использования отдельно при обсуждении деталей.

Символ: текстовая строка, используемая для ссылки на переменную (например, имя переменной).

Значение: отдельные бит, хранящиеся в памяти и ссылающиеся с использованием символа переменной.

Местоположение памяти. Где хранится значение переменной. (Само местоположение представлено числом, отдельным от значения, хранящегося в местоположении.)

Параметр функции: переменная, объявленная в определении функции, используемая для ссылки на переменные, переданные функции.

Аргумент функции: переменная вне функции, которая передается функции вызывающим абонентом.

Объектная переменная: переменная, базовое базовое значение которой не является самим объектом, а его значение является указателем (значением ячейки памяти) в другое место в памяти, где хранятся фактические данные объекта. На большинстве языков более высокого поколения аспект "указатель" эффективно скрывается путем автоматического удаления ссылок в различных контекстах.

Примитивная переменная: переменная, значение которой является фактическим значением. Даже эта концепция может быть осложнена автоматическим боксированием и объектно-подобными контекстами разных языков, но общие идеи заключаются в том, что переменная value IS является фактическим значением, представленным символом переменной, а не указателем на другое местоположение памяти.

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

Передача по значению или совместное использование вызовов (для объектов). Значение параметра функции COPIED - это другое место памяти, на которое ссылается символ параметра функции (независимо от того, включен ли он стек или куча). Другими словами, параметр функции получил копию переданного значения аргумента... И (критическое) значение аргумента НИКОГДА НЕ ОБНОВЛЯЕТСЯ/ИЗМЕНЕН/ИЗМЕНЕН вызывающей функцией. Помните, что значение переменной объекта НЕ является самим объектом, скорее это указатель на объект, поэтому передача переменной объекта по значению копирует указатель на переменную параметра функции. Значение параметра функции указывает на тот же самый объект в памяти. Сами данные объекта могут быть изменены непосредственно через параметр функции, НО значение аргумента функции НИКОГДА НЕ ОБНОВЛЯЕТСЯ, поэтому оно будет продолжать указывать на один и тот же объект на протяжении всего и даже после вызова функции (даже если данные объекта были изменены или если функциональному параметру назначается другой объект вообще). Неправильно заключить, что аргумент функции передавался по ссылке только потому, что ссылочный объект обновляется через переменную параметра функции.

Call/Pass-by-reference. Значение аргумента функции может/будет обновляться непосредственно соответствующим параметром функции. Если это помогает, параметр функции становится эффективным "псевдонимом" для аргумента - они фактически ссылаются на одно и то же значение в том же месте памяти. Если аргумент функции является объектной переменной, возможность изменения данных объекта не отличается от случая с байтовым значением, поскольку параметр функции все равно указывает на тот же объект, что и аргумент. Но в случае переменной объекта, если параметр функции установлен на совершенно другой объект, тогда аргумент также будет указывать на другой объект - этого не происходит в случае с переходом.

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

Клонирование/копирование объектов. Создается новый объект и копируются исходные данные объекта. Это может быть глубокая копия или мелкая копия, но дело в том, что создается новый объект. Создание копии объекта - это отдельная концепция из пропущенного значения. Некоторые языки различают объект класса и структуры (или тому подобное) и могут иметь различное поведение для передачи переменных разных типов. Но JavaScript не делает ничего подобного автоматически при передаче объектных переменных. Но отсутствие автоматического клонирования объектов не переводится на передачу по ссылке.

Ответ 15

Мой простой способ понять это...

  • При вызове функции вы передаете содержимое (ссылку или значение) переменных аргумента, а не самих переменных.

    var var1 = 13;
    var var2 = { prop: 2 };
    
    //13 and var2 content (reference) are being passed here
    foo(var1, var2); 
    
  • Внутри функции переменные параметра inVar1 и inVar2 получают переданное содержимое.

    function foo(inVar1, inVar2){
        //changing contents of inVar1 and inVar2 won't affect variables outside
        inVar1 = 20;
        inVar2 = { prop: 7 };
    }
    
  • Так как inVar2 получил ссылку { prop: 2 }, вы можете изменить значение свойства объекта.

    function foo(inVar1, inVar2){
        inVar2.prop = 7; 
    }
    

Ответ 16

На языке низкого уровня, если вы хотите передать переменную по ссылке, вы должны использовать определенный синтаксис при создании функции:

int myAge = 14;
increaseAgeByRef(myAge);
function increaseAgeByRef(int &age) {
  *age = *age + 1;
}

&age является ссылкой на myAge, но если вам нужно значение, которое вы должны преобразовать ссылку, используйте *age.

Javascript - это язык высокого уровня, который делает это преобразование для вас. Таким образом, хотя объекты передаются по ссылке, язык преобразует ссылочный параметр в значение. Вам не нужно использовать &, в определении функции, передать его по ссылке, а не *, в тело функции, чтобы преобразовать ссылку на значение, JS делает это для вас.

Поэтому, когда вы пытаетесь изменить объект внутри функции, заменив его значением (т.е. age = {value:5}), это изменение не сохраняется, но если вы измените его свойства (т.е. age.value = 5), это произойдет.

Подробнее...

Ответ 17

Для юристов на языке программирования я просмотрел следующие разделы ECMAScript 5.1 (который легче читать, чем последнее издание), и зайдите в спрашивая его в списке рассылки ECMAScript.

TL; DR: каждое значение передается по значению, но свойства объектов - это ссылки, а определение объекта, как правило, отсутствует в стандарте.

Построение списков аргументов

Раздел 11.2.4 "Списки аргументов" говорит следующее о создании списка аргументов, состоящего всего из 1 аргумента:

Произведение ArgumentList: AssignmentExpression оценивается следующим образом:

  • Пусть ref является результатом оценки AssignmentExpression.
  • Пусть arg - GetValue (ref).
  • Возвращает список, единственным элементом которого является arg.

В разделе также перечислены случаи, когда список аргументов имеет 0 или > 1 аргумент.

Таким образом, все передается по ссылке.

Доступ к объектным свойствам

Раздел 11.2.1 "Аксессоры свойств"

Произведение MemberExpression: MemberExpression [Expression] оценивается следующим образом:

  • Пусть baseReference будет результатом оценки MemberExpression.
  • Пусть baseValue будет GetValue (baseReference).
  • Пусть свойствоNameReference является результатом вычисления выражения.
  • Пусть свойствоNameValue будет GetValue (propertyNameReference).
  • Вызов CheckObjectCoercible (baseValue).
  • Пусть свойствоNameString - ToString (propertyNameValue).
  • Если синтаксическое производство, которое оценивается, содержится в коде строгого режима, пусть строгое истинно, иначе пусть строгое ложное.
  • Возвращает значение типа Reference, базовым значением которого является baseValue, а ссылочное имя - propertyNameString и строгий флаг строгого режима.

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

On Reference

Это описано в разделе 8.7 "Тип ссылочной спецификации", что ссылки не являются реальными типами в языке - они используются только для описания поведения операторов delete, typeof и присваивания.

Определение "Объект"

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

Ответ 18

делиться тем, что я знаю о ссылках в JavaScript

В JavaScript объекты хранятся в виде ссылок:

var a = {
  a: 1,
  b: 2,
  c: 3
};
var b = a;

// b.c is referencing to a.c value
console.log(b.c) // Output: 3
// Changing value of b.c
b.c = 4
// Also changes the value of a.c
console.log(a.c) // Output: 4

Ответ 19

Все аргументы функции в ECMAScript передаются по значению. Это означает, что значение вне функция копируется в аргумент внутри функции так же, как копируется значение от одной переменной к другой. Если значение является примитивным, то оно действует так же, как примитивная переменная копировать, и если значение является ссылкой, оно действует как копия ссылочной переменной. Это часто бывает путаницы для разработчиков, поскольку к переменным обращаются как по значению, так и по ссылке, но аргументы передаются только по значению. Когда аргумент передается по значению, значение копируется в локальную переменную (именованный аргумент и в ECMAScript - слот в объекте arguments). Когда аргумент передается по ссылке, расположение значения в памяти сохраняется в локальной переменной, что означает, что изменения в локальном переменная отражается вне функции. (Это невозможно в ECMAScript.)

Ответ 20

Это немного больше объяснения для передачи по значению и передачи по ссылке (JavaScript). В этой концепции они говорят о передаче переменной по ссылке и передаче переменной по ссылке.

Передача по значению (примитивный тип)

var a = 3;
var b = a;

console.log(a); // a = 3
console.log(b); // b = 3

a=4;
console.log(a); // a = 4
console.log(b); // b = 3
  • применяется ко всем примитивным типам в JavaScript (строка, число, логическое значение, неопределенное и нулевое значение).
  • a выделяется память (скажем, 0x001), а b создает копию значения в памяти (скажем, 0x002).
  • Таким образом, изменение значения переменной не влияет на другую, поскольку они оба находятся в двух разных местах.

Передача по ссылке (объекты)

var c = { "name" : "john" };
var d = c;

console.log(c); // { "name" : "john" }
console.log(d); // { "name" : "john" }

c.name = "doe";

console.log(c); // { "name" : "doe" }
console.log(d); // { "name" : "doe" }
  • Механизм JavaScript назначает объект переменной c, и он указывает на некоторую память, скажем, (0x012).
  • Когда d = c, на этом шаге d указывает на то же местоположение (0x012).
  • Изменение значения любого изменения значения для обеих переменных.
  • Функции являются объектами

Особый случай, передача по ссылке (объекты)

c = {"name" : "jane"};
console.log(c); // { "name" : "jane" }
console.log(d); // { "name" : "doe" }
  • Оператор равенства (=) устанавливает новое пространство памяти или адрес

Ответ 21

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

  • Примитивы. Когда вы получаете доступ к примитивному типу, вы работаете непосредственно с его Значение

    • строка
    • номер
    • булева
    • NULL
    • undefined

например:.

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

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

Ответ 22

Я читал эти ответы несколько раз, но НЕ ДЕЙСТВИТЕЛЬНО получил его, пока не узнал о техническом определении "Call by sharing" как называется Барбара Лисков

Семантика вызова путем совместного использования отличается от вызова по ссылке в том, что назначения для аргументов функции внутри функции не отображаются вызывающему (в отличие от ссылочной семантики) [править], так, например, если переменная была передана, невозможно смоделировать присвоение этой переменной в области вызова. Однако, поскольку функция имеет доступ к тому же объекту, что и вызывающий (без копирования), мутации для этих объектов, если объекты изменяемы, внутри функции видны вызывающему, которые могут отличаться от вызова по значению семантика. Мутации изменяемого объекта внутри функции видны вызывающему, потому что объект не копируется или не клонируется - он является общим.

То есть, ссылки на параметры могут быть изменены, если вы перейдете и получите доступ к самому значению параметра. С другой стороны, назначение параметра исчезает после оценки и не доступно для вызывающего функции.

Ответ 23

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

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

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

Ответ 24

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

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

Если вы не можете сделать то же самое в JavaScript, это не "передача по ссылке".

Ответ 25

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

function replaceOrModify(aObj) {
  if (modify) {

    aObj.setNewValue('foo');

  } else {

   var newObj = new MyObject();
   // _.extend(destination, *sources) 
   _.extend(newObj, aObj);
  }
}

Ответ 26

  1. Примитивы (число, логическое значение и т.д.) Передаются по значению.
    • Строки неизменны, поэтому для них это не имеет значения.
  2. Объекты передаются по ссылке (ссылка передается по значению).

Ответ 27

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

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

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

Ответ 28

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

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

Ответ 29

В JavaScript отсутствует "проход по ссылке". Вы можете передать объект (то есть вы можете передавать по значению ссылку на объект), а затем изменить функцию содержимого объекта:

function alterObject(obj) {
  obj.foo = "goodbye";
}

var myObj = { foo: "hello world" };

alterObject(myObj);

alert(myObj.foo); // "goodbye"

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

function swap(a, b) {
   var tmp = a;
   a = b;
   b = tmp; //assign tmp to b
 }

 var x = 1, y = 2;
 swap(x, y);
 // x and y dont changed in method
 alert("x is " + x + " and y is " + y); // x is 1 and y is 2

Ответ 30

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

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

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

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

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

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

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

код

    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