I know the what the postfix/prefix increment/decrement operators do. And in javascript, this seems to be no different.
While I can guess the outcome of this line easily:
var foo = 10; console.log(foo, ++foo, foo, foo++, foo);
// output: 10 11 11 11 12
as ++ operators appear within separate expressions.
It gets a bit complicated as these operators appears within the same expression:
var foo = 10; console.log(foo, ++foo + foo++, foo);
// output[1]: 10 22 12
// Nothing unexpected assuming LTR evaluation
var foo = 10; console.log(foo, foo++ + ++foo, foo);
// output[2]: 10 22 12
// What? Ordering is now different but we have the same output.
// Maybe value of foo is evaluated lazily...
var foo = 10; console.log(foo, foo + ++foo, foo);
// output[3]: 10 21 11
// What?! So first 'foo' is evaluated before the increment?
and my question is, how does Javascript (V8 in this case, as I tested these in Chrome) end up evaluating the addition expression in 2nd and 3rd example differently?
Why does foo end up evaluating differently than foo++. Isn't postfix ++ supposed to increment after the expression and just evaluate to foo within expression?
Just look at:
foo++ + ++foo
Mentally rewrite it to:
foo++ →
addition_lhs = foo // addition_lhs == 10
foo += 1 // foo == 11
++foo →
foo += 1 // foo == 12
addition_rhs = foo // addition_rhs == 12
addition_lhs + addition_rhs == 10 + 12 == 22
And foo + ++foo:
foo →
addition_lhs = foo // addition_lhs == 10
++foo →
foo += 1 // foo == 11
addition_rhs = foo // addition_rhs == 11
addition_lhs + addition_rhs == 10 + 11 == 21
So everything is evaluated left to right, including the incrementation.
The crucial rule to understand is that in JavaScript the whole left hand side (LHS) is executed, and the value memorized, before any operation gets done on the right hand side (RHS).
You can either confirm the evaluation order by reading the standard or just place a runtime error in your expression and look what happens:
alert(1) + alert(2) + (function () { throw Error(); })() + alert(3)
Understand that when you use foo++ you're telling to the "compiler": after you push it to the stack, increment it. When you use ++foo you're telling the other way: increment it then push it to the stack.
The ++ operator have preference over the +, since the "compiler" read the expression this way (foo++)+(++foo)
var foo = 10; console.log(foo, ++foo + foo++, foo);
++foo + foo++
11 + 11
The pre increment sets foo to 11 then adds it to foo again which is still 11, evaluating to 22 before foo is again incremented.
var foo = 10; console.log(foo, foo++ + ++foo, foo);
foo++ + ++foo
10 + 12
By the time we reach ++foo, the value has already incriminated from foo++
var foo = 10; console.log(foo, foo + ++foo, foo);
foo + ++foo
10 + 11
foo is incremented before we add it to foo, thus giving us 10 + 11
SUMMARY
Basically it all depends on what the current value of foo is when you add them together.
Related
When I do something like this:
var x = 5;
console.log( x + (x += 10) ); //(B) LOGS 10, X == 20
console.log( (x += 10) + x ); //(A) LOGS 0, X == 30
The difference in the returned value between (A) and (B) is explained by the value of x at the time it becomes evaluated. I figure that backstage something like this should happen:
TIME ---->
(A) (x = 5) + (x += 10 = 15) = 20
(B) (x += 10 == 15) + (x == 15) = 30
But this only holds true if and only if x is evaluated in the same left-to-right order that it was written.
So, I have a few questions about this,
Is this guaranteed to be true for all Javascript implementations?
Is it defined to be this way by the standard?
Or, is this some kind of undefined behavior in Javascript world?
Finally, the same idea could be applied to function calls,
var x = 5;
console.log(x += 5, x += 5, x += 5, x += 5); // LOGS 10, 15, 20, 25
They also appear to be evaluated in order, but is there a stronger guarantee that this should always happen?
Is this guaranteed to be true for all Javascript implementations?
Yes.
Is it defined to be this way by the standard?
Yes, you can read it yourself here.
Specifically, the runtime semantics: evaluation of the addition operator (+) specify that the left expression is evaluated before the right expression.
It's the same for the evaluation of argument lists.
Or, is this some kind of undefined behavior in Javascript world?
Yes, there is undefined behaviour in JavaScript, but not here.
I've been studying for a job interview, and started digging into JavaScript. Came up with this.
So:
"use strict";
var x = 0;
var y = 0;
eval("x=3;y=11;"); //direct call to eval in global scope
console.log("x: " + x); // outputs 3
console.log("y: " + y); // outputs 11
But:
"use strict";
var x = 0;
(0, eval)("x=3;y=11;"); //indirect call to eval in global scope
console.log("x: " + x); // outputs 0 because the strict mode won't allow the reassignment?
console.log("y: " + y); // outputs 11
I don't know/understand what happens with the x when the eval is executed. I know with strict mode off the assignment goes through no problem. Would anyone be willing to explain this to me? Thanks!
It appears to be how Node.js handles variables (they do not default to global). The indirect call to eval is assigning to the global object.
"use strict";
var x = 0;
(0,eval)("x=3;y=11;");
x++;
console.log("x: " + x); // outputs 1
console.log("global x: " + global.x); // outputs 3
console.log("y: " + y); // outputs 11
When I do something like this:
var x = 5;
console.log( x + (x += 10) ); //(B) LOGS 10, X == 20
console.log( (x += 10) + x ); //(A) LOGS 0, X == 30
The difference in the returned value between (A) and (B) is explained by the value of x at the time it becomes evaluated. I figure that backstage something like this should happen:
TIME ---->
(A) (x = 5) + (x += 10 = 15) = 20
(B) (x += 10 == 15) + (x == 15) = 30
But this only holds true if and only if x is evaluated in the same left-to-right order that it was written.
So, I have a few questions about this,
Is this guaranteed to be true for all Javascript implementations?
Is it defined to be this way by the standard?
Or, is this some kind of undefined behavior in Javascript world?
Finally, the same idea could be applied to function calls,
var x = 5;
console.log(x += 5, x += 5, x += 5, x += 5); // LOGS 10, 15, 20, 25
They also appear to be evaluated in order, but is there a stronger guarantee that this should always happen?
Is this guaranteed to be true for all Javascript implementations?
Yes.
Is it defined to be this way by the standard?
Yes, you can read it yourself here.
Specifically, the runtime semantics: evaluation of the addition operator (+) specify that the left expression is evaluated before the right expression.
It's the same for the evaluation of argument lists.
Or, is this some kind of undefined behavior in Javascript world?
Yes, there is undefined behaviour in JavaScript, but not here.
This question already has answers here:
How do JavaScript closures work?
(86 answers)
Closed 9 years ago.
In the following example, how is y given the value of 1? I added some logging to see values and don't understand how/where y is assigned...
(function() {
function foo(x) {
var callNum = 0;
var baz = 3;
return function (y) {
callNum++;
console.log("callNum: " + callNum);
console.log("y: " + y);
console.log("baz: " + baz);
console.log("x: " + x);
console.log(x + y + (++baz));
}
}
var moo = foo(2); // moo is now a closure.
moo(1);
moo(1);
})();
Here's the fiddle output log:
callNum: 1
y: 1
baz: 3
x: 2
7
callNum: 2
y: 1
baz: 4
x: 2
8
foo() returns a function. This returned function accepts a single argument, the y you are concerned with.
So when you do this:
// returns a function that accepts `y` with `x` shared via closure
var moo = foo(2);
// execute the inner function, passing in a value for `y`.
moo(1);
foo(2) returns a function. x is now 2. moo is now a function that accepts a value for y, and you pass in 1. So y is now 1.
To think of it another way, you can invoke your inner function by doing:
foo(x)(y);
Or with the values you are using:
foo(2)(1);
So, in answer to your question, y gets set to 1 when you do:
moo(1);
In your code:
(function() {
function foo(x) {
var callNum = 0;
var baz = 3;
These are the parameters that matter (x, callNum and baz). They form closures involving the following function:
return function (y) {
This function has a closure to each of the outer local variables (including moo and foo).
callNum++;
console.log("callNum: " + callNum);
console.log("y: " + y);
console.log("baz: " + baz);
console.log("x: " + x);
console.log(x + y + (++baz));
}
}
There are also closures involving moo and both the above functions, however it's not used so is irrelevant to the outcome.
var moo = foo(2); // moo is now a closure.
The rest is answered by Alex.
newbie in javascript closure
i follow a example from internet, and try to change some of it
i think it should give me 16,17,18,19
but the result was unexpect
here is my code.
i do not know why i first call bar2(10),it alert 17, does it should give me 18?
function foo(x) {
var tmp = 3;
return function (y) {
alert(x + y + (++tmp));
}
}
var bar = foo(2);
bar(10);//alert16
bar(10);//alert17
var bar2 = foo(3);
bar2(10);//alert17
bar2(10);//alert18
Because tmp is a variable local to the function you return from foo -- that means when you call foo for the second time, it gets reset to 3. 3 + (3+1) + 10 = 17.
The result 17 is correct.
Each call to foo produces a new function with a new closed-over variable tmp.
Perhaps you thought the second call to foo uses the same tmp as in the first call? It doesn't. That is why you get 17: 3 + 10 + 4.
bar(y) = n = x + y + tmp
bar(10) = 16 = 2 + 10 + 4
bar(10) = 17 = 2 + 10 + 5
bar2(10) = 17 = 3 + 10 + 4
bar2(10) = 18 = 3 + 10 + 5