I'm reading some code and I see a comparison that's laid out like this:
a = b = c
Seeing as how searching Javascript about equal or comparison yields remedial results, anyone care to explain what's going on?
EDIT: These are all objects or object properties that we're talking about here, should have specified.
DOUBLE EDIT: This is inside of an Object.defineProperties() block.
= is an operator. It takes two arguments: a variable reference and an expression. It assigns the value of the expression to the variable, and returns the assigned value.
As a result, you can chain them and it equates to this:
a = (b = c)
In other words, assign b to the value of c, then assign that value to a also.
a = b = c is just shorthand expression for:
b = c;
a = b;
if(a = b) will always return true because it is assigning, instead of comparing. To compare, the statement should read: if(a == b).
The = operator associates right-to-left and evaluates to the value that was assigned.
So this:
a = b = c;
Means this*:
b = c;
a = c;
* Unless you're dealing with properties.
That is not a comparison. It is an assignment of the value of c to the b and a variables.
Assignment works right to left, so it is an assignment of c to b first. Then the return value of that operation is assigned to a.
The return value of an assignment operation is the value that was assigned, so a will get the same value assigned to b.
It equates this;
b = c; a = b;
Related
I am looking for a way to check if two variables refer to the same object in javascript.
ex:
var a = {foo:"bar"};
var b = {foo:"bar"};
var aa = a;
testSame(a, b); //false
testSame(a, aa); //true
var r = "a string";
var s = "a string";
var rr = r;
testSame(r, s); //false
testSame(r, rr); //true
So far there doesn't seem to be a way of getting a way of doing this.
edit: testSame() is not a real function it would be the hypothetical solution.
edit: The answer to the question How to check if two vars have the same reference? does not answer this question as it uses the strict equality operator (===) which does not differentiate between between 2 vars pointing to 2 instances of an identical string.
Just comparing with == or === will do the trick, except for strings. There's no way to do what you ask with strings.
var a = {foo:"bar"};
var b = {foo:"bar"};
var aa = a;
testSame(a, b); //false
testSame(a, aa); //true
var r = "a string";
var s = "a string";
var rr = r;
testSame(r, s); // false <-- this will be true
testSame(r, rr); //true
function testSame(a, b) {
console.log(a === b);
}
The question is correct, but there is a trick in it. The following console code snippet reveals it:
const A = "abc", B = new String(A), C = B
> A == B
true
> A === B
false
> B === C
true
Variable A refers integral primitive that is converted to String object on a demand. JS machine may optimize references to equal primitive strings defined in the code to target exactly the same block of RAM — that's why the question, as defined, has no solution.
You need to manually wrap each integral value to corresponding object class: String, Number, Boolean, — and test them with === operator:
var r = new String("a string");
var s = new String("a string");
var rr = r;
I've applied this trick to track the initially empty controlled input in React, — whether the user had edited it and then erased to be clear, — without involving additional field in the state.
Here's how things work. First, in this code:
var a = {foo:"bar"};
var b = {foo:"bar"};
the variables a and b are initialized with references to two different objects. Thus comparisons with either == or === will report them as being different (i.e., not equal).
Here, however:
var a = "some string";
var b = "some string";
the two variables are initialized to refer to strings that are identical. String values in JavaScript are not objects — they're primitives. Comparisons between a and b with either == or === will therefore return true because the strings are the same. This is exactly the same as things would have been if the variables had been initialized like this:
var a = 17;
var b = 17;
Numbers and strings are primitives, so comparison compares the semantic values of the primitives. Objects, however, are not primitives, and comparison of objects is based on object identity.
It literally is nonsensical in the JavaScript semantic domain to want to know whether two variables pointing to the same identical string refer to two different expressions of that same string, in precisely the same way as it would be nonsensical to want to know whether one 17 were different from another.
This one is already answered in this question:
How to check if two vars have the same reference?
The short version use === instead of ==
As I understand it, === checks the identity of the object. Javascript's strings are immutable, so when you say
var x = "string"
vay y = "string"
x and y are actually referencing the same object in memory. So, unfortunately, what you want is impossible. Symbols provide this functionality:
Symbol('x') === Symbol('x') // => false
This snippet of JavaScript code alerts 1 as answer. Can anyone please explain how this code executes?
const b = [1,2,3];
const f = (a, ...b) => a+b;
alert( f( 1 ) );
There are a couple of things going on here. The main one is that you're shadowing b, so the b outside the function isn't used within it. Instead, within it, you're creating a new array (because you've used a rest parameter, ...b) and assigning it to the b parameter. Since you call f with just one parameter, that array is empty. 1+[] is "1" because when either of the operands to + isn't a primitive (arrays aren't primitives), it's coerced to a primitive, and coercing an array to a primitive (indirectly) results in doing a .join(",") on the array. With a blank array, .join(",") is "". Then, since one of the operands is a string, the other operand (1) is coerced to string ("1") and it does "1"+"" which is, of course, "1". (Details on that last bit in the spec.)
f(1) is the same as 1 + []
f(1,2,3) is the same as 1 + [2, 3]
That's all...
The first line const b = [1,2,3]; is not used because the b in the lambda expression is the argument, not the constant declared before.
You can reference variables in a function call, however, when you define a function expression, the parameters name do not refer to any variables.
You'll get the expected result if you call the function like this:
alert(f(1, b));
It takes the rest parameters ... as an array b.
While this is empty, it is converted to an empty string and both operands are treated as string, because if one is a string, then it adds all values as string.
The result is '1'.
const b = [1, 2, 3];
const f = (a, ...b) => a + '';
console.log(typeof f(1));
Reproducing this in my browser's development tools console looks like this:
> b = [1,2,3]
> f = (a, ...b) => a+b
> f(1)
< "1"
// so it results in the string 1, why's that?
// lets try logging what a and b are in the function
> g = (a, ...b) => console.log("a=%o, b=%o", a, b)
> g(1)
< a=1, b=[]
// ah, so b is an array, which is what the spread operator does
// (gathers all remaining arguments into an array, so the question
// is then what does JavaScript return for the number 1 added to an empty array?
> 1 + []
< "1"
This behavior is one of the many quirks of JavaScript when using the + operator on different types.
Sometimes in the internet I see a syntax that is strange to me. Something like:
console.log = console.error = console.info = console.debug = console.warn = console.trace = function() {}
How does this "equal" sequence work?
Thanks.
An assignment operator assigns a value to its left operand based on the value of its right operand.
Consider:
a = b = c = d = 5;
The expression is resolved right to left so:
d = 5 and c = d (which is 5), b = c (5) and so on.
In your example those console methods are all being (re)defined as an empty function.
See: MDN: Assignment Operators for more info.
With assignments, the operations are resolved from right to left. So the right most value will be populated into all the preceding variables.
What you describe can be easily explained by analogy using a simpler example:
// Normal variable assignment
var a, b;
a = 15;
b = 15;
console.log("a: "+a+" , b: "+b);
// Assing the same value to two variables
var c, d;
c = d = 15;
console.log("c: "+c+" , d: "+d);
// Assign the same value to two variables and make it a function
var e, f;
e = f = function(){ console.log("Hi!"); };
// Call both of the variables' functions
e(); f();
Starting from variables a and b, you then go to c and d that are given the same value. The takeaway here is that you can assign the same value to two variables and the expression will be evaluated from right to left, so in effect it's like assigning the two variables' values separately. However, this does not mean that chaning one will change the other as well.
Finally, see what happens with e and f. These are assigned a function instead of a value, so you can then call them as if they were functions.
Short version: Expression gets resolved from right to left. The assignment is by value, not by reference, meaning that changing one of the variables' value will not affect the others. Finally, if you assign a function to your variables, you can then use their names to call the function that is their value.
Just read on Javascript book by David Flanagan this case:
(a = b) == 0
But I can't see the use of this. Could be like this?
var b = 0;
var a = b;
if (a == 0) ...
Thanks
Your interpretation is correct. The assignment returns the assigned value.
It just assigns b to a. If b (and consequently a) is 0, the condition is true.
It's evaluated in this order:
(a = b) == 0
-------
^ assign the value of b to a
------------
Check if the value of a equals 0
Pretty much it's the same with:
a = b;
if (a == 0) {
// do something
}
It's just a shorter version. Don't forget to declare the variables, otherwise they will be appended to the global namespace.
This is the short form. Means:
Assign b to a
Then compare the value.
(a = b) assigns b to a and is furthermore an expression with the new value of a.
So (a = b) == 0 is an expression that assigns b to a and is evaluates its relational equality to 0.
In C and C++ you'll often see it written as if (!(a = b)). Some folk find such a form obfuscating as it's a stone's-throw away from the considerably different if(!(a == b)).
Looking at var a=b=1; , I already know that both a and b has the same value.
But my question is :
Does the a gets its value from 1 or from b ?
I made a small test :
/*1*/ (function (){
/*2*/ var j = window.j = function (){ alert('3');};
/*3*/ window.j2 = j;
/*4*/ })();
/*5*/
/*6*/ window.j(); //3
/*7*/ window.j=null;
/*8*/ window.j2();//3
As you can see line #8 yields 3 so I persume that a is not having the value of b but the value of 1.
Am I right ?
visualize :
(function (){
var j = window.j = function (){ alert('3');};
|
| ^ ^
| | | //which one ?
+----------+--------+
})();
Assignment in javascript works from right to left. So you are getting your value from window.j. Re-setting window.j will not affect the result because Javascript variables always passes by value, exception is array or object.
Example of passing value by ref in JS object:
var obj = { x: 2 };
var anotherObj = obj;
anotherObj.x++;
alert(obj.x); //3
You can find more information here.
More useful examples available in this answer.
The "=" operator associates to the right so "a=b=1" is equivalent to "a=(b=1)". So 1 is assigned to b first with a result of 1, which is then assigned to a.
Assigment in JavaScript is right associative, so you are correct.
In
a = b = c;
a takes the value of b at time of assignment, so if b is later assigned to something else, a retains its value (which happens to be the same as c)
You are right technically but are confused with reference / value assignment i think. Technically a does get it's value from b but there is no reference to b therefore if your were to do b = null it would have no affect to a, which is what you're seeing in your example.
a inherits the value of b without relying on b still existing or having that same value later on when you refer back to a. The assignment happens right to left so actually reads a = ( b = 1)