This question already has answers here:
Javascript function scoping and hoisting
(18 answers)
Closed 5 years ago.
I was running following JavaScript:
var foo = function() {
var a = 3,
b = 5;
var bar = function() {
var b = 7,
c = 11;
a += b + c;
console.debug(d);
};
bar();
console.debug(c);
var d = 10;
};
foo();
Clearly, d is not known to nested function bar and c is not known to external function foo. But in developer tools, when I load my web page I get two different logs one by one:
undefined
Uncaught ReferenceError: c is not defined
Why are the errors different for the two cases? In my opinion both should have thrown simply thrown reference error if the corresponding variable is not known to them or is out of scope.
The variable c died when function foo returned; c is local to bar because a var qualifier was used.
Related
Run below code in Node environment. Running it in browser console doesn't allow to redeclare variable of var.
console.log(a);
var a = 5;
According to hoisting, the above code is going to look like this
var a = undefined;
console.log(a); // undefined
a = 5;
a variable is being hoisted to the top of the file. JS Engine allocates memory for this variable before the execution. The question is why below code consols 5 instead of undefined.
var a = 5;
console.log(a);
var a = 6;
I'm looking at this code and imagining that it's going to look like this:
var a = 5;
var a = undefined;
console.log(a); // undefined
a = 6;
I'd like to be sure of the answer instead of guessing. The JS Engine is smart enough to see that a variable is already declared and is going to ignore the next var expression and rehoisting in such case? So the output should be looking like:
var a = 5;
console.log(a); // 5
a = 6;
So it's like:
JS Engine sees for the first time declaration (in this case along with initialization) of a variable so it's allocating memory.
JS Engine sees for the second time declaration of a variable but is going to ignore the hoisting because variable of given name is already in the memory.
Am I wrong in something?
Preface: In modern JavaScript, var should never be used. Use let or const.
The JavaScript engine handles var in two steps:
Upon entering the global scope or a function scope, it processes every var in the entire scope, defining variables for the them initialized wit the value undefined. If a variable is declared more than once with var, it's exactly as though it were declared once.
Then it starts the step-by-step execution of the code. In that step-by-step execution, any initializer on a var statement (the = 5 in var a = 5) is considered an assignment. So var a = 5 is treated exactly like a = 5 at this point.
So in your example:
var a = 5;
var a = undefined;
console.log(a); // undefined
a = 6;
It's as though you had written this:
var a = 5;
a = undefined;
console.log(a); // undefined
a = 6;
or this:
a = 5;
var a = undefined;
console.log(a); // undefined
a = 6;
or this:
a = 5;
a = undefined;
console.log(a); // undefined
var a = 6;
or this:
var a;
a = 5;
a = undefined;
console.log(a); // undefined
a = 6;
or this:
a = 5;
a = undefined;
console.log(a); // undefined
a = 6;
var a;
or even this (but please don't! :-) ):
var a = 5;
var a = undefined;
console.log(a); // undefined
var a = 6;
var a;
That is, first all the variables declared with var are created (and only once), then the code runs as though any initializers on them were assignments.
This is not how let, const, and class declarations are handled (collectively: lexically-scoped declarations). First: Multiple declarations in the same scope are an error (including if one of them is with var and the other is with one of the lexically-scoped ones). Second: They're hoisted (in Step 1 above), but the hoisted binding¹ is uninitialized until the declaration is executed in the step-by-step code, at which point it's initialized (either with the value from the initializer, or with undefined if it's just e.g. let a;). The time between entry to the scope and the point the binding is initialized is called the Temporal Dead Zone. var doesn't have it because var variables are initialized when they're created (with the value undefined), but let, const, and class declarations do.
¹ The term binding is the general term for variable-like things. In the code:
function example(p) {
var v;
let l;
const c = 42;
function f() {
}
class C {}
}
the bindings created upon entering the example function's scope are p (a parameter), v (a var variable), l (a let variable), c (a const constant), f (the binding created by a function declaration), and C (the binding created by a class declaration). (Note: function and class expressions are handled slightly differently.)
This question already has answers here:
JavaScript object functions and `this` when unbound and returned in expression/parens
(2 answers)
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 4 years ago.
Here is an example where o.foo(); is 3 but (p.foo = o.foo)(); is 2?
function foo() {
console.log( this.a );
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // 2”
If I do something like this then I get 4 which is what I want. How are those 2 examples are different?
p.foo = o.foo;
p.foo(); // 4
This :
(p.foo = o.foo)();
Is pretty much the same as doing this:
d = (p.foo = o.foo);
d();
Basically what it says is that the return of an assignment is the function itself in the global context. On which a is 2.
actually your code is wrong because your snippet doesnt run, you should be doing the following: console.log( this.a );
and now, lets see how this works.
function foo() {
console.log( this.a );
}
this will call this in the scope of the caller, so lets investigate our results.
so, you are setting a=2 globally, and then in the objects o.a = 3 and p.a=4
so:
calling o.foo it will return 3 because this is pointing to o
calling p.foo it will return 4 because this is pointing to p
BUT
calling (p.foo = o.foo)(); it will return 2 because it is not pointing to any object, so it will take your scope (which is the global scope) and then it will return 2.
if you go with:
p.foo = o.foo
p.foo() //4
it will return 4 successfully because it is pointing to p.
Performing that assignment operation before the function call here:
(p.foo = o.foo)();
causes the object reference to p to be lost. If you instead wrote
p.foo = o.foo;
p.foo();
you'd get 4. As it is, you get 2 because the value of this will be window in the function.
Because that parenthesized subexpression is an assignment result, there's no object lookup directly associated with the result of the expression — the value of the assignment expression is just the function reference without a contextual object. Thus the runtime doesn't have a value to use for this when it calls the function, so this is bound by default to window (or the global object in whatever context).
This question already exists:
What is `var { comma, separated, list } = name;` in JavaScript? [duplicate]
Closed 7 years ago.
Does anyone know what this syntax means in JavaScript?
var { variable } = value;
I found it in some code examples and I've never seen this before. Is this JavaScript 6? I tried googling variable syntax and es6 but no examples came up with this syntax.
Here's the full example:
var { Tab } = require('app-dev-kit/tab');
var tab = Tab({ properties });
Weirdest part is if I drop parens from { Tab } then it doesn't work (it says Tab is not a function in that case):
var Tab = require('app-dev-kit/tab');
var tab = Tab({ properties });
This doesn't work: Error: Tab is not a function.
This is an ES6 feature known as destructuring assignment that works for arrays (array destructuring) and objects (object destructuring)
The destructuring assignment syntax is a JavaScript expression that
makes it possible to extract data from arrays or objects using a
syntax that mirrors the construction of array and object literals.
Say you have a function
function foo() {
return { bar: 1, baz: 2 };
}
And you want to assign the properties of that functions returned value to local variables. Traditionally, you would do something like
var f = foo();
var bar = f.bar;
var baz = f.baz;
console.log(bar); // 1
console.log(baz); // 2
With destructuring assignment, you can do this
var {bar, baz} = foo();
console.log(bar); // 1
console.log(baz); // 2
I modified the original script from the MDN website given below.
What is the type of var? Is the type assigned only after a value is assigned to a variable.
Does var b = 1 overwrite the previous statement var b = 10? Or just the variable b?
Is let a non-standard language feature? I read here that it is supported in ECMAScript 6.
var a = 5;
var b = 10;
if (a === 5) {
let a = 4; // The scope is inside the if-block
var b = 1; // The scope is inside the function
alert(a); // 4
alert(b); // 1
}
alert(a); // 5
alert(b); // 1
What is the type of var?
var has no type. It's a keyword used to declare variables.
Is the type assigned only after a value is assigned to a variable?
When you declare a variable but don't assign any value to it, its value will be undefined, whose type is Undefined.
Does var b = 1 overwrite the previous statement var b = 10? Or just the variable b?
Variable statements are hoisted to the top. That means that those are equivalent:
// ...
var b = 10;
if(cond) var b = 1;
var b;
// ...
b = 10;
if(cond) b = 1;
So, since b was already declared, var b = 1 will be equivalent to b = 1.
Is let a non-standard language feature? I read here that it is supported in ECMAScript 6.
let was introduced in JavaScript 1.7, and was not part of any ECMA-262 standard at the time.
Now ECMAScript 6 has standardized it (in a bit different way than JS 1.7). However, be aware that ECMAScript 6 is still a draft.
Yes, var x has no type. var x = 1 has a type of number.
var b doesn't overwrite the other statement, it just sets a new variable for the given scope. It means within that scope you get the newly assigned value for b.
let is es6. So yes and no, depending on where your code is running.
This question already has answers here:
Javascript function cannot be found
(5 answers)
Closed 8 years ago.
Recently I noticed a behavior difference between Firefox and other browsers for the following javascript code:
var condition = true;
A();
function A() {
var x=0;
for(var i=0; i<10; i++) {
if(condition) {
++x;
B();
}
function B() {
console.log("B function. x = "+x);
}
}
}
Chrome, Opera, IE output:
B function. x = 1
B function. x = 2
B function. x = 3
B function. x = 4
B function. x = 5
B function. x = 6
B function. x = 7
B function. x = 8
B function. x = 9
B function. x = 10
Firefox output:
ReferenceError: B is not defined
However, there are no complaints from Firefox and gives out the same result as other browsers, if I put the definition of function B before the call, like this:
for(var i=0; i<10; i++) {
function B() {
console.log("B function. x = "+x);
}
if(condition) {
++x;
B();
}
}
Based on this quote from Mozilla developer site:
Functions must be in scope when they are called, but the function declaration can be below the call
I understand the call, A() works. But I am not clear on why there is a difference in behavior between Firefox and others in calling B(), when the call is before definition.
While trying to narrow down the cause, I read about function hoisting here, which says Firefox doesnt do hoisting when inside an if block, but the definition was never inside the if statement in my case, so Im confused.
Firefox does not hoist function declarations outside of for blocks either. ECMA standard says it's okay. The documentation you linked to is not applicable only to if blocks, but for blocks as well.