In the code below there is callback function used with forEach loop going over returned results. Is variable 'error' inside forEach loop and 'error' in callback same variables ?
session.getAll(options, function (error, varbinds) {
varbinds.forEach(function (vb) {
if (error)
console.log('getALL Fail ');
else
console.log(vb.value);
});
});
Yes, it is the same variable.
I'm not sure how much you know. So, I'm going to explain in detail. Scoping in JavaScript is at the function level*. Think of function definitions as points on a tree. Each point on the tree is a scope. When using a variable, you can only use what is at your current scope and anything available to ancestors going up to the top (global scope). Here are a few rules & examples that may help you better understand:
*UPDATE: ES6 const and let are block-level
Inner functions have access to outer function-level variables
function a() {
var a = 4;
function b() {
alert(a); /* a = 4 */
}
}
Parameters are defined at the same scope as if they were defined one line below
function a(a) {
// variable "a" is at same scope as the example above
function b() {
alert(a);
}
}
Variables in adjacent functions are not accessible
Function a() is the parent. b() and c() are its children. Those children cannot access each other's variables.
function a() {
function b() {
var aValue = 2;
}
function c() {
alert(aValue); /* "aValue" is undefined here */
}
}
Location of function definition is what counts
This returns 5 if you run main();:
function getValue(returnFunc) {
var a = 7;
alert(returnFunc());
}
function main() {
var a = 5;
getValue(function() { return a; }); // anonymous function becomes "returnFunc"
}
Lastly, variable overriding
(function getValue() {
var a = 5;
(function () {
var a = 7;
alert(a);
})();
alert(a);
})();
I tried to avoid using self-invoking functions/IIFEs for these examples but I just couldn't help myself on this last one. It's the easiest way, I think. Run this and you'll get 7, then 5. But, if you exclude "var" on that inner "a"...
(function getValue() {
var a = 5;
(function () {
a = 7;
alert(a);
})();
alert(a);
})();
You'll get 7, 7. This is because "var" creates a new space in memory. Also, if there is a name conflict with something in a higher scope, it gets overridden as a different variable (despite having the same name).
For some more examples, please see: What is the scope of variables in JavaScript?
Yes, it's the same variable, it would change if you define another error variable inside the scope of the forEach callback by using the var keyword:
session.getAll(options, function (error, varbinds) {
varbinds.forEach(function (vb) {
if (error) //Same error as the error parameter above
console.log('getALL Fail ');
else
console.log(vb.value);
});
});
session.getAll(options, function (error, varbinds) {
varbinds.forEach(function (vb) {
var error = false; //New error for this closure.
if (error)
console.log('getALL Fail ');
else
console.log(vb.value);
});
});
Related
So here are 2 snippets of code. Each one gives a different output.
Snippet 1
var a=1;
function none () {
a = 2;
return;
}
none();
console.log(a);
console.log();
Snippet 2
var a=1;
function none () {
a = 2;
return;
function a() {}
}
none();
console.log(a);
console.log();
What makes the output differ?
This has nothing to do with var, let or const.
Function declarations create a (hoisted) variable of the same name in the current function, just like using the var keyword.
The key difference between the examples is function a() {}.
In the first code snippet, a inside the none function refers to the globally declared a variable. So when you do
a = 2;
you are assigning 2 to the global a variable.
To verify this, check the type of a inside none function before the assignment.
var a = 1;
function none() {
console.log(typeof a);
a = 2;
return;
}
none();
In the second code snippet, you have a nested function declaration a. Because of hoisting, a inside the none function refers to the function declared at the end of the function. So in the second code snippet, when you do
a = 2;
instead of referring to global a variable, a refers to the locally defined function. So, you are assigning to the local variable a instead of the global variable.
To verify this, check the type of a inside none function before the assignment.
var a = 1;
function none() {
console.log(typeof a);
a = 2;
return;
function a() {}
}
none();
function hello() {
var result = [];
var str = 'I am here';
function inner() {
var result = [];
for (var i=0;i<10;i++) {
result.push(i);
}
return result;
}
}
in the code above when I called the function hello(), the return value was an empty [], also it did not console.log the str from the inner function. However, in the below code set I have used a call back function:
function forEach(cb) {
for(var i =0;i<10;i++) {
cb(i);
}
}
function hello() {
var result = [];
var str = 'I am here';
forEach(function(num) {
console.log(str);
result.push(num);
});
return result;
}
the question is why both functions reacted, and gave a different output? Note; in both codes there was an inner function which supposed to create a new scope that can access the outer scope ? Does anyone have a good explanation for this issue ?
Thanks
In the first code block, inner is a new function that is declared inside of hello. It does not execute because you do not call it. It does create a new child scope inside of hello when it is called. But, since hello() doesn't actually return anything and doesn't call inner(), you get undefined when you call hello(). You could fix that by changing to this (you can run this snippet to see the return value):
function hello() {
var str = 'I am here';
// declare inner
function inner() {
var result = [];
for (var i = 0; i < 10; i++) {
result.push(i);
}
return result;
}
// now call inner() and return its result
return inner();
}
console.log(hello());
Functions declared inside other functions do create a new scope. Every function declaration and corresponding call in Javascript creates a new scope. If the function is inside another function, then the code inside that inner function has access to both its local scope and to the parent scope and this can nest as deep as your nested function declarations go.
the question is why both functions reacted, and gave a different
output? Note; in both codes there was an inner function which supposed
to create a new scope that can access the outer scope ? Does anyone
have a good explanation for this issue ? Thanks
In the first example, you never called the inner function so it never executed.
In the second example, you pass an inline, anonymous function reference as a function argument to your forEach() function. When that forEach() function executes, it calls your callback function with the line of code cb(i) so that's how your callback function is getting called in the second example. forEach() calls it for you.
Also, in the second example, the locally declared callback function is accessing the parent scope and modifying the result array (which is perfectly allowable). In your first code example, you are declared a new result variable in the inner function scope and then returning that. You are not accessing the parent result variable. When you declare a local variable with the same name as a variable in the parent scope, the local variable overrides the parent variable (essentially hiding the parent variable) and any references to that variable in the local scope only access the local variable.
You could have written the first code example to use a parent scoped result variable like this:
function hello() {
var result = [];
var str = 'I am here';
// declare inner
function inner() {
for (var i = 0; i < 10; i++) {
result.push(i);
}
return result;
}
// now call inner() and return result
inner();
return result;
}
console.log(hello());
You have confused function declaration and calling.
Declaring a function can be done in multiple ways:
function myNewFunction() {}
Now this function exists in the current scope, but will not execute unless called.
You can call the function like this. Now your function will get executed.
myNewFunction();
Functions and their scopes can be compared to variables. Functions defined inside another function can only be accessed from inside the parent function. Let me give you an example.
function myMegaFunction() {
console.log("in mega");
function mySmallFunction() {
console.log("in small");
}
}
myMegaFunction();
This will only print - 'in mega'. If you call mySmallFunction() inside of myMegaFunction then both lines will get printed.
Now let's take a more complex scenario like this:
function myMegaFunction() {
console.log("in mega");
var str = "car";
var result = function mySmallFunction() {
console.log("in a small", str);
}
return result;
}
var resultingFunction = myMegaFunction();
resultingFunction();
This will first print the following:
in mega
in a small car
So essentially, this is functions being passed around like variables. They can be executed later on too.
I don't understand a part of the accpeted answer of this OP:
Javascript function scoping and hoisting
Writer says:
"
Also, in this instance,
function a() {}
behaved the same as
var a = function () {};
".
What I know is that function expression is different than function declaration, at least for hoisting. Why are they similar in this case?
Why are they similar in this case?
Because var is hoisted (but not set), like a function declaration is hoisted, meaning that there is an a in the local scope before a = 10; is evaluated, so the global a never gets modified - the identifier lookup finds the local a first so sets that
Related parts of the other question
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
Why is a === 1?
That the answer was trying to say was that b is equal to
function b() {
function a() {}
a = 10;
return;
}
Similar to
function b() {
var a = function () {};
a = 10;
return;
}
i.e. there is an identifier a defined in b, so
function b() {
var a = 10;
return;
}
And now, obviously, the global a will not be modified by b
Please note that the position of the var isn't really important, just that it's there, the following will produce the same behaviour
function b() {
a = 10;
return;
var a;
}
The difference is that the first line is defined at run-time, whereas second line is defined at parse-time for a script block.
Look at the full answer on stack, here : var functionName = function() {} vs function functionName() {}
En example can be found in Twitter'a typeahead.js here:
function () {
// ...
return this.each(initialize);
function initialize() {
// ...
}
}
Questions:
What are the scopes and what function sees what?
What is the reason for using such a construct (usage scenarios and advantages)?
Javascript has function based scope, which means that every thing defined inside a function is available from the first line, since the definition is "hoisted" by the complier.
That goes for both variable and function definitions - variable values however, are not available until after assignment.
You can read all about javascript scoping and hoisting here
This means that the function initialize is available from the first line of the wrapping anonymous function.
There is no real reason, and no advantages, for doing it that way, unless you count the code structure as an advantage.
Personally I don't see any reason to do this. For me even it looks a little bit weird. Martin is right. You should be careful, because the defined variables are not accessible like functions. For example this doesn't work:
var getValue = function(func) {
return func();
}
var f = function() {
return getValue(now);
var now = function() {
return 10;
}
}
alert(f());
However, this works:
var getValue = function(func) {
return func();
}
var f = function() {
return getValue(now);
function now() {
return 10;
}
}
alert(f());
The following code
'use strict';
function blah() {
if (1 ==21) {
}
else {
var i = 10;
function inner() {
console.log(i);
}
}
}
Produces the following error:
SyntaxError: In strict mode code, functions can only be declared at
top level or immediately within another function.
How can I write my function inner such that it has access to my variable 'i'? According to strict mode I need to move the function to the top but at this point 'i' has not been declared
Since var i will be hoisted to the top of function blah's scope anyway, you could do this:
'use strict';
function blah() {
var i;
function inner() {
console.log(i);
}
if (1 ==21) {
}
else {
i = 10;
}
}
Where does inner() need to be accessible from? Will this work for your purposes?:
var inner = function () { ... };
It has been declared, since the var declares the variable for the entire function, not for the block.
The inner function must be declared as a function expression, like so:
var inner = function () {
console.log(i);
};