preface
The main reference for this article is JavaScript Advanced Programming.
To be clear: function arguments in JavaScript can only be passed by value. Most of the time, the reason this statement is confusing is largely because JavaScript has two ways of accessing variables: by value and by reference, so it’s easy to assume that function parameters are also passed by value and by reference. But, actually, it’s not.
Knowledge review
Before giving examples, we need to review a few points:
- Copy the difference between a base type value and a reference type value from one variable to another.
- Copying a value of a primitive type from one variable to another creates a new value on the variable object, and then copies that value to the location allocated for the new variable. Look at the following example:
let val = 10;
let val2 = val;
Copy the code
The variable val holds the value 5. When we copy the value of val to the variable val2, it also holds the value 5. But the two variables are completely independent and unknown, and the value of val2 is just a copy of the value of val. After that, whatever you do to these two variables, they won’t affect each other. The following figure shows the process of copying primitive type values.
- Same as copying primitive type values. When you copy a value of a reference type from one variable to another, you still make a copy of the value stored in the variable object into the space allocated for the new variable. The difference, however, is that a copy of this value is a pointer to an object stored in the heap. In other words, these two variables refer to the same object, and if you change either of them, the other will be affected.
let objVal = {
name: 'hello'
};
let objVal2 = objVal;
objVal2.name = 'ha ha';
console.log(objVal.name); / / ha ha
Copy the code
Define the variable objVal to hold an object that has a name attribute with a value of ‘hello’. Then, copy the variable objVal to the variable objVal2 and change the name property value. Since these two variables refer to the same object. So, objVal accesses the name property and gets the modified value of objVal2. The following figure shows this relationship between variables stored in variable objects and objects stored in the heap.
For example
Note tips:
-
When a function argument passes a value of the primitive type, the passed value is copied to a local variable (that is, a named parameter, or an element in the Arguments object in the ECMAScript concept).
-
When a function argument passes a value of a reference type, the value’s memory address is copied to a local variable, which is immediately reflected outside the function whenever it changes.
Look at this example:
function changeNum(val) {
val = val + 10;
return val;
}
let num = 10;
let result = changeNum(num);
console.log(num); / / 10
console.log(result); / / 20
Copy the code
Specific process:
-
Call the changeNum() function and pass the variable num as an argument to it. The value of this variable is copied to the parameter val, which is local to the function.
-
Inside the changeNum() function, the parameter val is incremented by 10 and then assigned to.
-
Returns the reassigned parameter val.
However, changes inside the function do not affect the num variable outside the function. Because copying a value of a primitive type from one variable to another creates a new value on the variable object, and then copies that value to the location allocated for the new variable. That is, the parameter val and the variable num simply have the same value; they are completely independent and do not know each other.
Here’s another example:
function getBookName(obj) {
obj.name = Js Little Red Book;
}
const book = Object.create(null);
getBookName(book);
console.log(book.name); // Js little Red Book
Copy the code
Specific process:
-
Define the getBookName() function, which takes a parameter (reference type) obj and adds the name attribute to it.
-
Use object.create (null) to create an empty Object and store it in the variable book.
-
Call getBookName() and pass the variable book as an argument to the function, that is, copy it to obj.
-
Add and assign the name attribute to obj inside the function.
This is because when a function argument passes a value of a reference type, it copies the value’s memory address to a local variable, which is immediately reflected outside the function whenever it changes. So, when you add the name attribute to obj inside the function, book outside the function is reflected.
Most developers assume that parameters are passed by reference because they see that objects modified in the local scope are reflected in the global scope. But in fact, this is the wrong perception. To prove that objects are passed by value, let’s modify this example:
function getBookName(obj) {
obj.name = Js Little Red Book;
obj = Object.create(null);
obj.name = "Js Rhino Book";
}
const book = Object.create(null);
getBookName(book);
console.log(book.name); // Js little Red Book
Copy the code
The obvious change to this example is the addition of two lines of code to the getBookName() function in the previous example:
obj = Object.create(null); // Redefine an object for obj
obj.name = 'Js Rhino Book '; // Define a name attribute with different values for the new obj object
Copy the code
Specific process (steps 1 — 4 are the same as the previous example) :
- using
Object.create(null)
Create a new object and assign it to the variable obj with its name attribute set to ‘Js rhino book ‘.
If book is passed by reference, then book should point to a new object whose name attribute value is ‘Js rhino book ‘. However, when we access book.name again, the value is still ‘Js Little Red book ‘. This tells us that even if you change the value of a parameter inside a function, its original reference remains the same. Note also that when we redefine obj inside a function, it becomes a variable that refers to a local object. Once the function completes, it is immediately destroyed.