`this` in global scope in ECMAScript 6 - javascript

I've tried looking in the ES6 draft myself, but I'm not sure where to look:
Can someone tell me if this in ES6 necessarily refers to the global object? Also, will this object have same members as the global scope?
If you could answer for ES5 that would be helpful as well.
I know this in global scope refers to the global object in the browser and in most other ES environments, like Node. I just want to know if that's the defined behavior by the spec or if that's extended behavior that implementers have added (and if this behavior will continue in ES6 implementations). In addition, is the global object always the same thing as the global scope? Or are there distinctions?
Update - Why I want to know: I am basically trying to figure out how to get the global object reliably in ES5 & 6. I can't rely on window because that's specific to the browser, nor can I rely on global because that's specific to environments like Node. I know this in Node can refer to module in module scope, but I think it still refers to global in global scope. I want a cross-environment ES5 & 6 compliant way to get the global object (if possible). It seems like in all the environments I know of this in global scope does that, but I want to know if it's part of the actual spec (and so reliable across any environment that I may not be familiar with).
I also need to know if the global scope and the global object are the same thing by the spec. In other words will all variables in global scope be the same as globalobject.variable_name?
Update 2 - What I'm trying to do:
I have developed some ES6 shims for ES5 environments. I want to know the best way to (1) check to see if the ES6 built-ins already exist so that they can be used when possible instead of my shims, and (2) add my shims to the global scope if the built-ins do not already exist.
Currently I'm following this pattern:
(function() {
// Indirect eval to run in global scope.
// (We get whatever "this" is in global scope, hoping that it's the global object...
// Whether this line does what I want it to is the crux of my question.)
var global = (0, eval)('this');
// If Symbol does not already exist in global scope,
if (!global.Symbol)
// Then add Symbol to global scope.
global.Symbol = (function() {
// ...
// Return my Symbol shim
})();
})();
There are some other possibilities for (1), but at the end of the day I need a way to add something to global scope without using var in global scope (because that would override the built-ins before I can check for them, due to var hoisting [at least in the naive case, perhaps I could indirect eval a var statement as well?]). I want my code to be able to run in strict mode, so that compounds the problem.
I have discovered that, by the ES5 spec, indirect eval executes code in global scope. So I am at least able to do that. My questions are if I get this in global scope, (1) Will checking the properties of that object let me know if a built-in already exists in global scope? and (2) Will adding properties to that object allow me to add variables to global scope?

Yes, this in global scope will continue to refer to the global object in ES6. (Generally, ES6 is supposed to be fully backwards compatible, i.e. any code that was guaranteed to work in ES5 should also work in ES6).
The notion of "global scope", however, will no longer be identical with the global object in ES6. It introduces new declaration forms that are lexically scoped (let, const, class, module, and a few more). The conclusion at the last meeting was that none of these will appear as properties of the global object. There is a variety of technical and methodological reasons for that, but the bottom line is that it is best to avoid using the global object directly altogether (this has always been true, but is even more so in ES6).
Is there something specific you need the global object for?

Mostly yes.
Passing this in any non-object (or non-set this) will refer to the global object:
(function( global ){ /* do stuff! */ }(this));
This behavior is intended to stay in ES6 (for understandable backward compatibility issues). And that's how most of multiplatform (Browser/Node) plugins I know of are accessing the global object. For example: https://github.com/documentcloud/underscore/blob/master/underscore.js#L12
Although, it's true that plugin on the server only access this as being module (which is exported). But, that's what you want in node. Your global space isn't cleaned up ever (except if done manually, or on server restart). So it's shared between all client connections; assigning anything to the global space is really not a good idea.
The only notable difference in how this is handled between javascript "version" is in strict mode, where it will throw an error is if null or undefined is passed to call or apply or bind (in the position of the this value). In un-strict mode, this was only coerced to the global object.
"use strict";
foo.apply(null); // Throw error
Hope this help!

Related

What can we do with global variables in the console?

I've read that, in the console, variables with let, const or class, defined in the 'inner global environment' (I understand this to mean the 'highest' line of code i.e. not scoped in a function) are considered global variables.
In node.js, I understood global variables can be accessed in all files. Does a global variable in the console have any similar attribute? I already know that it can be accessed anywhere in the console. If that's all it means then that's fine.
Variables defined with let, const or class are not automatically global variables. It depends on the scope, where you defined them. If they are defined in a function, they are block-scoped (i.e. only usable in that function). Outside of a function, they are globally accessible (for instance, in a function you can use these variables without defining them explicitly) but it is usually not necessary and must be avoided, if possible. Otherwise, it makes future implementations of software much more complex.

Why call method of window object explicitly, performance will be lower than inexplicitly

