i'm learning about functions. i'm confused in one scenario.
suppose i have three functions
<script>
var fnRef = function() {
console.log("i'm function with no name but refered to fnRef");
};
var funRef2 = function test() {
console.log("im test reffered to funRef2");
};
function test2() {
console.log("i'm test2 named function")
};
</script>
fnRef, fnref2 and test2 will be assigned to window as a property as fnRef and fnRef2 are variable and test2 is named function that act as variable.
but why test2 is not assigned to the global object(window) when refered by funref2? and why i'm not able to execute test(); can someone tell me what is happening in detail.
The named function expression is useful so you can access the function inside it's own scope without using arguments.callee, and it also makes it easier when debugging as the name can be seen in stack traces, breakpoints etc.
This name is then local only to the function bodys scope, meaning
var test1 = function test2() {
if (something) test2(); // available in this scope only
}
test2(); // not here
You can't call the function by it's name, only by the variable it's assigned to, as the functions name is limited to the functions scope when it's a function expression.
When defining a function declaration, the name is assigned to the current scope, and hoisted, so this
var bar = test();
function test() { return 'foo'; }
is more or less turned into this
var test = function() { return 'foo'; }
var bar = test();
Related
var abc = function() {
console.log(1);
}
function abc() {
console.log(2);
}
abc();
I am expecting that it will console 2, but no it will console 1 because of
function and variable hoisting.Anybody who want to make it more clear.
In JavaScript, a name enters a scope in one of four basic ways and the order of hoisting follows following order...
Language-defined: All scopes are, by default, given the names this and arguments
Formal parameters: Functions can have named formal parameters, which are scoped to the body of that function
Function declarations: These are of the form function foo() {}
Variable declarations: These take the form var foo;
Reference: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
In your case the 1st function is type 4 and the second function is type 3. Therefore the second function is hoisted first assigning the function reference to abc. And then the first function is hoisted reassigning the reference to abc. Your code is compiled in following order,
function abc() {
console.log(2);
}
var abc;
abc = function() {
console.log(1);
}
abc();
Note that only declarations are hoisted. Assignments are not hoisted.
var bar = 'test';
var foo = function(){/*foo 1*/};
var foo;
function foo(){/*foo 2*/}
alert(foo);
will be complied in this order,
function foo(){/*foo 2*/} //function declaration
var bar; //variable declaration
var foo; //variable declaration
bar = 'test';
foo = function(){/*foo 1*/};
alert(foo);
var hoisting
the Key to understanding how scope in JavaScript works is understanding the concept of hoisting.
Because variable declarations (and declarations in general) are
processed before any code is executed, declaring a variable anywhere
in the code is equivalent to declaring it at the top. This also means
that a variable can appear to be used before it's declared. This
behavior is called "hoisting", as it appears that the variable
declaration is moved to the top of the function or global code.
console.log("function hoisting:::: ",abc()); /* log = 2 we are calling the function(hoisting)*/
var abc = function() {
console.log(1);
};
console.log("var:::: ",abc()); /* log = 1*/
function abc() {
console.log(2);
}
abc(); /* log = 1*/
console.log("function:::: ",abc()); /* log = 1*/
So in your case you are not calling the function, to call the function log it on the top.
this is how the javascript engine interprets it
function abc() {
console.log(2);
}
var abc;
abc = function() {
console.log(1);
};
abc();
REF: JavaScript Scoping and Hoisting
If you're simply asking why the function abc isn't the one being executed despite it being declared most recently, it's because, In Javascript, functions are hoisted to the top of the current scope.
That means your code is morphed into something like the following:
function abc() { console.log(2); }
var abc = function() { console.log(1); }
abc();
That means, when it comes time to call abc, the "active" one is the one that logs 1.
One of the best articles I ever found on this behaviour was the one over at adequately good.
Sorry if its being a noob question, but I still can't understand the difference of its usage so I am unable to search on google with right keywords to search for.
I am following this tutorial on Closures.
Now my query is for this code -
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
Why displayName being a function is referenced as a property in the code ? Do being a closure function it needs to be returned as a property as I tried this code -
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName();
}
var myFunc = makeFunc();
myFunc();
Output - An alert but an error TypeError: myFunc is not a function.
Let me know when to use what or what basic concept I am missing here.
"return displayName;" is returning the function displayName.
The result is then being set to myFunc.
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
It is easier to understand if you think of:
function displayName(){}
as an alternative to:
displayName = function(){}
makeFunc = function () {
var name = "Mozilla";
displayName = function () {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
In first case, you're returning a function reference which you can use later. In the second case, you are returning the result of the function which is undefined since you're not returning anything. So the error comes up as myFunc is not a reference to a function and hence cannot be called.
Other than the above, I don't know what you're meaning to say when you say "property".
return displayName()
this code returning not the function, but result of calling this function.
var myFunc = makeFunc();
myFunc();
the same.in myFunc not the function, but it's result.
try to do this:
return displayName;
...
var myFunc = makeFunc(); //makeFunc() will return displayName() function
myFunc();
Before understanding closures, which is a concept extended from the Javascript function scope.
Closures: allows certain variables to get accessed within the scope being created.The inner function can get accessed to the outer function as well as its variables.But the outer function cannot access variables within the inner function.
So in your closure example, the reason why output alerts "Mozilla" is because your inner function-displayName alerts the name variable declared in the outer function (displayName can get access to any variables in the makeFunc function). So when your makeFunc function invokes the inner function-displayName, you will get a TypeError with undefined. Same result will output when you simply call the makeFunc(), you get undefined.
Is there a way to print the value of temp (a closure variable) from a function defined outside the closure but referenced within the closure without passing temp as a variable to funcA?
var funcA, funcB;
funcA = function () {
console.log(temp);
}
funcB = function () {var temp, funcC;
temp = 1;
funcC = funcA;
funcC();
}
funcB(); // temp is undefined.
This works, but only because funcA is defined within funcB:
funcB = function () {var temp, funcA, funcC;
temp = 1;
funcA = function () {
console.log(temp);
}
funcC = funcA;
funcC();
}
funcB(); // 1
I'm trying to find a way to pull some function definitions out of outer functions to streamline code that's getting a little complex. Can I define funcA outside of funcB but still reference the temp variable without having to pass parameters?
I read that javascript does not have dynamic run time scoping, that it's only lexical scoping, but with referencing a function (funcA via funcC) within funcB, is there a way to meet the lexical scope requirement and provide access to the scoped variables for funcB?
Using Akinkunle Allen's comment, I came up with this which seems to solve my problem.
function funcB () {
var funcA, funcB, temp;
funcA = function () {
console.log(temp);
}
funcB = function () {var funcC;
temp = 1;
funcC = funcA;
funcC();
}
return funcB();
}
funcB(); // 1
Yes, and No.
The keyword var for declaring variables behaves different depending upon what the current scope is. When var is executed on the global scope it is optional. The variable becomes a property of the global object. When executing in the browser this global object is window.
So the following in global space has the same result.
var temp = 1;
window.temp = 1;
this.temp = 1;
All the above is just window.temp because of the global context.
When you use var inside a function then the variable is attached to the function. All functions in Javascript are objects so local var variables will live as long as the parent function is still being used somewhere.
Javascript will walk the hierarchy of executing scopes to find a variable identifier. So any inner functions can access their outer function variables (as in your example).
What you can do is play around with the this reference in functions.
The identifier this in Javascript is dynamic (meaning that you can change it). I can pass a variable to an unknown function that was declared outside the calling function. Since the this.temp is used to reference the variable the function funcA is able to display the value.
funcB = function(otherFunc)
{
this.temp = 1;
otherFunc();
}
funcA = function()
{
alert(this.temp);
}
funcB(funcA);
http://jsfiddle.net/thinkingmedia/dfLvj/
See the above jsfiddle example.
What you can do with this is change the meaning of this on the fly. Here is a better example.
funcB = function(otherFunc)
{
var temp = {
message: "Hello World!"
};
var foo = otherFunc.bind(temp);
foo();
}
funcA = function()
{
alert(this.message);
}
funcB(funcA);
http://jsfiddle.net/thinkingmedia/K5Pw6/
Dynamically changing this can have a lot of benefits by allowing a function to accept closure references that will be executed with a custom this reference.
An example might be a click event handler where this is the DOM element that triggered the event.
Does a Javascript self executing function work like a compiled program. I.e can you declare some function after a named anonymous function within a self executing function and have the named anonymous function locate the other function at runtime? I.e why does the following work?
I'd thought that you could not hoist named anonymous functions as they are only created during runtime so perhaps the self executing function "compiles" the code to make the named anonymous function available to the function that calls it!!
(function(){
var myFunc = function(){
var bar = "Bar";
return myFunc2() + bar;
}
function myFunc2(){
return "Foo ";
}
})()
or even
(function(){
function myFunc(){
var bar = "Bar";
return myFunc2() + bar;
}
var myFunc2 = function(){
return "Foo ";
}
window.fooBar = myFunc();
})()
console.log(fooBar);
That particular example works because myFunc2 is never called because myFunc is never called.
In general though, the normal rules for JS scope, hoisting and timing apply:
A variable must be populated before you use it, not before you define a function that will use it when called.
Lets see what actually happens in your code.
1.you have a function that performs a variable assignment:
var myFunc = ;
2.you declare a function. (But don't yet invoke it)
3.you assign myFunc to window.foobar.
4.And you invoke the function you were defining.
Now, these steps happen:
myFunc gets a function as its value.
myFunc2 gets defined.
window.foobar gets the result of calling myFunc().
so what happens is, myFunc() returns the result of invoking myFunc2() and appends its result to bar.
Thus, the value of window.foobar will be "foobar".
(no, this is not how compiled programs work)
(function(){
var myFunc = function(){
var bar = "Bar";
return myFunc2() + bar;
}
function myFunc2(){
return "Foo ";
}
})()
After some hoisting this becames:
(function(){
var myFunc;
function myFunc2(){
return myFunc2() + bar;
}
myFunc = function(){
var bar = "Bar";
return "Foo ";
}
})()
And actually this will work if you call myFunc(); and log the returned value from myFunc2 you will get Foo Bar.
When hoisting named anonymous functions(which is actually function expression), only
var myFunc (= undefined); is hoisted. Then the assignment stay at the same level.
Also you cant refer this function as self execution function(because self executed function is actually recursion). This is Immediately Invoked Function Expressions.
And #Quentin said the rest: A variable must be populated before you use it, not before you define a function that will use it when called.
Why does self-invocation function inside a function don't get the scope of the outer function in JavaScript?
var prop = "global";
var hash = {
prop: "hash prop",
foo: function(){
console.log(this.prop);
(function bar(){
console.log(this.prop);
})();
}
};
var literal = {
prop: "object"
};
hash.foo();
// hash prop
// global
hash.foo.call(literal);
// object
// global
Looks like altering the scope of the outer function has no effect on the scope of the inner self-invocation function.
PS: The question is not about how to alter the scope of the inner function. But what is the proper explanation in the "Javascript language" perspective? Does all self executing functions have 'global' scope by default? If so, why?
Your problem is the this and what it references:
foo: function(){
console.log(this.prop);
(function bar(){
console.log(this.prop); <--- this does not reference to foo here, but instead it refers to the window object
})();
}
You need to keep a reference to the outer this:
foo: function(){
console.log(this.prop);
var that = this;
(function bar(){
console.log(that.prop); <--- tada!
})();
}
Update
Some explanation. It's all about how JavaScript determines the context when invoking a function.
function Test() {
this.name = "Test";
this.bar = function() { console.log("My name is: "+ this.name);}
}
function Blub() {
this.name = "Blub";
this.foo = function() { console.log("My name is: " + this.name);}
}
var a = new Test();
var b = new Blub();
// this works as expected
a.bar(); // My name is: Test
b.foo(); // My name is: Blub
// let's do something fun
a.foo = b.foo; // make an educated guess what that does...
a.foo() // My name is: Test
Huh? Aren't we referencing the method of Blub? No we're not. We are referencing the unbound function of Blub.
JavaScript binds on . (dots) and based on that it decides waht the value of this should be.
Since you're not calling your anonymous function on an object (therefore no .) it will make this reference to the global object, which is - in case of the browser - the window object.
Another example (one might think this would work):
var str = "Hello World";
var ord = str.charCodeAt; // let's make a little shortcut here.... bad idea
ord(0) // no dot...
Instead of the char codes that are in str we get the ones that are in the global object, of course that's not a string so charCodeAt calls toString on which results in "[object DOMWindow]"
You are not applying any object as the this context when you call the inner function, so it gets this set to window by default. If you wanted to call the closure with the same this as the outer function, you would have to do:
(function bar(){
console.log(this.prop);
}).call(this);
Or:
var that = this;
(function bar(){
console.log(that.prop);
})();