Строки, числа, логические значения передаются в функцию по значению. Иными словами при передаче значения в функцию, эта функция получает копию данного значения. Рассмотрим, что это значит в практическом плане:
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]