I'm learning Javascript, and had this question. Here's some sample code:
var xq = false;
var fooyy = function ttt() {
var xq = false;
baryy = function() {
var xq = true;
console.log(xq);
console.log(ttt);
console.log(fooyy);
console.log(ttt.xq);
console.log(fooyy.xq);
console.log(window.xq);
}();
};
fooyy();
console.log(xq);
console.log(fooyy.xq);
Looking at the output, my question is, so does it mean that from an inner nested function, properties and variables of outer functions can't be accessed (both in the cases of having the same name and otherwise)? Or if they can, could you explain how and why? (I see that the local and global variables are accessible) Thanks!
does it mean that from an inner nested function, properties and variables of outer functions can't be accessed?
No. Those are not properties, they are variables. You tried to access them as properties of the functions, which don't exist.
I see that the local and global variables are accessible. What about variables of outer functions (both in the cases of having the same name and otherwise)?
They can be accessed as long as they have different names. This is known as lexical scope, and works even after the outer function has returned - the inner one will form a closure. You can access them simply by their name, they are local variables.
If you do however have a variable of the same name in your local scope, like in your example the variable xq, that local variable will shadow the variable from the outer scope and make it inaccessible. If you want to access it, you need to rename either variable.
What you have there is a closure, nicely explained in this SO question.
Also, please have a look at this SO question, where people invested lots of effort to explain what a closure is.
In short, baryy function has access to outer variables.
Related
I want to access the variable with the "apfala"
var frucht="apfala";
function getFrucht(frucht){
console.log(frucht);
console.log(this.frucht) // I want here the apfala one, I thought .this would work
}
getFrucht("apfel");
Or do I have to rename them differently?
http://eslint.org/docs/rules/no-shadow
Shadowing is the process by which a local variable shares the same
name as a variable in its containing scope. For example:
var a = 3;
function b() {
var a = 10;
}
In this case, the variable a inside of b() is shadowing the variable a
in the global scope. This can cause confusion while reading the code
and it’s impossible to access the global variable.
Your code suggests that you need to rethink whatever it is you are trying to do. As it is unclear as to the true nature of what you are trying to do, it is hard to suggest an alternative solution to your problem (other than do not shadow or use globals), if you have one rather than just curiosity?
Please don't do this, but this should work in all environments.
'use strict';
var getGlobal = Function('return this');
getGlobal().frucht = 'apfala';
function getFrucht(frucht) {
console.log(frucht);
console.log(getGlobal().frucht); // I want here the apfala one, I thought .this would work
}
getFrucht('apfe');
Also see: https://www.npmjs.com/package/system.global
In case your javascript runs in a browser, you can use the window global variable in order to access the variable frucht that defined in the global scope:
var frucht="apfala";
function getFrucht(frucht){
console.log(frucht);
console.log(window.frucht) // I want here the apfala one, I thought .this would work
}
getFrucht("apfel");
If it is a global and you are running in a browser:
You can use window.frucht as global variables are properties of the window object.
Not reusing the same variable name would be a much better idea though. It avoids the dependency on globals and the confusing of reusing names.
Generally speaking, in JavaScript, if you want to pass a parent scope to a child one, you need to assign this in the parent to a variable and access that variable inside the child:
var frucht="apfala";
var parent = this;
function getFrucht(frucht){
console.log(frucht);
console.log(parent.frucht);
}
getFrucht("apfel");
Also, as stated in other answers, if you are working in a browser, just use the window object to attach and access global variables (window.frucht="apfala", then use window.frucht to access that variable)
Hope that helps.
I am going through the book JavaScript: The Complete Reference, Third Edition By: Thomas Powell; Fritz Schneider to have a detailed understanding of the concepts.
Scoping Rules
Outside of a function or object, variables are within the global space whether explicitly defined with var or not. Within a function or object, if the var statement is used, the defined variable will be local to the construct; without the statement, it will be global.
Commonly, JavaScript developers make assumptions about scoping rules with var that aren’t quite true. For example, a var statement found within a for loop does not scope that value to the loop. In this case, it is scoped to either the function it is within or to the global space if it is outside a function or an object.
Just to see what happens consequently, I coded like this,
When I press Ctrl+Space in Eclipse IDE for it to show JavaScript proposals, why am I able to access the variable jLocal outside the function?
As per the author description:
For example, a var statement found within a for loop does not scope that value to the loop. In this case, it is scoped to either the function it is within or to the global space if it is outside a function or an object.
Because at the bottom of your code you have:
...
jLocal = jLocal + j; // defined not in any functions
...
Making it global, but not necessary defined.
It isn't the case of a local function. myFunc is global, just as the variable jLocal is (albeit the name). Because of hoisting, jLocal is assumed to be declared on top of parent scope.
Looking more carefully, there's two variable's named jLocal. One local to myFunc and an implicit one on global scope.
Want a tip?
Put "use strict"; just before var global1 = true;. An HTML 5 implementation would be able to catch and show your error.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to gain access to the closure of a function?
Say I have the following implementation of the revealing module pattern:
var myModule = (function() {
var myVar,
_self = this;
function setMyVar( myVar ) {
_self.myVar = myVar;
}
return {
setMyVar: setMyVar
}
})()
myModule.setMyVar('happy');
What I want to do is set the module level myVar to be 'happy'. This doesn't work because 'this' is equal to window in the anonymous parent function. One easy work around would be to avoid child-parent name collisions, but putting that aside, is there a way I could have access to a reference to the anonymous function scope from inside a nested child function?
"One easy work around would be to avoid child-parent name collisions"
Please don't consider that to be a workaround, but rather a best practice. Variable shadowing doesn't often add benefit, but can add confusion to code and bugs when you forget which variable you're working with.
The only variable scope (or variable object, or binding object... whatever) that is available as an object that can be directly manipulated in code is the "global" scope. No nested scopes allow this sort of direct access, so no, there's no other option other than to avoid shadowed variables.
This should generally not be an issue. A function variable or parameter can only access (and therefore shadow) variables in its original scope, so passing a function into a different scope will not cause any sort of conflict with the variables in that scope.
If needed, code validators like http://jshint.com are able to catch shadowed variables for you.
No. If it is masked, it is masked and you can't get access to it.
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.
When I call a function, a local scope is erected for that call. Is there any way to directly reference that scope as an object? Just like window is a reference for the global scope object.
Example:
function test(foo){
var bar=1
//Now, can I access the object containing foo, bar, arguments and anything
//else within the local scope like this:
magicIdentifier.bar
}
Alternately, does anyone have a complete list of what is in the local scope on top of custom variables?
Background: I'm trying to get down to a way of completely shifting to global scope from within a function call, the with statement is a joke, call works a little better, but it still breaks for anything declared in function scope but not in global scope, therefore I would declare these few cases in global scope, but that requires me to know what they are. The IE function execScript makes a complete shift, but that only solves the problem for IE.
Note: To anyone loading JavaScript dynamically, setTimeout(code,1) is a simple effective hack to achieve global scope, but it will not execute immediately.
No, there's no way to reference the variable object of the execution context of a function binding object of the variable environment of the execution context (that's what that thing is called [now; hence the strikethrough]; details in §10.3 of the specification). You can only access the limited view to it you get with arguments (which is very limited indeed).
Usually when I've wanted to do this, I've just put everything I wanted on an object and then used that (e.g., passed it into a function). Of course, any functions created within the context have access to everything in scope where they're created, as they "close over" the context; more: Closures are not complicated.
I know this is hugely late, and you're probably not even slightly interested any more, but I was interested in the feasibility of this too and you should be able to make a work around of some sort using:
(function(global) {
var testVar = 1;
global.scope = function(s) {
return eval(s);
}
})(this);
then running:
scope('testVar'); // 1
returns the variable from within the closure. Not particularly nice, but theoretically possible to wrap that in an object, perhaps using some validation and getters and setters if you needed?
Edit: Having re-read the question, I assume you'd want to access it without having to specify a function in the scope itself, so this probably isn't applicable. I'll leave this here anyway.
Certain versions of Netscape had a magic property in the arguments object that did what you're looking for. (I can't remember what it was called)
What about something like this?
<script type="text/javascript">
var test = {
bar : 1,
foo : function () {
alert(this.bar);
}
}
test.foo();
</script>
You don't need a keyword to reference a variable in the local scope, because it's the scope you're in.