In web environment think this code:
window.alert('foo'); //code1
alert('foo'); //code2
Why code2 is higher than code1 in performance? Why does this happened?
First, remember that many globals (including all of the traditional predefined globals) are properties of the global object, and that on browsers that global object is the window object. window isn't special, it's just a predefined global that refers to the global object. alert is also a predefined global.
window.alert(...) is slower than alert(...) because in window.alert(...) the JavaScript engine first has to:
Go look up the identifier window, which it ultimately finds as a property of the global object, then
Look up alert in that object's properties, then
Call the function it found
In alert(...), it only has to:
Go look up the identifier alert, which it ultimately finds as a property of the global object, then
Call the function it found
So instead of looking for two things, it only has to look for one.
Less work = faster performance.
Having said that, two observations:
The speed with which you show an alert is...not usually important. :-) alert does, after all, seize up the JavaScript engine until the user dismisses it.
Even with something that doesn't seize up the JavaScript engine, the difference between window.xyz(...) and xyz(...) will be trivially small in most cases. Typically you see window.xyz(...) for other reasons (such as some other xyz being in scope when you want to access the global one). (I'm not saying they're good reasons; typically you can avoid that, and of course one tries to avoid globals wherever possible anyway...)
If performance calling a global function matters (by definition, this means you're calling it a lot), you probably don't want to use the global reference to it anyway; grab a local reference to it in your inner scope (var f = theGlobalFunction;) and then use f(); to call it repeatedly. This avoids both lexical environment traversal and lookup on the global object. And again: Only matters in very rare cases; don't do it until/unless you've identified an observable performance problem and narrowed it down to the global function call. :-)
The time for that first lookup (the global) depends on how deeply nested the code is (and thus how many lexical environment objects need searching before the global one is reached) and how many properties the global object has. The second part, looking up the property, is only dependent on the second one. A truly hideously massive mass of globals (such as is created if you use ids on lots of elements, since those get added as automatic globals) can conceivably slow down global lookup time.

Have javascript declare (by default) undeclared variables to the current local scope (based on first use) instead of global scope?

Can this be done either via writing some code to intercept the global scope default declaration or via a setting within the javascript engine itself which each program or function has access to?
What I mean is if I could, at the top of the program (or function), tell the javascript engine to use local scope for undeclared variables instead of global scope... then, when the javascript engine compiles each function, it would declare them in local scope.
I understand if you want to declare a variable outside of the current scope, that should be done explicitly since no one knows where you want it declared, but I think defaulting to global scope leaves too much room for error and forces too much typing of var statements in each function, so I'd like to change the default in my programs if that's possible.
My primary purpose is to avoid having to type the list of local variables in a var statement at the top of every function, and to avoid the maintenance of keeping this list in sync with the local variables as I'm using them within a function. Not allowing a global scope default also reduces the risk of errors.
I would never want undeclared variables to end up in any higher scope than the scope in which they are first used. There is no value in having them default to global scope that I can see.
I know I can explicity declare variables in the current scope (or the global scope), but would like to avoid doing so and use a more useful default than the global scope default built into javascript.
I also know I can use "use strict" to force all variables to be declared explicitly. Not wanting to debate the right or wrong of it, but just asking if there is any way to change the default to local scope instead of global scope for a given function.
No, Javascript behaves the way it does, there's no switch to flip to turn its variable declaration rules on its head.
'use strict' is an option you can employ to help you catch problems more easily, but it doesn't change the rules.
What you want is a different language; for example CoffeeScript, a Javascript preprocessor which, among other things, happens to solve this variable declaration issue explicitly.

What's the global object within a module in nodejs?

