I read about JavaScript closures and I thought that I understood it, but apparently I didn't.
The success function is called when request is succeeded. This means that when the closure (function () {
return obj;
})(); is executed the scope, inside success function, is NOT function (evt) {...} anymore, so how it can still access obj?
How the closure work in this example
EDITED(there is var before obj)
function (evt) {
var obj = evt.data.obj,
$.ajax({
type: "POST",
url: url,
data: data,
success: function () {
var o = (function () {
return obj;
})();
}
});
}
In JS, scope is limited by function.
Everything inside a function to which a variable is scoped can access that variable — including other functions — unless there is another variable of the same name in a narrower scope.
That said, in this example there is no var keyword to localise the scope of the obj anyway, so it is a global. Removed after edit of question
One way to look at it is that closures have access to all scopes above themselves.
Another way would be to say that obj actually is accessible in scope of function function(evt), which is parent to the scope of function(), and therefore, obj is also accessible from function().
Either way, this is how JavaScript works: closure has access to everything that is accessible at the closure's point of definition.
A closure has access to all higher scopes, not only the "parent scope".
Since an obj variable isn't defined in the current scope, JavaScript goes up all the scopes the function has access to until it finds it.
It's like someone looking up a very weird ladder; one which can split to sub-ladders, but when you climb down these sub-ladders, you are still in the bigger ladder.
A closure has by design access to surrounding scope upon creation as it is created within the scope.
Any variables you access in the outer scope is accessed through a reference that will keep the variable alive after the scope within which it was created is destroyed.
That way when the closure executes, the variables it was referencing will still exist and only after the closure is disposed will the variables be released.
Each Function object has an Activation object that represents it's execution context.
Within a group of nested functions, A scope chain is formed starting from the inner most Activation object and ending with the Global object (Global Scope).
So unless there's a name clash between variables ,Each function has access to all of it's parent functions' local variables and parameters in addition to global variables.
Here's a lengthy but very useful explanation.
Related
I have no idea how to describe my question .
(function(fn){
var able=123;
function tmp(){
fn()
};
tmp();
})(function(){alert(able)});
This snippet throws a Reference Error :able is not defined' .
Would you please explain how javascript get variables to me ?
The scope of the "fn" function is not the same as the "parent" function, you should pass the "able" argument when you call the fn function, and then istantiate it in the fn function itself, like this:
(function(fn){
var able=123;
function tmp(){
fn(able)
};
tmp();
})(function(able){alert(able)});
Functions create lexical closures at the time of their creation. This means that when your alert function is created, the able variable does not exist. Wrapping the execution of fn in a lexical closure that does know about able at a later moment does not affect the already created lexical closure of fn.
If you come up with a question that better explains what you are trying to do, we can propose how to properly use closures to express that idea.
java script support in function local and global scoping.
in this case the "able" is local function scope you can't access outside the function.
If you use var the variable will be declared in the local scope. If u just declare the variable without a var, it will be declared in the global scope
Your code could be rewritten like this using named functions:
var func1 = function(fn) {
var able=123;
function tmp(){
fn()
};
tmp();
}
var func2 = function() {
alert(able)
}
func1(func2);
I believe this way it is clear that the variable 'able' is defined inside 'func1' (more precisely in its local scope) and you are trying to access it inside 'func2' which is outside the scope of 'func1' so it can not "see" into this scope.
More information about scoping in JavaScript can be found here: What is the scope of variables in JavaScript?
function f1 () {
console.log('f1')
}
var s = 'f1'
runLocalFunctionByName(s)
Is this possible at all to write runLocalFunctionByName() or just call f1 without typing f1 in the source code, but using a variable holding its name? I mean without modifying f1 into a method, that answer is obvious: just make myobj.f1 = function or declare it globally like f1= function(). I am talking about normal local functions declared with function keyword only, not as vars, global vars or some other object property.
Not without the use of eval, which is evil (when used for this purpose for sure!).
Global functions could be called as attributes of the window object, but if they are in a local/closure scope that's not possible.
If you need to call functions by name, the only proper solution is storing them as attributes on an object, and then using obj[s]() for calling them.
One way of doing this is by using the instantiating a Function object.
var runLocalFunctionByName = function(fName) {
return (new Function('','return '+fName+'();'))();
};
Calling runLocalFunctionByName with a name of a function will now return the output of the named function.
EDIT
In case of local functions, the scope has to be mentioned, so we can modify the code, such that:
var runLocalFunctionByName = function(fName, scope) {
return (new Function('','return '+(scope?scope:'this')+'.'+fName+'();'))();
};
You can't access a local function outside its scope until unless you assign it to a variable having an accessible scope. MDN: A function defined by a function expression inherits the current scope. That is, the function forms a closure. On the other hand, a function defined by a Function constructor does not inherit any scope other than the global scope (which all functions inherit)
When using Javascript Closures, is there some difference in using Object literal Vs Constructor based objects ?
Are there just syntax difference OR is there some other difference as well for Closures?
Any example explaining the 2 differences would be really helpful.
Closures are a feature of functional programming. They have nothing to do with objects or object literals.
Read the following answer - it explains closures really well: https://stackoverflow.com/a/12931785/783743
In general a closure is a function which closes over the variables in a nested function which moves out of the scope of the closure. For example:
function getCounter() {
var count = 0;
return function counter() {
return ++count;
};
}
var counter = getCounter();
counter(); // 1
counter(); // 2
counter(); // 3
Here the function getCounter becomes a closure because it closes over the variable count used in the nested function counter when the nested function is returned (moves out of the scope of getCounter).
The variable which is closed over (in this case count) is called an upvalue. Closures are important because they allow values which would otherwise go out of scope (be garbage collected) to remain alive. This is not possible in languages like C/C++ and Java.
Closure is more about the function scope of the variable. So the important thing to know is that the scope of a variable is the function it was defined in. Any function that run inside this scope will have access to its parent function per se. Parent function won't have access to a child function variable, because it's outside of that child's scope.
Therefore a variable in an object literal, would be scoped to the function that it is contained it. (If it's not in a function, then it's in the global scope). A constructor is a function so any variables that it defines, is scoped in itself and inaccessible outside. Any inner methods that are in the constructor has access to those defined variables.
Closures are created when a function has access to a variable that is outside its own scope and that variable may be changed or altered by something else...even well after the function has finished execution.
I hope that helped some what.
var foo = 'bar';
console.log(window.foo); // bar
Seems like variables get assigned as properties to this, but inside anonymous functions, this refers to the parent scope, but doesn't assign variables to the parent scope.
function() {
var foo = 'bar';
}();
window.foo; // undefined
What object do variables get assigned to in non-global scopes?
To cite http://perfectionkills.com/understanding-delete/#execution_context:
Every execution context has a so-called Variable Object associated
with it. Similarly to execution context, Variable object is an
abstract entity, a mechanism to describe variable instantiation. Now,
the interesing part is that variables and functions declared in a
source text are actually added as properties of this Variable object.
When control enters execution context for Global code, a Global object
is used as a Variable object. This is precisely why variables or
functions declared globally become properties of a Global object
Yet, these Variable Objects are not accessible. The only non-internal one is the global object, window or this (in global context).
The relevant section in the specification is #10: Executable Code and Execution Contexts.
In JavaScript, all variables are assigned to some scope object. However, only the scope object of global variables is accessible in JavaScript in the browser through the window object. Variables in a function scope are assigned to some scope object used internally by the JavaScript runtime, but this cannot be accessed by the user.
In another environment, global variables may be accessible as properties of another object (such as GLOBAL in node.js) or may be inaccessible (such as application scripts running inside the Windows Script Host).
They're available only in the function they're declared in.
Function scope is the only other scope in JavaScript, btw, unlike block-scoping in other {} languages.)
Re: your edit Don't be fooled--JS's this semantics are a bit irksome IMO--this may not be what you expect under a variety of circumstances.
Inside self-invoking anonymous function eg:
function() {
....
}()
All variables remain inside it and do not attach themselves to global object or window. Using that technique, there are patterns created such as module/singleton pattern.
Notice that in JS, variables have function-level scope.
Javascript functions are objects and they have scope chain associated with them.
If some closure exists with a function that has a different scope chain than the one that was in effect when they were defined.As an example invoking function is a returned function object from some other (parent) function that had a scope chain with a large number of private variables,
so invoking function will use the already existing inherited scope chain of parent function as well as bounded old variables.
Is there any way to check the variables associated with the scope chain without looking into the parent function?
Ideally one has to keep track of defined variables in the parent function, my question is without lookup of the parent function, can we see the variables associated with scope chain?
If yes (any method?) can we check the current value of variables associated with scope chain?
Also can someone give the structure of scope chain( at least i know its not like CPU stack like strucuture but something else?).
Scoped variables are available to the functions created in the same context (JavaScript is functionally scoped).
You have access to them but you can't run a method to report them. If this is a common requirement, I suggest keeping internal variables handy in a "config" variable:
var obj = (function (config) {
return {
getTest: function () {
return config.test;
}
};
}({test: 1}));
Nick Zackas has done a good presentation about the scope chain (I think it's here: http://googlecode.blogspot.com/2009/06/nicholas-c-zakas-speed-up-your.html)
Otherwise, use a browser with developer tools like Chrome (Firebug often forgets what the scoped variables are).