So far this is my thought process:
In JS primitives are pass by value, and objects are pass by reference.
let var1 = 10 // var1 is assigned a reference to the primitive 10
let var2 = var1 // var1 is evaluated to the primitive 10, var2 is assigned a reference to the primitive 10
// var1 and var2 are independent. This is pass by value
const obj1 = {} // obj1 is given a reference to the object created in memory by the object literal
const obj2 = obj1 // obj2 is given a reference to the exact same object obj1 is pointing to
// obj1 and ob2 are pointing to the same object, they are not independent variables. This is pass by reference
What I am confused about is closures. In closures, it seems that everything is passed by reference. Even variables that are referencing primitives.
function func() {
let a = 0;
return [
function () {
a ;
return a;
},
function () {
a ;
return a;
},
];
}
const [a, b] = func();
console.log(a(), b()); //will result in logging 1, 2
In this example the func defines a local variable a to 0, then includes it in the closure of 2 anonymous functions that are being returned. Then by mutating a from either function, its clear that they are referencing the same spot in memory.
Previously I had thought both functions just created an unaccessable object to store its closure in and copied over the variables. If this was the case then the variables would be copied by value, and each anonymous function would have a variable named a in their closure that referenced the primitive 0. Then you could safely mutate a in each function.
But now it's clear that instead, the functions have a reference to the actual variable a that was defined when func was executed.
Is my understanding of how closures work correct? And is there any other way to reference a variable itself, instead of the primitive that it points to?
CodePudding user response:
But now it's clear that instead, the functions have a reference to the actual variable a that was defined when func was executed.
That is a correct thought. A JS function keeps a 'reference' to an outer scope (a scope where a function is created) in its closure and access to that scope have all functions which were created in it.
Below example is similar to yours. Access to a global variable is possible due to closures:
let gl = 100;
function f(){
gl ;
return gl
}
function g(){
gl ;
return gl
}
f();
g();
gl;
CodePudding user response:
In JS primitives are pass by value, and objects are pass by reference.
The concept "pass by reference" is not applicable in JavaScript. Pass by reference would mean that you could design a function func
such that the following could happen:
let a = {};
let b = a;
func(a);
if (a !== b) console.log("This will not happen. This is not C ");
This is only possible in languages that support "pass by reference". Not so in JavaScript.
In JavaScript, objects are references, and they get passed by value just as any other value is passed by value. It can be confusing that in JavaScript-land the term "object" is used both for the reference and for the referenced "struct".
obj1 and ob2 are pointing to the same object, they are not independent variables. This is pass by reference
No, this is not the concept of "pass by reference". Even though obj1
and obj2
are pointing to the same object there are independent variables. Whether or not these two variables are object types or not, you can assign a different value to one of those variables and that will not affect the other.
Objects have the distinguished feature that they can be mutated, but that is another concept. Primitives cannot be mutated -- they are immutable. This has nothing to do with the concept of "pass by reference" which is not applicable to JavaScript.
In closures, it seems that everything is passed by reference. Even variables that are referencing primitives.
In your example the variable a
is not referencing a primitive, its value is a primitive. In your example, there is only one variable a
, and it can be accessed by the function func
, and by the two anonymous functions. There is no "pass by <something>" happening anywhere here.
In this example the func defines a local variable a to 0, then includes it in the closure of 2 anonymous functions that are being returned.
I wouldn't use the term "includes" here. It is just that functions have access to the outer scope they are defined in, and in this case that means the two anonymous functions have access to the scope of func
, which includes the variable a
.
But now it's clear that instead, the functions have a reference to the actual variable
a
that was defined whenfunc
was executed.
Their access to a
is the same as the access that the code in func
has to that variable. There is no difference.
And is there any other way to reference a variable itself, instead of the primitive that it points to?
Referencing a variable and not its value is exactly what object properties offer. Object properties are names that identify the property.
For example:
const myVars = { "a": 1, "b": 2 };
Now I have a reference to that property, and I could even keep that in a variable:
let prop = "a";
Now I have a variable for the name and can use it to retrieve the value:
console.log(prop); // a
console.log(myVars[prop]); // 1
I can change prop
to refer to the other property:
prop = "b";
console.log(prop); // b
console.log(myVars[prop]); // 2
So you could say that with prop
I have a reference to a primitive value.