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;.
Related
In the website the following lines are given:
Your global variables (or functions) can overwrite window variables (or functions).
Any function, including the window object, can overwrite your global variables and functions.
I am unable to understand what this says.
Above that paragraph you can find this:
Global Variables in HTML
With JavaScript, the global scope is the complete JavaScript environment.
In HTML, the global scope is the window object. All global variables belong to the window object.
Combined with the quote in your question - it means that because the global scope is actually the window object - it's possible to override global functions/variables.
Here is an example:
console.log(window.Math.PI);
Math = {
PI: 5
}
console.log(Math.PI);
The browser puts certain "global" (i.e. accessible anywhere in any file) functions and variables on the window object. One such example is the function window.setTimeout, which executes its argument after a given delay.
You can also access these global window.* variables without the window prefix at all, i.e.
window.setTimeout === setTimeout
That means if you assign to a global variable with a conflicting name, you can 'override' the browser defaults -
window.setTimeout === setTimeout
setTimeout = 'myString'
window.setTimeout === 'myString'
That's why it's generally best practice not to create variables in the global (window) scope.
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 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.
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.
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.