I know in node, every module gets an local scope and variable defined within one module won't escape to the global unless explicitly exported.
What I want to know is when I declare a variable in one module file as the following, what's the global object this variable defined on?
var obj = {};
// In browser, this is defined on window.obj
// How about in the node?
There is one statement that global is the object used as the local global scope, however the following test code fails:
a = 1
console.log global.a
// undefined
So what is the global variable for a module?
There is in fact a global object in node; it's simply called global. You can assign properties to it and access those properties just like any other object, and you can do it across modules. However, directly accessing it (global.foo=bar in one module, baz=global.foo in another) is the only way to access it. Unqualified variable names never automatically resolve to its properties the way that, say, an unqualified variable name in a browser environment would resolve to window.somethingOrOther. In node, every module is conceptually wrapped inside an immediate function call, so unqualified names represent local variables and have module-level scope.
edit again I'm just about ready to conclude that, in a Node module, you can't get a reference to the global object. You really shouldn't need to; that's kind-of the whole point of the module mechanism, I think. You import what you need and export what you choose.
Whether there even is a global object in Node is an interesting question, I guess. I know that in Rhino, there definitely is; there's no implicit wrapper function around code fed to Rhino from the Java container. Via the Java ScriptEngine mechanism (and presumably from Mozilla APIs in "naked" Rhino) there are ways of pushing symbols into the global context to make them visible to JavaScript as global object properties.
wow this got complicated well things seem to be on the move in the Node.js world. What I wrote above was true for Node 0.6.2, but in the 0.9.0-pre build I just did there is indeed an object called "global" that behaves more or less like the global object in a browser.
The stuff below applies to browsers and Rhino and other contexts like that
You can use this in the global context. If you need a name, you can give it one.
var global = this;
var obj = "Hi!";
global.obj = "Bye"; // sets "obj"
A (somewhat) common idiom is to wrap your code in a function, to protect the global namespace.
(function( global ) {
// everything
})( this );
Caveat: I'm not a Node person so there may be some emerging idiom in that culture.
edit — it occurs to me that if Node really does wrap code from files it evaluates in a function, and it doesn't pass this into it from the global context, then there's no way to "find" it, I don't think. If you use "use strict" (and you should), it doesn't matter, because you can't really mess with the global context anyway.

What are some of the problems of "Implied Global variables"?

JavaScript: The Good Parts defines these kinds of declarations as bad:
foo = value;
The book says "JavaScript’s policy of making forgotten variables global creates
bugs that can be very difficult to find."
What are some of the problems of these implied global variables other than the usual dangers of typical global variables?
As discussed in the comments on this answer, setting certain values can have unexpected consequences.
In Javascript, this is more likely because setting a global variable actually means setting a property of the window object. For instance:
function foo (input) {
top = 45;
return top * input;
}
foo(5);
This returns NaN because you can't set window.top and multiplying a window object doesn't work. Changing it to var top = 45 works.
Other values that you can't change include document. Furthermore, there are other global variables that, when set, do exciting things. For instance, setting window.status updates the browser's status bar value and window.location goes to a new location.
Finally, if you update some values, you may lose some functionality. If, for instance, you set window.frames to a string, for instance, you can't use window.frames[0] to access a frame.
Global variable make it very difficult to isolate your code, and to reuse it in new contexts.
Point #1:
If you have a Javascript object that relies on a global var. you will not be able to create several instances of this object within your app because each instance will change the value of the global thereby overwriting data the was previously written by the another instance.
(Unless of course this variable holds a value that is common to all instances - but more often than not you'll discover that such an assumption is wrong).
Point #2:
Globals make it hard to take existing pieces of code and reuse them in new apps. Suppose you have a set of functions defined in one file and you want to use them in some other file (in another app). So you extract them to a new file and have that file included in the new app. If these function rely on a global your 2nd app will fail at runtime because the global variable is not there. The dependency on globals is not visible in the code so forgetting these variables (when moving functions to new files) is a likely danger.
They're global variables, so yes, all of the "usual dangers" apply. The main thing that distinguishes them from global variables in other languages is that:
You don't explicitly declare them in a global scope. If you mistakenly omit var in a variable declaration, you've accidentally declared a global variable. JavaScript makes it a little too easy to unintentionally declare global variables; contrast this with Scheme, which raises an error if a variable is not defined in the global scope.
Global variables, at least in the browser, are aliased by window[variable_name]. This is potentially worrisome. For example, some of your code might access window['foo'] (with the intention of accessing a global variable). Then, if you accidentally type foo instead of var foo elsewhere in the program, you have declared a reference to window['foo'], which you meant to keep separate.
One issue is that you may be trampling on already defined variables and not know it, causing weird side effects in other parts of the code that can be a bear to track down.
Another is that it is just sloppy code. You should not be creating variable with more scope than they need since at the very least it keeps more variables in memory and at worst it can create data scenarios you didn't intend.
The bottom line is that when you do that you don't know for sure that you are not messing up other functions that use a global variable of the same name. Sometimes it isn't even your fault, a lazy programmer of another plugin left something global that was meant to have scope inside of a function. So it is a very practical safeguard for writing better and less buggy code.
The problems of typical global variables is that they are, well, global - there is no scope to enclose them, and any code that you are executing / interacting with (such as a library that you call down the road) could modify the variable without a warning.
However, these problems are compounded in Javascript by two things:
You can define a global variable anywhere - the only requirement for that is to forget the var keyword.
It is extremely easy to define a global variable when you had no intent to do so. That is the problem that "implied" globals have over "typical" globals - you will create them without even knowing you did.
In a reasonably-designed language that includes truly global variables (ok, so not that reasonably-designed), you would have a limited handful of places to define globals, and it would require a special keyword to do so.

Categories