Строки, числа, логические значения передаются в функцию по значению. Иными словами при передаче значения в функцию, эта функция получает копию данного значения. Рассмотрим, что это значит в практическом плане:
function change(x){
x = 2 * x;
console.log("x in change:", x);
}
let n = 10;
console.log("n before change:", n); // n before change: 10
change(n); // x in change: 20
console.log("n after change:", n); // n after change: 10
Функция change получает некоторое число и увеличивает его в два раза. При вызове функции change ей передается число n. Однако после вызова функции мы видим, что число n не изменилось, хотя в самой функции произошло увеличение значения параметра. Потому что при вызове функция change получает копию значения переменной n. И любые изменения с этой копией никак не затрагивают саму переменную n. В итоге мы получим следующий вывод в консоли браузера
n before change: 10 x in change: 20 n after change: 10
Объекты и массивы представляют ссылочные типы. То есть переменная или константы, которая представляет объект или массив, по сути хранит ссылку или иными словами указатель, которые указывают на адрес в памяти, где хранится объект. Например:
let bob ={
name: "Bob"
};
Переменная bob формально хранит объект, в котором определено одно поле name. Фактически же переменная bob хранит ссылку на объект, который расположен где-то в памяти.
И ссылочные типы - объекты и массивы передаются в функцию по ссылке. То есть функция получает копию ссылки на объект, а не копию самого объекта.
function change(user){
user.name = "Tom";
}
let bob ={
name: "Bob"
};
console.log("before change:", bob.name); // Bob
change(bob);
console.log("after change:", bob.name); // Tom
В данном случае функция change получает некоторый объект и меняет его свойство name. При вызове этой функции в нее передается значение переменной bob:
change(bob);
Но поскольку переменная bob представляет объект и хранит ссылку на некоторый объект в памяти, то функция change получае копию этой ссылки, которая указывает на тот же объект в памяти, что и переменная bob.
В итоге мы увидим, что после вызова функции изменился оригинальный объект bob, который передавался в функцию.
before change: Bob after change: Tom
Однако если мы попробуем переустановить объект или массив полностью, оригинальное значение не изменится.
function change(user){
// полная переустановка объекта
user= { name:"Tom" };
}
let bob ={
name: "Bob"
};
console.log("before change:", bob.name); // Bob
change(bob);
console.log("after change:", bob.name); // Bob
Почему здесь данные не изменяются? Потому что, как писалось выше, функция получает копию ссылки. То есть при передачи в функцию параметру user значения переменной bob:
change(bob);
Переменная bob и параметр user представляют две разные ссылки, но которые указывают на один и тот же объект.
При присвоении параметру в функции другого объекта:
user= { name:"Tom" };
ссылка user начиначет указывать на другой объект в памяти. То есть после этого bob и user - две разные ссылки, которые указывают на два разных объекта в памяти.
То же самое касается массивов:
function change(array){
array[0] = 8;
}
function changeFull(array){
array = [9, 8, 7];
}
let numbers = [1, 2, 3];
console.log("before change:", numbers); // [1, 2, 3]
change(numbers);
console.log("after change:", numbers); // [8, 2, 3]
changeFull(numbers);
console.log("after changeFull:", numbers); // [8, 2, 3]