Brackets in variable initialization - javascript

I've made an experiment in JavaScript:
var x=[ "1","2","3","4","5","6"];
c=(b = x)[2] ; //<--- what is this syntax?
alert(b ); // 1,2,3,4,5,6
alert(c ); // 3
I figured it out how it works. It saves me a line of equalization. Still, I was wondering about this strange syntax. How is it called and where can I read about it?

= operator returns a value being assigned so (b = x) returns value of x. That results in x[2] being assigned to c.
(note: "returns x" changed to "returns value of x" according to comments)

See below
b=x assigning the data of x to b and hence you are getting alert as 1,2,3,4,5,6
c=(b=x)[2] is displaying the second content of array i.e. 3.
Below is how c=(b=x)[2] works
c=(b=x)[2]
b=x
c=b[2]
let me know if you need further details...

this happens because of an assigment operator returns value in java script.
Think about it like this:
You make an assignment:
b = x;
Now in object oriented terms, its like invoking a method = on b with an x as an argument
b.=(x)
Here the '=' is like a method name
Now if its the method, why it can't return a value (its return type is other than void)?
Here you can find some additional explanation about this:
Link1
Link2
Hope this helps

var x = ["1","2","3","4","5","6"];
c=(b = x)[2]; // b = x; -> shallow copy of the array
// b -> now hods the array of x
// b[2] -> get the second element of the array
alert(b ); // b is pointing to the array
alert(c ); // c has the 3-rd element (array counting is from 0 - 0,1,2)
b.push("7"); // we add a new item to the array
alert(b); // 1,2,3,4,5,6
alert(x); //1,2,3,4,5,6,7 !

The same code can be written as:
var x = b = ["1","2","3","4","5","6"], c = b[2];
console.log(b); //=> 1,2,3,4,5,6
console.log(c); //=> 3
Or even:
var c = (x = b = ["1","2","3","4","5","6"])[2];
console.log(b); //=> 1,2,3,4,5,6
console.log(c); //=> 3
In var c = (b=x)[2], the parentheses force b=x to execute first. In both cases anyhow, when for example used within a function scope, the statement would create variable b in the global scope, so I would consider it bad practice.

Related

Arrays contain value call by Reference so their pointer should turn same values and equate to true

As far as I know, the arrays and objects always act as pointers and just point to somewhere a memory location.
In the following example, as var a is updated, so as b pointing to same memory location as a, should also be updated and final answer should be true, true.
Why is it not happening??? At what instance of time, b gets a different pointer than a and why???
Example:
var a = [2,3,5];
var b = a;
a = [33,45];
console.log(a,b);
console.log(a==b,a===b);
However, to support my clause kindly look at following unchanged values example. Here I am sure both a and b point to same memory location containing data as [2,3,5]. They got same values and are always equated as true.
var a = [2,3,5];
var b = a;
console.log(a==b,a===b);
Because you are not updating the reference of the new object [33, 45].
Following code might help you understand better.
a = [{'a': 1}, {'b': 2}];
b = a;
console.log(a, b);
// creates new object and assigns to the same variable
b = b.concat ([{'c': 3}]);
console.log(a, b);
// but property of object is still referenced in by a and b
b[0].a = 100;
console.log(a,b);
a[2].c = 100; // throws exception, because 'a' does not have the reference to object which refers the object created in 'b'
console.log(a,b);
look at blow:
var a = [2,3,5];
var b = a;
and after the a = [33,45];
the pointer is point to a new obj, not the obj changed

Will the reference of an object passed into a function as a parameter change?

