Can anyone explain why
function x() {
console.log("Hello!");
}
var a = x;
a();
x();
produces
Hello!
Hello!
but this
var a = function x() {
console.log("Hello!");
}
a();
x();
throws an error when you try to call function x? Is the second x function not considered a hoisted function? I tried this in both nodejs and a browser.
What you have in the second example is what's called a named function expression.
Its name is not added to the containing scope, but is accessible within the scope of the function itself:
var a = function x() {
alert(x);
};
a();
This is useful in writing recursive functions or functions that otherwise reference themselves, as it ensures that the name won't get clobbered due to anything that happens outside the function's scope.
It also allows you to create self-referencing functions in places where you can't use a function declaration, such as in an object literal:
var myFavoriteFunctions = {
factorial: function f(n) {
return n === 1 ? 1 : n * f(n);
},
identity: function (v) { return v; }
};
console.log(myFavoriteFunctions.factorial(10));
Your first example is a function statement, which declares a name in its containing scope.
Your second example is a named function expression, which does not.
For more information, see here.
Related
This code new Function('fn', 'fn()') creates anonymous function which has param and (in this case the param is a function) executed.
Doing console.log(new Function('fn', 'fn()')) shows the output :
function anonymous(fn)
{
fn()
}
Now , the docs states :
Note: Functions created with the Function constructor do not create
closures to their creation contexts; they always are created in the
global scope. When running them, they will only be able to access
their own local variables and global ones, not the ones from the scope
in which the Function constructor was called. This is different from
using eval with code for a function expression.
Ok.
So why does this code yields 1 and not 44 ?
var a = 44;
function myFunc()
{
var a = 1;
function f()
{
alert(a)
}
new Function('fn', 'fn()')(f);
}
myFunc();
Why ?
What about this line above ?
they will only be able to access their own local variables and global
ones, not the ones from the scope in which the Function constructor
was called
It looks like the f is closure over the parent a , but how come ? it suppose to be run at global , and able to access local and global only !
What am I missing ?
Because you're invoking function f, which is a normal function that does create a closure.
The documentation refers to this:
var a = 44;
function myFunc()
{
var a = 1;
new Function('fn', 'alert(a)')(); //shows 44, not 1
}
myFunc();
In your example you call f function that defined inside myFunc function. Does not matter where you called it from. So you called you anonymous function that is defined in global scope and see a = 44, anonymous function called f function that is defined in myFunc scope and see a = 1.
I'm not sure what exactly you want to achieve with this code, but if you need 44 in your f you need to pass it there as an argument.
var a = 44;
function myFunc() {
var a = 1;
function f(myArgument) {
alert(myArgument)
}
new Function('fn', 'fn(a)')(f);
}
myFunc();
I'm trying to understand javascript scopes, and I want to know if in the following example:
// B can access 'context'
var a = function (context) {
b = function () {
console.log(context);
};
b();
};
a('nicccce'); // works!
// C can't access 'context'
var d = function () {
console.log(context);
};
var c = function (context) {
d();
};
c('oh oh'); // breaks
is there a way of accessing 'context' from the 'd' function?
EDIT:
I know I could pass the argument to the d function and thats obviously the sane thing to do, but I wanted to know if there was another way of doing it, maybe using this.callee as this.callee.arguments[0].
You can either
1) pass context into d as you do for c and a. or
2) put context int the lexical scope of d.
Option 2 sounds complicated, but it isn't. That is exactly what you are doing in the case of b. context is "closed-in" to the execution scope of b because the variable is available on the scope of the caller of b (because it is an argument to a).
No, that's not possible and would result in very ugly/unreadable spaghetti code.
Why can't you pass it as an argument to the function? Another (but also ugly) solution would be declaring the variable in a scope where both functions can access it (i.e. in a parent function or global)
In your example, "context" is a variable scoped to function c() and a() (two different variables in two different scopes with the same name).
Judging from how you named the variable "context", I think .call is what you are looking for?
It is worth saying that scope in javaScript is actually very simple once you get block scope out of your mind. Anything appearing between function { ... } is a scope.
In your case if you pass context as an argument in c it will not break:
// C can access 'context'
var d = function () {
console.log(arguments[0]);
};
var c = function (context) {
d(context);
};
c('oh oh'); // doesn't break
And in d you will be able to access it by using argv/args (can't remember exactly)
So something like args[0] or argv[0]
EDIT:
Changed code with arguments
Define a variable that is in the top scope:
(function(){
var global;
var d = function () {
console.log(global);
};
var a = function (local) {
global = local;
b = function () {
console.log(global);
};
b();
};
}())
So I want to call function B in function A, but function B is fully declared after function A. I know that in c++ we'd use function prototypes on B, but what about javascript?
code:
markerArray = function() {
// some code here
this.array = [];
this.clearArray = function() {
for(var i = 0; i<this.getLength(); i++)
// for loop code
}
this.getLength = function() {
return this.array.length;
}
// some code here
}
these reason why I put this.getLength below is mainly because my coding style/structure is more readable this way
Javascript doesn't care about this requirement. It will simply work as long as Function A isn't called until after the file is loaded. Function A will be defined, Function B will be defined, then Function A can be called using Function B inside of it with no problem.
Not a problem. Function declarations are hoisted to the top of the enclosing variable environment, so they do not need to be declared in order.
A();
function A() {
B();
}
function B() {
alert('B was called');
}
If you meant something else, you'll need to explain it in your question.
It depends on how you declare your functions. If you declare a function via the Function constructor or a function expression, order matters.
a(1); //this call won't work
//function expression of an anonymous function assigned to the variable multiply
var a = function(i) {
b(i);
}
// b is defined using Function constructor
var b = new Function("i","alert('B was called with ' + i)");
a(1); //this call will work
I got a piece of code for javascript which I just do not understand:
function dmy(d) {
function pad2(n) {
return (n < 10) ? '0' + n : n;
}
return pad2(d.getUTCDate()) + '/' +
pad2(d.getUTCMonth() + 1) + '/' +
d.getUTCFullYear();
}
function outerFunc(base) {
var punc = "!";
//inner function
function returnString(ext) {
return base + ext + punc;
}
return returnString;
}
How can a function be defined within another function? Can we call pad2() from outside of my() function?
Please put some light on it. Thanks
Functions are another type of variable in JavaScript (with some nuances of course). Creating a function within another function changes the scope of the function in the same way it would change the scope of a variable. This is especially important for use with closures to reduce total global namespace pollution.
The functions defined within another function won't be accessible outside the function unless they have been attached to an object that is accessible outside the function:
function foo(doBar)
{
function bar()
{
console.log( 'bar' );
}
function baz()
{
console.log( 'baz' );
}
window.baz = baz;
if ( doBar ) bar();
}
In this example, the baz function will be available for use after the foo function has been run, as it's overridden window.baz. The bar function will not be available to any context other than scopes contained within the foo function.
as a different example:
function Fizz(qux)
{
this.buzz = function(){
console.log( qux );
};
}
The Fizz function is designed as a constructor so that, when run, it assigns a buzz function to the newly created object. That is, you'd use it like this:
const obj = new Fizz();
obj.buzz();
or more concisely (if you don't need to keep the object after calling buzz):
new Fizz().buzz();
It is called closure.
Basically, the function defined within other function is accessible only within this function. But may be passed as a result and then this result may be called.
It is a very powerful feature. You can see more explanation here:
javascript_closures_for_dummies.html mirror on Archive.org
function x() {}
is equivalent (or very similar) to
var x = function() {}
unless I'm mistaken.
So there is nothing funny going on.
Function-instantiation is allowed inside and outside of functions. Inside those functions, just like variables, the nested functions are local and therefore cannot be obtained from the outside scope.
function foo() {
function bar() {
return 1;
}
return bar();
}
foo manipulates bar within itself. bar cannot be touched from the outer scope unless it is defined in the outer scope.
So this will not work:
function foo() {
function bar() {
return 1;
}
}
bar(); // throws error: bar is not defined
When you declare a function within a function, the inner functions are only available in the scope in which they are declared, or in your case, the pad2 can only be called in the dmy scope.
All the variables existing in dmy are visible in pad2, but it doesn't happen the other way around :D
It's perfectly normal in JavaScript (and many languages) to have functions inside functions.
Take the time to learn the language, don't use it on the basis that it's similar to what you already know. I'd suggest watching Douglas Crockford's series of YUI presentations on JavaScript, with special focus on Act III: Function the Ultimate (link to video download, slides, and transcript)
function foo() {
function bar() {
return 1;
}
}
bar();
Will throw an error.
Since bar is defined inside foo, bar will only be accessible inside foo.
To use bar you need to run it inside foo.
function foo() {
function bar() {
return 1;
}
bar();
}
Nested functions can be the basis for writing a modular group of related functions, kind of halfway to full object-oriented programming (static classes only).
Here is an example of such a group of functions, in this case to convert a value to a JSON string or a JSON string to a value.
Notice how the inner functions are grouped into an Object inside an outer function, and how the Object is then stored into a group name. This is the only name directly visible from outside the group. To reach any contained function from outside, you just write the group name, a period, then the function name. To reach a contained function from inside, you can use the same notation, or 'this', a period, then the function name.
//--------------------------------------------------------------------//
// Module J:
// Convert from and to JSON strings
//--------------------------------------------------------------------//
const J=NewJ();
function NewJ()
{
const mod=
{
From:(str)=>
{
return JSON.parse(str);
}, // From
To:(val)=>
{
return JSON.stringify(val,null,3);
} // To
}; // mod
return mod;
} // NewJ
//--------------------------------------------------------------------//
// End Module J
//--------------------------------------------------------------------//
Here's a test:
console.log(J.To({A:'a'}));
Console output:
{
"A": "a"
}
I have two functions, one function calling the other.
Below is a simple analogy I created of the structure of code which I have:
function test1(){
alert(a);//a is not identified here even when test1() is called under test2 which has a defined in scope
alert(b);//b is identified here
}
function test2(){
var a = 'a';//Defining a
test1();//Calling test1()
}
var b = 'b';
test2();
As per the code above, function test1() is able to identify variable b but not variable a.
My question is that why variable a is not in the scope of test1 function even when we are calling test1() inside test2() which defines variable a?
Thanks in advance.
Functions remember their scope chain at the time they're being created, not at the time they're called.
Note that b gets "hoisted", so your code actually does this:
var b; // push b on scope chain
function test1(){ // store scope chain [b]
alert(a);
alert(b);
}
function test2(){ // store scope chain [b]
var a; // push a on scope chain
a = 'a';
test1(); //Calling test1() which still has scope chain [b], not [b,a]
}
b = 'b';
test2();
your expectation is wrong about the scope of the variables,
according to your code b is a global variable to 2 functions and a is in the scope of test2 function only because it is defined withing test2,
If you want something like you expected you can define test1 function in test2 scope like this,
function test2(){
var a = 'a';
test1();
function test1(){
alert(a);
alert(b);
}
}
var b = 'b';
test2();
JavaScript has 'function scope' which means that anything defined in a function is not visible outside of the function. So variable 'a' is not visible outside of test2. However, variable 'b' is a global variable so it is visible in every scope.
Function scope also means that inner functions get access to things defined in the outer function but that doesn't come in to play here...test1 is called from within test2 but it's not an inner function of test2. To see this in action you'd need to define the body of the test1 function within test2...
function test2(){
var a = 'a';//Defining a
test1();//Calling test1()
function test1(){
alert(a);//a is identified here because of function scope
alert(b);//b is identified here because it's global
}
}
It is a good practice to call the functions with arguments. This will make your code easily readable and maintainable. Just adding arguments to the functions make the code working:
function test1(a,b){
alert(a);
alert(b);
}
function test2(b){
var a = 'a';
test1(a,b);
}
var b = 'b';
test2(b);
If you don`t want to use arguments in the function declarations, a solutions is to use the arguments object inside the code:
function test1(){
alert(arguments[0]);
alert(arguments[1]);
}
function test2(){
var a = 'a';
test1(a,arguments[0]);
}
var b = 'b';
test2(b);
If you want you can make the arguments with default values. Since in JavaScript you can`t do it in the function argument list, it is done in the body of the function:
function test1(a,b){
a = a || 'a';
b = b || 'b';
alert(a);
alert(b);
}
function test2(b){
var a = 'a';
test1(a);//here b is not passed to the function and b will get the default value
}
var b = 'some new string for b';
test2(b);
Live on jsfiddle
According to your functions you have declared and defined the variable "a" within the function "test2()" so the scope of the variable "a" is restricted within that function itself and accessing the variable will return "undefined". But it is not in the case of the variable "b" which is declared and defined globally, So it can be accessed any where in the script part.
hope this helps you.