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

Область действия в javascript действует странно

Объект передается с их ссылкой в ​​javascript. Значение изменения в этом объекте из любого места должно быть отражено. В этом случае ожидаемый результат был {} для console.log(a)

function change(a,b) {
    a.x = 'added';
    a = b;//assigning a as {} to b
}
a={}
b={}
change(a,b);
console.log(a); //expected {} but output {x:'added'}
console.log(b)

Что здесь происходит? Насколько мне известно, это не должно быть из-за функционального охвата. Спасибо вам

4b9b3361

Ответ 1

Если вы добавили еще одну строку, вы можете получить более четкое представление о том, что происходит:

function change(a,b) {
    a.x = 'added';
    a = b;
    a.x = 'added as well';
};
a={};
b={};
change(a,b);
console.log(a);  //{x:'added'}
console.log(b);  //{x:'added as well'}

Когда вы делаете a = b, вы назначаете локальную переменную a ссылке, которую удерживает b.

Ответ 2

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

Что вам не хватает, так это то, что строка a = b; не изменяет объект, он изменяет ссылку на объект. Вы можете передать оба объекта в другой объект/массив контейнера, если вам нужно установить ссылку:

function change(container) {
    container.a.x = 'added';
    container.a = container.b;//assigning a as {} to b
}
var container = { a: {}, b: {}};
change(container);
console.log(container.a);
console.log(container.b)

Ответ 3

Переменная 'a' в контексте вашей функции не совпадает с переменной 'a' вне функции. Этот код семантически эквивалентен вашему:

function change(foo,bar) {
    foo.x = 'added';
    foo = bar;//assigning foo as {} to bar
}
a={}
b={}
change(a,b);
console.log(a); //expected {} but output {x:'added'}
console.log(b)

В этом случае очевидно, что переменная 'foo' существует только внутри функции, а выполнение foo = bar не меняет a, поскольку ссылка передается по значению.

Ответ 4

Объект передается с их ссылкой в ​​javascript.

Нет, это не так. ECMAScript/JavaScript строго передается по значению. (Точнее, вызов по-совместному использованию, который является частным случаем передачи по значению.)

Что здесь происходит?

Это просто нормальная пропускная способность.

Ваше замешательство проистекает из того факта, что вы ошибочно считаете, что ECMAScript/JavaScript передается по ссылке, когда на самом деле это не так.

ECMAScript использует pass-by-value или, точнее, частный случай pass-by-value, где переданное значение всегда является указателем. Этот особый случай также иногда называют совместным использованием вызовов, совместным использованием вызовов по вызову или позором.

Это то же соглашение, которое используется Java (для объектов), С# (по умолчанию для ссылочных типов), Smalltalk, Python, Ruby и более или менее каждый объектно-ориентированный язык, когда-либо созданный.

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

Вот простой пример, который вы можете выполнить для определения соглашения об отправке аргументов ECMAScript (или любого другого языка после его перевода):

function isEcmascriptPassByValue(foo) {
  foo.push('More precisely, it is call-by-object-sharing!');
  foo = 'No, ECMAScript is pass-by-reference.';
  return;
}

var bar = ['Yes, of course, ECMAScript *is* pass-by-value!'];

isEcmascriptPassByValue(bar);

console.log(bar);
// Yes, of course, ECMAScript *is* pass-by-value!,
// More precisely, it is call-by-object-sharing!

Ответ 5

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

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

Под капотом, так сказать, это в основном то, как были созданы ваши исходные ссылки.

Ответ 6

Это поможет решить вашу проблему:

var obj = {}, anotherObj = {};
// in case if they are not global, make them global or define parent scope to be able to modify inside the function
window.obj = obj;
window.anotherObj = anotherObj;
function swap(a, b) {
  window[a].newProp = 'XYZ';
  window[a] = window[b]; // now obj is gone, because replaced with anotherObj
}
swap('obj','anotherObj');
console.log(obj); // now it would give Object {}