This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 3 years ago.
I signed the variable bubbleL1 to 1, but why the first variable in the bubbles list, which is bubbleL1 still shows undefined? I know this maybe a stupid question, but I really don't know why.
let bubbleL1, bubbleL2, bubbleL3, bubbleR1, bubbleR2, bubbleR3;
let bubbles = [bubbleL1, bubbleL2, bubbleL3, bubbleR1, bubbleR2, bubbleR3];
bubbleL1 = 1;
console.log(bubbleL1) // 1
console.log(bubbles) // [undefined, undefined, undefined, undefined, undefined, undefined]
What I want is a list with a specific name for each item in it (for the declared reason, I really don't just use bubbles[0], bubbles[1]...)
Let's say we have a list named bubbles, and we also have six variables called bubbleL1, bubbleL2, bubbleL3, bubbleR1, bubbleR2, bubbleR3. I want to put all these six variables into the bubbles list, so later I can assign values to each variables that in the list, like this:
bubbles.forEach((bubble) => {
bubble = "something";
})
bubbleL1 is a primitive and therefore copied by value.
let x = 3;
let sum = x;
sum = 3 + 5;
console.log(x); // 3
Objects and arrays, on the other hand, will exhibit your expected copy-by-ref behavior:
let x = {a: 3};
let sum = x;
sum.a = 3 + 5;
console.log(x.a); // 8
Related
This question already has answers here:
Modifying a copy of a JavaScript object is causing the original object to change
(13 answers)
Closed 6 months ago.
var arr = []
var obj = {
a: undefined,
b: undefined,
c: undefined
}
var a = 0
while (a !== 100) {
arr.push(obj)
a++
}
var randNum
for (var i = 0; i < arr.length; i++) {
randNum = Math.floor(Math.random() * 2)
console.log(Math.floor(Math.random() * 2))
arr[i].a = Math.floor(Math.random() * 2)
arr[i].b = 5
}
console.log(arr)
When I console log arr, arr[n].a always equals one number, but thats not what I want, I want it to output a random number, like 0 or 1.
The issue is as VLAZ mentioned in their comment. To fully explore this, we need to understand reference vs. value types in JS.
Let's look at a simple program:
let a = 1;
let b = a;
a = 2;
console.log(b) // prints 1
This works because we're storing a simple, primitive type like a number. With more complex types like arrays and objects, we'll see different behavior.
let a = { foo: true, bar: true };
let b = a;
a.foo = false;
console.log(b) // prints { foo: false, bar: true }
This is because more complex types in JS like arrays and objects are passed by reference, not by value. In essence, this means that when we store an object using a variable, the variable is not storing the values, but rather a reference to the object's location in your machine's memory. Let's add comments to the above code for clarity.
// a stores a pointer to memory location A, where our object literal lives
let a = { foo: true, bar: true };
// b stores a pointer to memory location A
let b = a;
// change a value on the object in memory location A
a.foo = false;
// print the value in memory location A
console.log(b)
This reference vs value differentiation has to do with the complexities of managing memory when we have potentially large, dynamic objects, so JS does a bunch of low-level stuff for us behind the scenes and gives us a nice user-friendly syntax for instantiating a data type that would be more complicated to implement manually in a lower-level language. However, we still have to be aware of this difference.
The crux of your issue is that in each index of your array, you're storing a reference to the exact same object, so when you update one index, you're actually updating the value at the memory location the index is pointing to. Since all the indices are pointing to the same memory location, changing one behaves similarly to changing them all.
Fortunately, armed with this information we can simply devise a way to create a new object on each iteration, whether by copying the reference object or just passing an object literal to the Array.push() method. Here's a potential solution.
let arr = [];
for (let i = 0; i < 100; i++) {
// this "object literal" is defined when push is called, creating a new object on each iteration
arr.push({
a: Math.floor(Math.random() * 2),
b: 5,
c: undefined
});
}
This question already has answers here:
Are Javascript arrays sparse?
(7 answers)
JavaScript 'in' operator for `undefined` elements in Arrays
(3 answers)
What is "undefined x 1" in JavaScript?
(5 answers)
Ways to iterate over undefined in Arrays
(5 answers)
Closed 1 year ago.
I'm super interested in what the heck is going on the below code:
// 1.
let arr = [];
console.log(arr);
// []
// Totally ok and normal
// 2.
arr[5] = 404;
console.log(arr);
// (6) [empty * 5, 404]
// Absolutely nothing. it just works I know
// 3.
console.log(arr[0]);
// undefined
// No problem till here
// 4.
for (let idx in arr) {
console.log(idx);
}
// 5
// 5.
arr[0] = undefined
for (let idx in arr) {
console.log(idx);
}
// 0
// 5
// Wait, what?
Upon the step 3, arr[0] logged undefined and when I explicitly give a undefined to arr[0], it counted as an index in arr.
Can someone please explain this magic?
This question already has answers here:
Why is a semicolon needed here? [duplicate]
(1 answer)
Interesting error based on automatic semicolon insertion JS rules. Explanation required
(2 answers)
Use of semicolons in ES6 [duplicate]
(1 answer)
Closed 2 years ago.
Such as 2[a], whose value is undefined.
The code bellow will get an error Cannot access 'b' before initialization
let a = 1, b = 2
[a, b] = [b, a];
I know it caused by the missing semicolon after the b = 2. And after the semicolon has been added
let a = 1, b = 2;
[a, b] = [b, a];
It works fine. Is it caused by the square bracket after the number? If so, what is the meaning of it in javascript?
Is it caused by the square bracket after the number?
Yes.
If so, what is the meaning of it in javascript?
It's a property access operation, just like:
const array = [1, 2, 3];
const b = array[1];
// ^^^−−−−−−−−−−−−−−−−−−−−−−−−−
console.log(b); // 2
You can do property access operations on primitives, and in fact you often do. For instance, on a string primitive:
console.log("hi".toUpperCase()); // "HI"
// or
const fiftyFifty = Math.random() < 0.5;
const method = fiftyFifty ? "toUpperCase" : "toLowerCase";
console.log("Hi"[method]()); // "hi" or "HI"
Or using a number primitive:
console.log(2["toString"]()); // "2"
const n = 2;
console.log(n.toString()); // "2"
console.log(2..toString()); // "2"
When you do, the relevant prototype is used (String.prototype, Number.prototype, etc.) and in loose mode in some situations a temporary object is created (e.g., new String("hi") or new Number(2)).
This question already has answers here:
Why does JavaScript variable declaration at console results in "undefined" being printed?
(4 answers)
Closed 3 years ago.
When I write this in the console it's log undefined.
var obj = { first: 'lorem' };
But when I write this in the console it's log object.
var obj = { first: 'lorem' };
obj = { second: 'ipsum' };
Why is this happening?
The value you see being printed is the return value of the line of code you executed.
var obj = {first: 'lorem'};
returns undefined, whereas
obj = {second: 'ipsum'};
will return the object assigned to obj, hence {second: 'ipsum'} is printed.
This is why you can do things such as:
var a = b = 2;
Here the assignment of b = 2 will set b equal to 2, whilst also returning 2, thus setting a to 2
Anything you execute in the console, it will display the return value of it. When declaring and assigning variables, it will return undefined. When only assigning values to variables, that value is returned.
This question already has answers here:
Assign two variables to the same value with one expression? [duplicate]
(5 answers)
Closed 4 years ago.
In this situation:
(function() {
const a = b = 10;
})();
console.log('a:', a); // ReferenceError: a is not defined
console.log('b:', b); // 10
The b gets defined as a var in the global scope. Is it possible o do this equals trick but make b a const as well in the same scope? Just like a?
You could set b as a parameter to your IIFE function. That way b won't be accessible outside of function scope.
(function(b) {
const a = b = 10;
console.log(b)
})();
console.log('b:', b);
I don't think so. This "trick" is possible because b = 10 returns 10. However, const b = 10 returns undefined.
Why not just use:
const a = 10;
const b = a;
?
It's not slower, and it's more readable, even if you could nest the assignments I don't really see a reason to do it