Сообщение от Zeroglif
|
Ну, давай ещё добавим нечто, чтоб не разгрести было вообще.
|
Не, наоборот, разгребли полностью. Если наиболее точно, то именно так. Поскольку есть чёткое разграничение между by-value, by-reference и by-sharing.
А остальное - это уже локальная терминология: ES называет by-value, Java называет by-value, Ruby называет by-reference - но во всех них в данном случае используется
by-sharing.
Здесь фишка завязана ещё на связывание имён и объектов в памяти. Именно из-за того, что присваивание переменной объекта, отвязывает переменную от старого места в памяти, и не получается чистый by-reference.
Если бы был
by-reference, было бы так:
function test(a) {
a = {x: 20};
}
var b = {x: 10};
test(b);
alert(b.x); // 20
Если бы был
by-value, было бы так:
function test(a) {
a.x = 20;
}
var b = {x: 10};
test(b);
alert(b.x); // 10
А вот
by-sharing, как раз имеет чёткую разницу от них двоих:
function test(a) {
a.x = 20;
}
var b = {x: 10};
test(b);
alert(b.x); // 20
function test2(a) {
// присваивание связывает "а" с новым объектом
// старый остаётся нетронутым
a = {x: 30};
}
test2(b);
alert(b.x); // 20
Но именно это связывание переменной с объектом ничем не отличается, если сделать то же самое вне функции и её параметров:
var a = {x: 10};
var b = a;
// a и b указывают на одно место в памяти
alert(b.x); // 10
b = {x: 20}; // связывание с новым объектом, но не апдейт "а"
alert(a.x); // 10
Если в рамках ES, то, конечно, можно и by-value говорить, главное знать, что выше этого стоит определение общей теории. С другой стороны, ECMA-262-3 точно это не описывает. Есть куча ссылок (в том числе, которые приводил ты), где, действительно, говорят
by-value, но это, опять же, локальная терминология для
by-sharing.
Может смущать, что работает оператор ===, который возвращает true для локального формального параметра и внешнего объекта (а он возвращает true в данном случае, если операнды указывают на один и тот же объект):
function test(a) {
alert(a === b); // true
}
var b = {x: 10};
test(b);
Т.е. здесь тоже с толку может сбивать людей - кажется, что "a" - точно не локальный объект, а как будто бы переданный by-reference.
Но, во всяком случае, при разрешении "a" и "b", базовые объекты у них разные - для "а" - объект активации, для "b" - глобальный:
aRef = {baseObject: AO(test), propertyName: "a"};
bRef = {baseObject: Global, propertyName: "b"};
Каким-то образом затем [[Get]] получает value aRef и bRef и определяет, что они указывают на один объект.