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

К примитивам относятся такие типы данных, как:
⦁ числа,
⦁ строки,
⦁ логические значения,
⦁ null
⦁ неопределенные.

Объекты, с другой стороны, охватывают:
⦁ массивы,
⦁ функции,
⦁ объекты

Передача примитивных значений

При передаче примитивных значений в качестве аргументов функциям или присвоении их переменным создается копия значения. Это означает, что изменения, внесенные в скопированное значение внутри функции или другой переменной, не влияют на исходное значение. Вот два примера:

function modifyNumber(num) {
 num = 42; // Modifying the copied value
}
let x = 10;
modifyNumber(x);
console.log(x); // Output: 10 (Unchanged)
function concatenateStrings(str) {
 str += ‘ World!’; // Modifying the copied value
}
let message = ‘Hello’;
concatenateStrings(message);
console.log(message); // Output: ‘Hello’ (Unchanged)

В обоих примерах мы видим, что хоть мы и передали нашу переменную в качестве аргумента, вне функции значение остается неизменным. Это происходит потому, что для примитивных значений в функцию передается копия значения. Любые изменения, внесенные в скопированное значение внутри функции, не влияют на исходное значение. Поэтому исходная переменная x в первом примере и message во втором примере остаются без изменений.

Передача непримитивных значений (ссылки):

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

function modifyArray(arr) {
  arr.push(4); // Modifying the referenced array
}

let myArray = [1, 2, 3];
modifyArray(myArray);
console.log(myArray); // Output: [1, 2, 3, 4] (Modified)
function modifyObject(obj) {
  obj.name = 'John'; // Modifying the referenced object
}

let myObject = { id: 1 };
modifyObject(myObject);
console.log(myObject); // Output: { id: 1, name: 'John' } (Modified)

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

Изменение ссылки

Опираясь на мою предыдущую статью на Medium о разнице между var, let и const в JavaScript, я подчеркнул, как const позволяет переменным содержать ссылки на не примитивные значения, предотвращая переназначение самой переменной. Однако важно отметить, что const не делает объекты или массивы неизменяемыми; это только предотвращает переназначение переменной другой ссылке.

const person = { name: 'John', age: 30 };
person.age = 31; // Modifying the property of the referenced object
console.log(person); // Output: { name: 'John', age: 31 } (Modified)

В этом примере, несмотря на то, что переменная person объявлена ​​как const, мы по-прежнему можем изменять свойства объекта, на который указывает ссылка. Сама ссылка остается неизменной, но свойства внутри объекта могут быть изменены.

let person1 = { name: 'John' };
let person2 = { name: 'Jane' };

person1 = person2; // Changing the reference of person1
person2.name = 'Alice'; // Modifying the referenced object

console.log(person1); // Output: { name: 'Alice' }
console.log(person2); // Output: { name: 'Alice' }

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

Этот пример демонстрирует, как let позволяет нам изменить ссылку на объект, и демонстрирует изменчивую природу объектов в JavaScript.

Краткое содержание:

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

Важно отметить, что const в JavaScript не делает объекты или массивы неизменяемыми. Хотя это предотвращает переназначение самой переменной, свойства объекта, на который делается ссылка, все же могут быть изменены. Кроме того, использование ключевого слова let позволяет нам изменить ссылку на объект, демонстрируя изменчивую природу объектов в JavaScript.

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