Let's say I'm declaring a list of variables in the following manner:
var a = "value_1"
, b = "value_2"
, c = b;
What is the expected value of c? In other words, is the scope of a variable immediately available after the comma, or not until the semicolon?
This is as opposed to the following code snippet, where it is very clear that the value of c will be "value_2":
var a = "value_1";
var b = "value_2";
var c = b;
I thought I'd ask rather than test in a browser and just assume that the behavior will be consistent.
See the comma operator:
The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand
So b = "value_2" is evaluated before c = b
It's not really an answer to the question, but when faced with such a choice between two expressions of the same thing, always choose the one which is the less ambiguous.
In your second code snippet, it's clear to everybody what the final state is. With the first one, well, you had to ask a question here to know :) If you come back to the code in a month from now, or if somebody else does, then you'll have to go through the same process of finding out the actual meaning. I don't think it's worth the 6 characters you're saving.
Related
I want to two values in typescript code say
let a:number = b + c;
And b and c come at runtime but are supposed to be number.
But if one of b or c comes as string, it will cause a to be string and that can cause bug down the line, we have no way to detect that at runtime
What can I do in typescript ( if any ) to avoid this situation to happen ?
PS: I know typescript goes out of picture during runtime but just wanted to know if someone has to say something about this sort of problem.
Well, first you should think why b or c don't have types.
The Typescript way to "fix" this is to force b and c to have number type. If you try to call sum with non-number arguments, it will complain AT COMPILE/LINTING TIME (not at runtime).
function sum(b:number, c:number) {
let a = b + c;
}
This way you force both variables to be numbers, so the result a will also be a number.
If b and c come from another location (user input?) where you don't have control of its type, you cannot do anything with Typescript. Typescript is a type checking language that will check everything before compilation. After that, it will compile to plain Javascript.
The way to go here is to sanitize inputs (TIP: That's a good practice! :-) by, for example, checking the types at runtime, like so:
if (typeof b !== "number") {
b = Number(b) || 0;
}
use let c = parseInt(b)+parseInt(c)
You can use the parseInt or parseFloat functions, or simply use the unary + operator:
let b = "3";
let c = 2;
let a = ((+b)+(+c)); // a: number
console.log(a)
I am interested in the Wasabi tool.
Please have a look on this piece of code.
I don't understand this instruction:
var W = window.Wasabi = window.Wasabi || {};
My final purpose is to adjust a CSS property, dynamically loaded by the JavaScript...
Thanks for the help.
Two things going on here.
Logical OR operator:
a||b will return a if a is truthy or b otherwise.
so window.Wasabi||{} mean return window.Wasabi if it is defined or otherwise return a new empty object.
Double assignment:
c=d=1 set d equal to 1 and c equal to d. i.e. set c and d to 1.
Putting these two things together:
if window.Wasabi is set already then just get a reference to it and store that in W. Otherwise create a new object, store a reference in window.Wasabi (to use next time) and call it W for use now.
If window.Wasabi doesn't exist, then window.Wasabi will be equal to {}. If it already exist, then don't change it. Finally, assign W to window.Wasabi. So, it would be like this code:
var W;
if (!window.Wasabi) {
window.Wasabi = {};
}
W = window.Wasabi;
There are 2 not-so-obvious things in this statement. There's the 2 consecutive equals, and the || at the end. They are not related so Ill tackle them one by one.
var W=window.Wasabi=window.Wasabi;
//Shorthand for
var window.Wasabi=window.Wasabi;
var W=window.Wasabi;
In english, that'd be: W equals window.Wasabi which equals window.Wasabi.
Now, the || is an OR in an operation, it states to take the left most value, if it's a truthy value, OR the one on the right.
var window.Wasabi=window.Wasabi||{};
//equates to
var window.Wasabi;
if(window.Wasabi){
window.Wasabi=window.Wasabi;
}else{
window.Wasabi={};
}
This pattern is very useful to give a default value to a variable. This will answer that Wasabi is at least an object...
There are two main javascript concepts to understand in this statement.
The first one is :
var x = y || {}
This is equivalent to :
if (y)
x = y
else {
x = {}
If y is truethy, then its value will be assigned to x. Else, x will be equal to {} (an empty object)
The second one is :
a = b = "something"
b will be assigned the value "something" and a will be assigned the value of b (which was just set to "something")
Both a and b will be assigned the value "something".
Application to your example :
var W=window.Wasabi=window.Wasabi||{};
If window.Wasabi is not defined (or is falsy), then it will be assigned to {}.
Then the W variable will be assigned the value of window.Wasabi.
Is window.Wasabi is defined, then it will be assigned to the value of itself (nothing will happen), and W will be assigned the value of window.Wasabi.
It's a pretty dirty way to set the initial value of an object if it doesn't exist, but... it works.
var a=1;
b=++a*a;
console.log(b);
console.log(a);
the result is 4,2.how the program get this result?
in my mind,the result will be 2,2
can anybody tell me how the javascript compiler compile this piece of code and get the result 4,2.
Then the deep question is why these two pieces of code result are the same.
var a=2;
var b=3;
c=(a++)*a;
console.log(c);
var a=2;
var b=3;
c=(a++)*b;
console.log(c);
can anyone explain this one step by step?
++ has a higher precedence than *. Thus b = ++ a * a is evaluated as b = (++a) * a.
++a makes a equal to 2 and then a gets muliplied by itself.
On a sidenote, every time you get confused by something like this, find JavaScript's operator precedence table and try to break the equation down by yourself.
++a increases the value to 2 before the multiplication. After this, variable "a" will point to value 2 and it will make the multiplication: 2*2.
a++*a wil give you the desired result (2,2)
I was reading David Flanagan's JavaScript: The Definitive Guide, probably the fattest book for JavaScript in the world. When briefly describing array initializers, Flanagan said "The element expressions in an array initializer are evaluated each time the array initializer
is evaluated". What does this means. My practice results made me more confused:
var a = 50;
var b = 70;
var array = [a+b, 50];
console.log (array [0]); //120
a = 60;
console.log (array [0]); //120
var other = array;
console.log (other [0]); //120
I thought the result would be 130 after I change a's value to 60, because the expression is going to be re-evaluated. But it's not that. I know I am completely getting it wrong. Can someone explain what Flanagan is trying to explain in that sentence?
He means that when the array literal expression is ("re"-)evaluated, so will be its contents.
function makeArray() {
return [a];
}
var a = 0;
console.log(makeArray()); // [0]
a = 1;
console.log(makeArray()); // [1]
So, nothing special actually, just default expression behaviour.
You've misquoted the author; what he actually said is
The element expressions in an array initializer are evaluated each time the array initializer is evaluated.
Rather than the term "array initializer", it would be clearer, and more in line with common usage, if he said "array literal". If we adopt the common-sense interpretation of "array initializers" as meaning "initializers for an array-valued variable", then such initializers could be array literals, but could also be any array expression. (Having said that, it does appear that the spec uses the term "array initializer" for "array literal" in Section 12.2.5, so the author's usage is not wrong in that technical sense.) Array literals (basically, anything of the form [...]) can, on the other hand, be used as initializers, but can also be used elsewhere.
What he appears to be trying to say is that an array literal such as
[a]
re-evaluates a each time it itself is re-evaluated, such as when a function is re-executed. If you think about it, that's pretty obvious. It's hard to see how it could work any other way. So the function
function foo(x) { return [x]; }
will return the array [1] when called as foo(1), and the array [2] when called as foo(2), because the array literal [x] is re-evaluated each time the function is called.
This is an entirely different issue from the one that is tripping you up, which is that
var a = 22;
var b = [a];
a = 42;
console.log(b);
does not change b to have the value [42]. This behavior has nothing to do with how array initializers are (re-)evaluated or their component elements are (re-)evaluated. Is has to do with how JavaScript variables and references work. The above would change the value of b if b were storing a dynamic reference to a as its element, but JavaScript has no such notion of dynamically-updatable references. To put it a different way, the console.log(b) line is indeed evaluating b, but that just returns whatever b already is. It does not (re-)evaluate the expression [a] originally used to set b. The fact that b happens to have taken on he value resulting from evaluating [a] is lost immediately after the statement setting the value of b, at which point b now has the value [22].
Consider also the following example, which is completely analogous:
var a = 1, b = 2, c = a + b;
a = 42;
console.log(c);
Here, no-one would expect the expression given as the initial value for c to change when the value of a changes later. c is 3, and it will always be until explicitly re-assigned. In the console(c) line, yes, we are "evaluating" c, but that is merely a matter of retrieving the value of c, not of re-evaluating some expression which happens to have used to assign a value to c in the past. There are some other declarative-style language paradigms where things might behave in that way, but not JavaScript.
Here you assigning the array to array variable and it will store that value until that variable(unless you modify that variable) goes out of scope. In the second statement you're reusing the the same array pointed to by "array" variable. Third statement is just assigning the reference to "array" variable to another variable and access the same element.
Only the first time a+b statement is evaluated and that resulting array is saved as value reference. Last statement is an example of pass by value(Javascript is always pass by value) where copy of "array" variable is created as "other", and "other" also points to same memory reference pointed by "array" variable.
At wtfjs, I found that the following is legal javascript.
",,," == Array((null,'cool',false,NaN,4)); // true
The argument (null,'cool',false,NaN,4) looks like a tuple to me, but javascript does not have tuples!
Some quick tests in my javascript console yields the following.
var t = (null,'cool',false,NaN,4); // t = 4
(null,'cool',false,NaN,4) === 4; // true
(alert('hello'), 42); // shows the alert and returns 42
It appears to behave exactly like a semicolon ; separated list of statements, simply returning the value of the last statement.
Is there a reference somewhere that describes this syntax and its semantics? Why does it exist, i.e. when should it be used?
You are seeing the effect of the comma operator.
The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.
The resultant value when a,b,c,...,n is evaluated will always be the value of the rightmost expression, however all expressions in the chain are still evaluated (from left to right).
As already explained this behaviour is caused by , operator. Due to this the expression (null,'cool',false,NaN,4) will always evaluate to 4. So we have
",,," == Array(4)
Array(4) - creates new array with allocated 4 elements. At the time of comparison with the string this array is converted to string like it would be with Array(4).toString(). For arrays toString acts like join(',') method called on this array. So for the empty array of 4 elements join will produce the string ",,,".
Try this alert((null,'cool',false,NaN,4)) and then you can see.
demo
The reason is because the comma operator evaluates all the statements and return the last one.
Think of this line: a = 1, b = 2, c = 3; it will run each expression so in essence it will set the variables to what you want and return the last value (in this case 3)