Why is a.y undefined after I change the reference of a in the function?
var a = { x : 1 };
a = { y : 2 };
function _change(b) {
b = { y : 3 };
return b;
}
_change(a);
document.write(a.y); // undefined
document.write(a.x); //1
And the below code behaves differently
var a = {x:1};
var b={y:1};
b=a;
a.x //undefined
a.y //1
Why?
Because you're totally changing the a object {x:1} with {y:2} so there's no x property in a object.
What I think is you need to use like this:
var a = {x:1};
a.y = 2;//assign y = 2 in a oject.
So, do the same manner in your change function.
First Block
This is what I get by running the code line by line:
var a = {x:1}; // <-- sets a to the object {x:1}
a = {y:2}; // <-- sets a to the object {y:2}, so it no longer has a.x = 1
function _change(b)
{
b= { y:3};
return b;
}
_change(a); // <-- this doesn't change a, it returns {y: 3} but it is not used
document.write(a.y); // 2 actually
document.write(a.x); // undefined
Let's try to understand it...
var a = {x:1};
There you declare the variable a, you create an object {x:1}, and set a to that object.
a = {y:2};
There you create a new object {y:2} and set a to it. So a no longer has the first object.
So... when you ask for a.y it has 2, and when you ask for a.x it is undefined because the object {y:2} doesn't have x. Remember that you replaced the object of the variable a from being {x:1} to {y:2}.
Instead you can add fields on the fly, like this:
var a = {x:1}; // <-- sets a to the object {x:1}
a.y = 2; // <-- Add a field y to the object of the variable a, it has the value 2
function _change(b)
{
b.y = 3; // <-- actually modify the object, now the field y has value 3
return b;
}
_change(a);
document.write(a.y); // 3
document.write(a.x); // 1
Second Block
Again, I get a different result than you... I wonder where are you running your code.
var a = {x:1}; // <-- sets a to the object {x:1}
var b={y:1}; // <-- sets b to the object {y:1}
b=a; // <-- now sets b to the object {x:1} - nobody has {y:1} anymore
document.write(a.x); // 1 actually
document.write(a.y); // undefined
Ok, so when you say b=a you are making the variable b to point to the same object as the variable a. By doing so, the variable b no longer points to the object {x:1}... which is irrelevant because you are not using the variable b anyway.
The variable a had {x:1} all along, and you can see it doesn't have any field y defined.
It seems to be that you believe that assigning an object somehow fuses the objects, resulting in both sides having a combination of the fields... if you intend to do that, you may be interested in How can I merge properties of two JavaScript objects dynamically?.
You need to break this down and understand the variables in different lexical scopes.
a in the global lexical scope:
var a = {x:1};
a = {y:2};
The above initialization would resolve to:
a = {y:2};
//hence at this global lexical scope
//`lexicalscope = {"a":{y:2}};`
Now, let us see the variables inside the lexical scope of the function:
function _change(b){
// at the function's `lexicalEnvironment = {"b":{y:2}}`
b= { y:3};
// at this point `lexicalEnvironment = {"b":{y:3}}`
return b; //returned {y:3}.
}
When the function is invoked with a as its parameter.
_change(a); // obtained {y:3} but not captured.
I would love to include the beautiful explanation for why the value of a does not change outside the scope of the function in this answer here, but, do not want to duplicate the original answer. Would like to share the relevant part though,
In practical terms, this means that if you change the parameter itself (as with a),
that won't affect the item that was fed
into the parameter. But if you change the INTERNALS of the parameter, such as b.y = 3,
that will propagate back up.
Again, printing their values in the global lexical scope.
console.log(a.y); // still in the global lexical environment a.y = 2;
console.log(a.x); // `a.x` is undefined in the global Lexical Environment.

Understanding pass by reference vs value with functions

