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.
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.
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.
I was looking at adding comments to JSON and found this script that strips them out before processing making the JSON valid. I am just trying to understand how it works to make the JSON.minify() function available?
It starts with
(function(global){ ...
totally which is weird to me. I found that "global is a property of a RegExp instance, not the RegExp object" on MDN but I don't understand how it is works in this script if at all.
This snippet:
(function(global){
// your code here
// referring to the variable named "global" in this scope
// will be a reference to the default javascript global object
})(this);
is a construct for assigning the global object (whatever it might be) to an argument labeled global for all code that is inside this self-executing function.
The self executing function is used to define a separate execution scope so that any functions or variables you define inside this other scope will not interfere with or be directly accessible from outside this scope (insulating your scope from other code scopes).
In a browser, the global object is the window object, but if you intended to have code that might work in other javascript environments (like no node.js on a server) where the global object might not be window, this is a way of extracting the global value from the default this value, putting it into another variable which you can then refer to anywhere inside your code block.
For code mean to only run in a browser, there really is no point to this. You can just refer to window when you need the global object.
It's just a function parameter name. It might as well be froozboggles.
This code:
(function(foo) {
// In here, what's called "bar" in the outer scope is called "foo"
})(bar);
Defines an anonymous function taking one parameter bar and immediately calls it with the value of bar as the first parameter.
Apart from what jfriend00 mentions in his fine answer, it's also a good way of making sure that you don't leak variables and functions to the outer scope: If you declare, say, var baz = 17; in the top scope in javascript, it will be a property of window. If you wrap it in a function as in the pattern you mention, you can only export properties to window explicitly -- by assigning them to global, in the case of your example. Edit: As #josh3736 says in his comment, you can also leak to window by assigning without a previous declaration, e.g. quux = 4711;.
I've been doing some javascript reading, and I've gathered that a closure has access only to the closure "wrapping" it, or, you might say it's immediate parent. Now I've been playing a bit, and I see in this jsfiddle that even deep nested functions have access to to vars defined way up.
Can anyone please explain that? Or explain what have I got completely wrong?
http://jsfiddle.net/tPQ4s/
function runNums() {
this.topVar = 'blah';
return function(){
(function() {
(function() {
console.log(topVar);
})();
})();
}
}
var someFunc = runNums();
someFunc();
Without going too deep into the details, a closure technically describes a array like variable within the such called Activation Object that is handled from the javascript engine. An ActivationObject contains Variables declared by var, function declarations and formal parameters.
That means, anytime a new function (-context) is invoked, internally a new Activation Object is created. That object is part of the new Execution Context, a typicall EC looks like:
this context variable
Activation Object
[[Scope]]
The interesting part here is [[Scope]]. That variable contains all Activation Objects of all parent context and is filled when the EC is called. So now, when a function wants to access a variable, the name resolution process first looks into its own Activation Object, if nothing is found the search continues in the "Scope chain", which is just an Indexed search through our [[Scope]] variable (which again, is an array of parent contexts). Thats why we also speak a lot about "lexical scope" in ECMA-/Javascript.
Note: The above behavior is not described entirely, that would need several pages of text. Also it describes the ECMAscript3 262 specification. Things work a little different in ES5, but its still around the same thing
That is because the chain runs further up to the top context.
In the example, that would be:
window < runNums < anonymous < anonymous < anonymous
Variables living in any of these will be available in the last anonymous function. In runNums, only variables living in runNums or window will be available. In the first anonymous function, only its variables and those living in runNums or window will be available, etc.
this is nothing but the Window object here.
Here runNums is a global function and runNums() is equal to window.runNums(). So this is window and this.topVar is window.topVar. Obviously it will be accessible from anywhere.
Try this and see the difference
var someFunc = new runNums();
someFunc();
The deep nested functions have not been executed. You did not return them for executing.
I'm new to JavaScript, and have a simple (I presume) question regarding best practices for accessing variables in functions:
When should I declare a global variable, as opposed to simple passing a value into a function?
Declaring a global variable should only be used as an option of last resort.
Global variables are bad in general and especially so in javascript. There is simply no way to prevent another piece of javascript from clobbering your global. The clobbering will happen silently and lead to runtime errors.
Take the following as an example.
// Your code
myParam = { prop: 42 };
function operateOnMyParam() {
console.log(myParam.prop);
}
Here i've declared 2 global variables
myParam
operateOnMyParam
This might work fine while testing your javascript in isolation. However what happens if after testing a user combines your javascript library with my javascript library that happens to have the following definitions
// My code
function myParam() {
console.log("...");
}
This also defines a global value named myParam which clashes with your myParam. Which one wins depends on the order in which the scripts were imported. But either way one of us is in trouble because one of our global objects is dead.
There are many, many reasons.. but an easy one is.. The argument of a function only exists in the function, while it's running. A global variable exists all the time, which means:
it takes up memory until you manually 'destroy' it
Every global variable name needs to be unique
If, within your function.. you call another function.. which ends up calling the first function, all of a sudden you may get unexpected results.
In short: because the function argument only lives for a really short time and does not exist outside the function, it's much easier to understand what's going on, and reduced the risk of bugs greatly.
When dealing with framework-less JavaScript I'll store my simple variables and functions in an object literal as to not clutter up the global namespace.
var myObject = {
variableA : "Foo",
variableB : "Bar",
functionA : function(){
//do something
//access local variables
this.variableA
}
}
//call functions and variables
myObject.variableA;
myObject.functionA();