После всех этих отличные ответы, на самом деле нечего сказать, поэтому объясняет объяснение, основанное на спецификации ECMAScript 5.
Также функция deepclone в конце ответа.
Как определено в спецификации ES5,
11.13.1 Simple Assignment (=) Производство ВыражениеПрисваивания: ЛевостороннееВыражение = ВыражениеПрисваивания вычисляется следующим образом:
- Пусть LRef быть результатом оценки ЛевостороннегоВыражения.
- Позвольте rref быть результатом оценки AssignmentExpression.
- Пусть rval будет
GetValue(rref)
.
- Бросить исключение SyntaxError, если выполняются следующие условия все верно:
- Тип (LRef) является Ссылка верно
- IsStrictReference (LRef) верно
- Тип (GetBase (LRef)) является среда записи
- GetReferencedName (LRef) либо "Eval" или "аргументы"
- вызовов
PutValue(lref, rval)
.
- Обратно rval.
Так Что происходит, когда мы достигаем точку и rref
является объектом, является
§8.7.1 (раздел 4В В GetValue(V) //V==rref
интересная точка)
4. Если IsPropertyReference (V), а затем
- (б) Возвращает результат вызова получить внутренний метод с использованием базы, как это его значение, и переходя GetReferencedName (V) для аргумента.
Теперь в этой точке rval
держит ссылку на объект, который затем получает положить в на 5.
Где §8.7.2 (опять 4В PutValue(V,W) //V==lref , W==rval
интересная часть) приходит в игру.
Примечание: W является атм ссылка на объект, который нужно назначить, и не значение
4. Иначе, если IsPropertyReference (V), а затем
- (б) Вызвать внутренний метод put, используя base, как его значение, и передать GetReferencedName (V) для имени свойства, W для значения и IsStrictReference (V) для флага Throw.
Как вы можете видеть в вашем случае значение из b
что банкомат ссылка на объект [6, 7, 8]
заменяется на результат, так сказать GetValue(rref)
, который является ссылка на [1, 2, 3];
Однако
Видимо вы ищете deep clone
Адрес: 1.
Object.defineProperty(Object.prototype, "clone", {
value: function (deep) {
var type = Object.prototype.toString.call(this).match(/^\[object (.+?)\]$/)[1];
if (type !== "Object") {
return this.valueOf;
}
var clone = {};
if (!deep) {
for (var prp in this) {
clone[prp] = this[prp];
}
} else {
for (var prop in this) {
if (typeof this[prop] !== "undefined" && this[prop] !== null)
clone[prop] = (typeof this[prop] !== "object" ? this[prop] : this[prop].clone((typeof deep == "boolean" ? deep : (deep - 1))));
else
clone[prop] = "";
}
}
return clone;
},
enumerable: false
});
Object.defineProperty(Array.prototype, "clone", {
value: function (deep) {
var clone = [];
if (!deep) clone = this.concat();
else this.forEach(function (e) {
if (typeof e !== "undefined" && e !== null)
clone.push((typeof e !== "object" ? e : e.clone((deep - 1))));
else
clone.push("");
});
return clone;
},
enumerable: false
});
var a = [1, [2, { a: 3 } ], 4];
var b = a.clone(Infinity);
a[1][1]["a"] = "cloned";
console.log(a[1][1]["a"], b[1][1]["a"]); //"cloned" , 3
И Демо на JSBin
Чтобы использовать это просто вызовите .clone(levelOfDeepness)
на объект или массив
Примечание: Я использовал прототип Объекты ради простоте так как я могу напрямую вызвать .clone
элементов Object и Array при клонировании m (дает повышение производительности по варианту проверки типов в одной функции)
Строго говоря, это всегда «передать по значению», а значение переменных, относящихся к объектам, является ссылкой на объект. «Пропустить по ссылке» не существует в JavaScript: https://en.wikipedia.org/wiki/Evaluation_strategy. –
* «Как избежать передачи по ссылке?» *: Вам нужно скопировать массив: http://stackoverflow.com/q/7486085/218196. –
Вы ничего не передаете по ссылке. Это означает, что вы (в псевдокоде) объявляете свою функцию «function why (const n)» или «function why (var n)».Разница в том, что в первом случае выполняется копия 'n', и если вы оставите функцию, она будет уничтожена, а во втором вы измените переменную, поэтому оставляя эту функцию, вы сохраните свои изменения. В ваших примерах «a» и «b» являются глобальными переменными, поэтому по умолчанию они являются ссылками (функция 'why' не имеет ничего общего). Вы должны были спросить не о ** передаче ** (переменные по ссылке), а ** ** (ссылки на переменные). – Voitcus