Suggest an editImprove this articleRefine the answer for “Passing arguments by value or by reference”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**JavaScript always copies an argument at call time, but the outcome depends on the data type: primitives are copied in full (by value), while for objects, arrays and functions the reference to them is copied, so the function works with the very same object in memory.** That is why changing a property inside the function is visible outside, whereas reassigning the parameter itself is not. ```javascript let count = 10; const user = { name: "Alice" }; function change(x, obj) { x = 20; // only the copy of the primitive changes obj.name = "Bob"; // the shared object changes } change(count, user); console.log(count, user.name); // 10 "Bob" ``` **Key point:** technically JavaScript passes everything by value, it is just that for objects that value is a reference, so what travels is a copy of the reference.Shown above the full answer for quick recall.Answer (EN)Image**When we pass arguments into a function, JavaScript copies them, and how exactly it copies depends on the data type: primitives are copied by value, while objects, arrays and functions are passed by reference, or more precisely by a copy of the reference.** That is why some changes made inside a function are visible outside and others disappear with the call. ## Theory ### TL;DR - Primitives (`number`, `string`, `boolean`, `null`, `undefined`, `symbol`, `bigint`) are passed **by value**: the parameter gets a full copy. - Objects, arrays and functions are passed **by reference**, that is, the parameter gets a copy of the reference to the same region of memory. - Changing the **contents** of an object inside a function (`obj.name = "Bob"`, `arr.push(4)`) is visible in the original. - **Reassigning** the parameter (`obj = {...}`, `arr = [...]`) does not touch the original, because only the local copy of the reference changes. - Strictly speaking, JavaScript always passes by value: for objects that value is a reference. ### Quick example ```javascript let a = 10; function changeValue(x) { x = 20; // we change the copy } changeValue(a); console.log(a); // 10 ``` The value of `a` did not change, because only its copy was written into `x`. ### Passing by value Primitives, that is numbers, strings, booleans, `null`, `undefined`, `symbol` and `bigint`, are copied **in full**. | Data type | How it is passed | | --- | --- | | Primitives (numbers, strings, booleans, `null`, `undefined`, `symbol`, `bigint`) | **by value** | | Objects, arrays, functions | **by reference (more precisely, by a copy of the reference)** | Explanation for the example above: - A **copy** of the value of `a` is written into `x`. - Changing `x` has no effect on `a` whatsoever. In memory it looks like this: ```text a -> 10 x -> 10 (copy) ``` ### Passing by reference Objects, arrays and functions are not copied whole. Instead, a **reference to their address in memory** is passed. ```javascript const user = { name: "Alice" }; function rename(obj) { obj.name = "Bob"; } rename(user); console.log(user.name); // "Bob" ``` Explanation: - The variable `user` holds a **reference** to the object in memory. - That same reference is copied into `obj`, so both variables point to one and the same object. - Changes made through `obj` are visible through `user` as well. In memory it looks like this: ```text user --+ v { name: "Bob" } ^ obj ---+ ``` ### Reassigning the reference inside a function If you change the reference itself inside the function, the original stays untouched. ```javascript const user = { name: "Alice" }; function reassign(obj) { obj = { name: "Charlie" }; // a new reference } reassign(user); console.log(user.name); // "Alice" ``` What happens here: - The reference to `user` is first copied into `obj`. - Then `obj` is redirected to a **new object**, while the original reference (`user`) stays the same. This is exactly the proof that a copy of the reference is passed, not the variable slot itself. ### Array example An array is an object too, so the same rules apply. Changing the contents is visible outside: ```javascript const numbers = [1, 2, 3]; function modify(arr) { arr.push(4); // we change the contents } modify(numbers); console.log(numbers); // [1, 2, 3, 4] ``` But reassigning the reference is not: ```javascript function modify(arr) { arr = [9, 9, 9]; // we create a new array } modify(numbers); console.log(numbers); // [1, 2, 3] ``` ### Summary and a simple analogy | Data type | How it is passed | Does a change inside the function affect the original? | | --- | --- | --- | | Primitives (`number`, `string`, `boolean`, `null`, `undefined`, `symbol`, `bigint`) | **By value** | No | | Objects, arrays, functions | **By reference (a copy of the reference)** | Yes, if the contents change | | Reassigning the parameter inside the function | A local copy | No | An analogy that works well in an interview: - **By value** is like handing over a photocopy of a sheet of paper: if you write something on your copy, the original does not change. - **By reference** is like handing over the address of a safe: both of you can open the same safe and change what is inside. ### Common mistakes - **Believing that JavaScript has true pass by reference.** It does not: a function cannot reassign the variable it was given. The accurate wording is "passing a copy of the reference", also known as call by sharing. - **Confusing mutation with reassignment.** `obj.name = "Bob"` changes the shared object, `obj = {...}` changes only the local parameter. - **Thinking that `const` protects against changes.** `const user = {...}` forbids reassigning `user`, but it does not forbid changing its properties inside a function. For that you need `Object.freeze` or a copy. - **Expecting a shallow copy to solve everything.** `{ ...user }` and `structuredClone` behave differently: the spread copies only the top level, so nested objects stay shared. - **Forgetting that a string is immutable.** A method such as `str.toUpperCase()` does not change the argument, it returns a new string that you have to assign.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.