As I understand objects are passed by reference in JavaScript (and primitives are passed by value?).
var a, b;
a = {
Foo: "Bar"
}
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
This worked similarly with arrays but did not work like I expect with functions:
var a, b;
a = function(){ return 20; }
b = a;
a = function(){ return 40; }
console.log(b()); // returns 20 ?
I'm confused because I thought functions are objects. Shouldn't the above example return 40?
In the first case, a.Foo = ..., You are changing the value of a property in the object, referred by both a and b. This is called mutating an object.
But in the second case, you are making a refer a new function object. Now, a and b are referring to different function objects.
That is why you are getting 20 in the second case.
First regarding the question in the title (which is actually different from what you demonstrate with the code examples):
"As I understand objects are passed by reference in JavaScript"
No, Javascript doesn't support passing parameter by reference at all. All parameters are passed by value, but the value can be a reference.
Example:
var a = { answer: 42 };
function f(x) {
alert(x.answer); // shows 42
x = { answer: 0 };
alert(x.answer); // shows 0
}
f(a);
alert(a.answer); // shows 42
As the parameter is passed by value, the variable x is separate from the variable a, so assigning a new object to x doesn't change the value of a.
Back to your code:
When you assign an object reference from a variable to another, it's the reference that is copied, not the object. You get two variables that reference the same object.
Either of the variables can be used to access members in the object, which your first code example demonstrates.
If you assign a new object to the first variable, you will replace the reference in the variable, you will not overwrite the object that it currently points to. The object is still intact, and the second variable still points to it. You get two variables that point to one object each, which your second code example demonstrates.
Further to #thefoutheye's answer, consider the following proof of your statement functions are objects:
var a, b;
a = function() { return 20; }
a.Foo = "Bar";
b = a;
a.Foo = "Other";
console.log(b.Foo); // "Other"
You are reassigning the variable a to a new function. That's not the same as changing a property value.
Try:
var a, b;
a = {Foo: function() {return 20;}};
b = a;
a.Foo = function() {return 40;};
console.log(b()); // returns 40

how does this two varibles exchange using one line? [duplicate]

This question already has answers here:
How does [b][b = a,0] swap between a and b?
(2 answers)
Closed 9 years ago.
I do not know how to learn demo 2,because it's difficult for me.
//demo1.js
var a = 1;
var b = 2;
var c;
c = b;
b = a;
a = c;
log(a); // a = 2
log(b); // b = 1 I can read this one.
//demo 2.js
var a = 1, b = 2;
a = [b][b = a, 0]; // why? '0' is a varible?
console.log(a,b) //output a = 2, b =1
// v---- 1. v---- 3.
a = [b][b = a, 0];
// ^---^-- 2.
Put the value of the b variable in a new Array.
The next set of square brackets is the member operator used for getting the index. In this case, that space is being used to reassign the value of the a variable to the b variable. This can be done because the original value of b is safely in the Array (from step 1.).
Separated by comma operator, the 0 index is then used as the actual value of the Array being retrieved, which if you'll recall is the original b value. This is then assigned to a via the first = assignment on the line.
So to summarize, b is put in the Array, and is retrieved via the 0 index and assigned to a on the left, but not before a is assigned to b (borrowing the space of the [] member operator).
This could also be written like this:
a = [b, b = a][0];
Only difference now is that the second index of the Array is used to do the assignment. Probably a little clearer like this.
The comma operator in Javascript evaluates its left operand, throws it away and returns its right operand after evaluating. Its only use is when the left operand has a side-effect (like modifying a variable's value) but you don't want its result.
[b] defines an array containing b.
[b = a, 0] evaluates b = a - so b now contains the value of a. Then it throws it away. Then it takes the element at index 0 of [b] - returning b. a now contains the value of b that was stored there, rather than the up-to-date value of b, so our swap is successful (albeit obfuscated).

How does [b][b = a,0] swap between a and b?

As gdoron pointed out,
var a = "a";
var b = "b";
a = [b][b = a,0];
Will swap a and b, and although it looks a bit of hacky, it has triggered my curiosity and I am very curious at how it works. It doesn't make any sense to me.
var a = "a";
var b = "b";
a = [b][b = a, 0];
Let's break the last line into pieces:
[b] // Puts b in an array - a safe place for the swap.
[b = a] // Assign a in b
[b = a,0] // Assign a in b and return the later expression - 0 with the comma operator.
so finally it is a =[b][0] - the first object in the [b] array => b assigned to a
Live DEMO
read #am not I am comments in this question:
When is the comma operator useful?
It's his code...
It might help (or hinder) to think of it terms of the semantically equivalent lambda construction (here, parameter c takes the place of element 0):
a = (function(c) { b = a; return c; })(b);

Categories

Resources