Переназначение, изменение, ссылочные типы и типы значений

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

// Reassignment
let a = 1;
let b = a;
a = 2;
console.log(b); // → 1

// Mutation
let myArray = [1, 2, 3];
let ourArray = myArray;
ourArray[2] = 10;
console.log(myArray); // → [1, 2, 10]

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

Когда явно говорится только о метке переменной (то есть почему метки в первом примере не отслеживают изменения значения, тогда как во втором примере это происходит), разве истинное различие не связано с мутацией vs. переназначение?

В конце концов, мы могли бы так же легко переназначить myArray или ourArray, и ни один из них не имел бы какой-либо постоянной связи. И, если бы примитивные значения были теоретически изменяемыми в JavaScript, первый пример можно было бы заставить вести себя так же, как и второй.

Последующий вопрос

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

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

Я здесь на правильном пути?


person jabacchetta    schedule 18.03.2016    source источник
comment
Я думаю, что вам не хватает опыта работы с языком нижнего уровня (с указателями). 5 дней борьбы с паскалем сэкономили бы вам 50 дней борьбы с JS, все было бы намного яснее.   -  person Ivan Kuckir    schedule 19.03.2016
comment
Да, это вопрос мутации и переназначения изменяемых и неизменяемых значений. Существует ли в памяти одновременно только один экземпляр из 9? Вероятно, если это фактическое значение, а не объект Number , которым вы присвоили другие свойства, но это полностью зависит от того, как компилятор обрабатывает их.   -  person Mike Cluck    schedule 19.03.2016


Ответы (2)


В своем вопросе вы смешиваете детали реализации («существуют один раз в памяти») со стратегиями оценки («ссылочные типы и типы значений») и конкретными выражениями («мутация против переназначения»). Детали реализации различаются в зависимости от браузера и, вероятно, изменятся в будущем.

В Javascript есть две стратегии оценки:

  • Копировать по значению (передавать по значению при вызове функций)
  • Копировать по ссылке (передавать по ссылке при вызове функций)

Типы значений

Типы значений всегда копируются по значению. Предполагаемые строки были изменяемыми в Javascript:

let s = "abc";
let t = s;

s[0] = "x";
s; // "xbc";
t; // "abc";

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

В отличие от строк числа атомарны. Для атомарных примитивов нет практического различия между мутацией и переназначением:

let n = 0;
n = 1, n++, n = n + 1; // all reassignments

Типы справочников

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

Ссылочные типы имеют идентичность, то есть их идентичность больше не привязана к значениям:

let xs = [1];
xs === [1]; // false
person Iven Marquardt    schedule 20.03.2016

Когда явно говорится только о метке переменной, разве истинное различие не связано с мутацией или переназначением?

Конечно. Я предполагаю, что вы имеете в виду, что один изменяет объекты и присваивает переменные. Но так их не всегда отличить. Я мог бы также сказать, что я присваиваю свойства объекта (в вашем втором примере) или изменяю ячейки памяти «с меткой переменных» (в вашем первом примере). Есть ли разница?

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

Я продолжаю читать противоречивую информацию о том, существуют ли примитивные значения только один раз в памяти.

Дело в том, что это не имеет значения, поскольку примитивные значения (по определению) неизменяемы. Реализация JS может копировать их или делиться ссылками, поведение не различимо для сценария.

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

person Bergi    schedule 20.03.2016