Передача по значению
В JavaScript pass by value функция вызывается путем непосредственной передачи значения переменной в качестве аргумента. Поэтому даже изменение аргумента внутри функции не влияет на переменную, переданную извне функции.
- Важно отметить, что в JavaScript все аргументы функций всегда передаются по значению. То есть JavaScript копирует значения передаваемых переменных в аргументы внутри функции.
Кредиты — Рейна Митчелл
Пример-
Код-
let a=5
let b=a
b++;
console.log(b)
console.log(a)
Выход-
6
5
Передача по ссылке —
В Pass by Reference функция вызывается путем прямой передачи ссылки/адреса переменной в качестве аргумента. Изменение аргумента внутри функции влияет на переменную, переданную извне функции.
- В JavaScript объекты и массивы всегда передаются по ссылке.
Пример-
Код —
let obj1={
a: 'a',
b: 'b',
c: 'c'
}
// shallow copying the object using the spread operator
let obj2={...obj1}
obj2.b='d'
console.log(obj2)
console.log(obj1)
или
let obj1={
a: 'a',
b: 'b',
c: 'c'
}
// another way of copying the object
let obj2=Object.assign({}, obj1)
obj2.b='d'
console.log(obj2)
console.log(obj1)
Выход-
{
a: "a",
b: "d",
c: "c"
}
{
a: "a",
b: "b",
c: "c"
}
- Но это лишь поверхностная копия исходного объекта.
Глубокая копия означает, что все значения новой переменной скопированы и отсоединены от исходной переменной. Неглубокая копия означает, что некоторые (под-)значения все еще связаны с исходной переменной.
- Давайте разберемся в этом с помощью примера.
Пример —
let obj1 = {
a: 'a',
b: 'b',
c: {
d: 'd'
}
};
let obj2={...obj1}
obj2.c.d='f'
console.log(obj2)
console.log(obj1)
Выход-
{
a: "a",
b: "b",
c: {
d: "f"
}
}
{
a: "a",
b: "b",
c: {
d: "f"
}
}
Как вы можете видеть, новый объект все еще связан с исходным объектом, из которого он получил значение.
-
Проблема с поверхностным копированием заключается в том, что если пользователь вносит изменения в сложный объект (обновляет свойство street объекта адреса) объекта-источника
userName
, это также отражается в объекте назначения, поскольку он указывает на тот же адрес памяти и наоборот. -
Таким образом, мы переходим к глубокому копированию. Глубокое копирование означает, что значение новой переменной отсоединено от исходной переменной, в то время как поверхностное копирование означает, что некоторые значения все еще связаны с исходной переменной.
-
Давайте разберем глубокое копирование с помощью примера.
Пример —
Код —
let obj1 = {
a: 'a',
b: 'b',
c: {
d: 'd'
}
};
// converts obj1 to string and then parses it into a new object
let obj2 = JSON.parse(JSON.stringify(obj1))
obj2.c.d = 'f'
console.log(obj2)
console.log(obj1)
Выход-
{
a: "a",
b: "b",
c: {
d: "f"
}
}
{
a: "a",
b: "b",
c: {
d: "d"
}
}
- Здесь мы видим, что изменения, сделанные в
obj2
, не отражаются вobj1
, поэтому мы можем сказать, что это глубокая копия и два объекта не связаны.
Как сравнить два объекта, расположенных в разных местах памяти, но имеющих одинаковое значение?
-
Чтобы ответить на этот вопрос, я нашел эту тему Stack Overflow, которая безупречно отвечает на этот вопрос, и я не смог объяснить это лучше, чем добавив ссылку на эту тему: Stack Overflow
-
Если ссылка по какой-то причине не открывается, то вот самый быстрый и ограниченный способ сравнения значений объектов в разных местах памяти —
JSON.stringify(obj1) === JSON.stringify(obj2)
Кредиты — Mathwarehouse
Сложный вопрос для проверки знаний-
const number = 100
const string = "Jay"
let obj1 = {
value: "a"
}
let obj2 = {
value: "b"
}
let obj3 = obj2;
function change(number, string, obj1, obj2) {
number = number * 10;
string = "Pete";
obj1 = obj2;
obj2.value = "c";
}
change(number, string, obj1, obj2);
// guess which variables will get updated
console.log(number);
console.log(string);
console.log(obj1.value);
Выход —
100
Jay
a
Принуждение типов —
Принуждение типов — это автоматическое или неявное преобразование значений из одного типа данных в другой (например, строк в числа).
Кредиты — Счет
Пример-
Код-
const value1 = '5';
const value2 = 9;
let sum = value1 + value2;
console.log(sum);
Выход-
"59"
-
В приведенном выше примере JavaScript преобразовал 9 из числа в строку, а затем объединил эти два значения вместе, в результате чего получилась строка 59. У JavaScript был выбор между строкой и числом, и он решил использовать строку.
-
Компилятор мог бы преобразовать 5 в число и вернуть сумму 14, но он этого не сделал. Чтобы вернуть такой результат, вам придется явно преобразовать 5 в число с помощью метода
Number()
:
sum = Number(value1) + value2;
В качестве примера коэрцитивности типов на практике посмотрите сравнительную таблицу JavaScript, которая показывает, как ведет себя оператор свободного равенства ==
для различных типов.
Неявное и явное принуждение
-
Принуждение типов может быть явным и неявным.
-
Когда разработчик выражает намерение преобразовать тип путем написания соответствующего кода, например Number(value), это называется явным принуждением типа (или приведением типа).
-
Поскольку JavaScript является слабо типизированным языком, значения также могут преобразовываться между различными типами автоматически, и это называется неявным приведением типов.
Связь со мной —
- GitHub
Приложение-
- Advanced JavaScript Series — Часть 1: За кулисами (JavaScript Engine, ATS, скрытые классы, сборка мусора)
- Серия Advanced JavaScript — Часть 2: Контекст выполнения и стек вызовов
- Серия Advanced JavaScript — Часть 3: Странное поведение JS, строгий режим и подъем, временная мертвая зона
- Серия Advanced JavaScript — Часть 4.1: Глобальный, функциональный и блочный диапазоны, лексический и динамический диапазоны
- Серия Advanced JavaScript — часть 4.2: Цепочки диапазонов и их работа, лексическое и переменное окружение
- Advanced JavaScript Series — Часть 5: IIFE иamp; ключевое слово ‘this’ в JS (хитрые примеры), call(), apply(), bind(), Currying(Functional Prog)
- Advanced JavaScript Series — Часть 6.1: Все в JS является объектом? Странное поведение JS раскрыто, примитивные типы без примитивов
- Advanced JavaScript Series — часть 6.2: Передача по значению и передача по ссылке, мелкое и глубокое копирование, коэрцитивность типов
- Продвинутая серия JavaScript — Часть 7: Граждане первого сорта & Функции высшего порядка
- Серия Advanced JavaScript — Часть 8: 2 столпа ~ замыкания и наследование прототипов
- Серия Advanced JavaScript — Часть 9: Функции конструктора, объектно-ориентированный подход, ключевое слово
new
.
Ссылки-
- https://flexiple.com/javascript-pass-by-reference-or-value/
- https://developer.mozilla.org/en-US/docs/Glossary/Type_coercion
- https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/