While coding I realized that certain variable names such as top, self, left\right create all sorts of errors when you try to use them. What's the reason behind this in JavaScript, while other languages can use them?
You can't use them as global variables because there already exist global accessor properties with these names.
top is used to access the top frame.
self is used to access the global object.
As far as I know there is no problem with left and right.
console.log(Object.getOwnPropertyDescriptor(window, 'top'));
console.log(Object.getOwnPropertyDescriptor(window, 'self'));
Attempting to assign some value to these variables will run the setter, which may not do what you expected. If there is only a getter but no setter, the assignment will be ignored in sloppy mode and throw in strict mode.
There is no problem in using these names as local variables. You should not use global variables anyways.
(function() {
var top = 123; // local variable
console.log(top === 123); // true - no problem
})();
var top = 456; // global variable
console.log(top === 456); // false !!!
There are no problems using variables with those names in JavaScript in most cases.
In some environments, some of the names are already used for existing global variables and are read only.
top is one such example, it refers to the top level frame.
You can still use it as the name of a variable in a non-global context.
Most probably you use variables without declaring them with var/let, and in such circumstances, you modify properties of the global execution environment.
In browser, the global execution environment is window, so when you do
self = '...'
you effectively do
window.self = '...'
self, top, left, right are properties of window object which may have certain non-standard behaviors. Many built-in properties of window object are in fact implicit setters which do more than setting a variable - they can also modify the current page, navigate etc. Also, many built-in properties of window can not be overridden, so assigning to them has no effect.
Contrary, when you do
(function() {
var self = '...'
})()
you should not have any problems.
You need a function call to make it work properly, to create a new scope, because in global scope, even with var, you'd still implicitly assign a property to window.
Related
(Sorry for my poor English)
I finally realized why it's better to use let or const instead of var because var can't work with window properties!
However, is it a good idea still to use window properties as variable names just because you can bypass the problem by using other two keywords of creating variables?
For example:
var name = 'James';
console.log(name);
The above won't work because I'm using var keyword however if I used let or const, this wouldn't cause any error!
So once again, just because I can should I ?
Using variable names that exist as properties on the window object was never the real problem. Using them for global variables was (and still is). But if you are in a local scope, e.g. inside a function, you can name your local variables however you like.
If you cannot avoid global variables, you should strife to use as few as possible, and yes you should try to avoid collisions with other globals, be they properties of window or not. Using let or const just ensures that if they are window properties, your custom variable will shadow them, but you will still break other code that relies on these to be accessible as global variables with the builtin value. However, most of the time you cannot avoid global variables you also cannot avoid var, as let and const cannot be redeclared.
var
Function-scoped variable. It is visible in the current function. If it's outside all functions, then it's visible globally, assuming it's not in module scope.
let
Block-scoped variable. It's visible in the {} block where it was defined.
const
Block-scoped constant. Like let, it's block-scoped, but this one is constant.
object property
window is an object, so let's think about objects in general.
window.foo = "bar"; console.log(window.foo);
"Better"
One is not "better" than the other by definition. You will need to think about your needs and the conventions your team has agreed upon and apply them. Setting window attributes should not be a custom in general, because you are making it global, but sometimes you need to set window properties. Again: always think about what you need to achieve.
A global object is an object that always exists in the global scope. In JavaScript there is always a global object defined.
Can there be more than one global object? Why do people say Window is a global object when MDN doesnt say this?
Every browser window has a single top level Window object routinely referred to as global object. The global object is accessible via window variable.
The object exposes a number of properties, most importantly document which is also an object, methods, and events.
A developer may define (via script) variables (var) and functions which automatically become properties and methods of window (global) object (provided they are declared on top (global) level).
For example, an expression var a = 1; declares a variable named a (and assign numeric value to it). This variable is accessible by its name (a) and as well as window.a and window['a'].
The reference to the global window object can be omitted so window.a = 2; and a = 2; are equivalent (but not ['a'] = 2; which is syntax error).
Also note that global window object belongs to the browser window, not to javascript. The browser only expose it to Scripting Engine.
This is javascript basics.
I hope this explanation clears a little your confusion.
What is the difference between the JavaScript Global object and Window object. I know in both, you don't have to declare the object to use the methods.
The window object encapsulates the global scope. Omitting var (or let) when declaring a variable will implicitly add that as a property to the global scope. It's unique in that sense since there is no equivalent to window when inside a different scope.
I'm going to quote myself on this one:
MDN's description of var states that the global scope is bound to the global object. This would suggest that declaring a variable (either with var at the top level, or without var inside a function) simply adds a new property to window (or an equivalent outside of the browser).
Try it out. Create a variable without using var, then look at the window object in your console. You'll see it in there. It's the equivalent of doing this:
Object.defineProperty(window, 'foo', {
value: "bar",
enumerable: true // see #dandavis' comment on iterating over implicit global vars
)}
This doesn't explain why that's the case. Just that window is unique in that everything is defined within it.
I could be wrong, but it seems to me that the so-called globals are defined under the window object.
In JavaScript that is running in a browser, window is at the top of the scope chain. If you define a "global" variable, it is implied that it is under the window object.
For example:
// Global variable
var g = 0;
function foo(){
window.g = 1
// This will output '1'
alert(g);
}
The global object serves as the top-level lexical environment (the top of the scope-chain, if you will). This means that global properties may be accessed via direct references (like variables):
// global code
this.foo = 1; // creating a global property
foo // accessing the global property via a direct reference
This also means that global variables may be accessed via property references:
// global code
var foo = 1; // creating a global variable
this.foo // accessing the global variable via a property reference
INTERPRETATION 1
Now, based on the above information, it would seem that it would be appropriate to use the terms "global variable" an "global property" interchangeably, meaning that both terms represent the exact same set of global bindings.
However, there are two differences between a global variable created using var ,e.g. var foo = 1;, and a global property created through an assignment, e.g. this.foo = 1;:
Global variables are statically scoped, whereas global properties are dynamically added to the global environment:
foo // => undefined
bar // throws ReferenceError
var foo = 1;
this.bar = 1;
So, global variables are bound before program evaluation, whereas global properties are bound during program evaluation, when the assignment is evaluated.
Global variables are non-configurable, i.e. they cannot be deleted (more specifically, their corresponding bindings cannot be removed from the environment subsequently), whereas global properties created through assignment are configurable.
// the names "foo" and "bar" are bound to the global environment
var foo = 1;
this.bar = 1;
// the binding "bar" can be removed from the global environment subsequently
delete this.bar;
// the binding "foo" cannot be removed subsequently
That being said, it should be noted that it is possible to create non-configurable global properties:
Object.defineProperty( this, 'bar', { value: 1 }); // non-configurable by default
INTERPRETATION 2
Now, based on this new information, one could say that only statically scoped global bindings may be referred to as both global properties and global variables, whereas dynamically added global bindings are merely global properties, but not global variables, meaning that the term "global variable" represents a subset of the set represented by the term "global property", as in:
All global variables are global properties
Only statically scoped global properties are global variables
So, which interpretation is correct? Do both terms represent the same set of bindings, or is one a subset of the other?
THE QUESTION
I do understand the term "global property" - a global property is a property of the global object. However, the term "global variable" appears to be ambiguous. Some use it as a synonym for "global property", while others define it to mean a global property which has been defined via a var statement. The intent of my question is to determine which of these two meanings is correct
Well, you already know everything I would have said to differentiate between the edge-cases of variables and properties which are attached to window.
If you wanted to get really, really pedantic, I suppose that you could consider the global scope to be both a functional-scope and a scope in which the window object is extended with properties using the same hidden configuration settings as what is provided within the program (eg: vars can be reassigned but not deleted). So in that sense, as far as functionality is concerned, they are different, and reflect attributes of properties and variables, globally scoped.
And referring to them as such is totally fine.
But the majority of people out there don't even recognize the difference, let alone differentiate between the two terms.
Even the important JS authors out there have referred to setting a global variable accidentally, by omitting var, when really, JS scales the function scopes, and if it makes it to the global scope without hitting that name, it appends a global property with that data, rather than a global variable.
But that really sort of brings us to the crux -- a strong and stable and reliable JS application, living on a modern webpage along with other applications, really shouldn't be too concerned with the differences.
The goal is to use as few global properties and variables as possible, in that case.
Moreover, the danger of variable/property collision is the same, regardless of which it is.
Variables are immune to delete, but what are the chances that any useful program is going to delete a property it's never even set?
So personally, I think it's good to understand the edge-cases, but I also think that while the pedant in me wants to agree that there's a difference, and they are not coterminous, the pragmatist in me shudders to think of a world where people are actively using the global scope to the extent where this makes a large difference to them.
A good explanation can be found here, but I'll shorten it down to answer your question. When you say:
both terms represent the exact same set of global bindings.
...you're almost correct, but not quite. Property assignments like this.foo = 1 are saved into the global object. Variable declarations like var bar = 2 however are saved into the variable object.
When executing under global scope, both the global object and the variable object are represented by the same object--the global object (when you're executing in a browser, this is the window object).
I mention this because your explanation alone is insufficient to explain the behavior of this program:
// "this" refers to the global object. But global object is also acting as the
// variable object! Because of that, the following code works:
var foo = 1;
alert(this.foo); // 1
(function() {
// "this" still refers to the global object! But the *variable* object has
// changed because we're now in the execution context of a function, thus
// the behavior changes:
var bar = 2;
alert(this.foo); // 1
alert(this.bar); // undefined
})();
This doesn't mean that global properties and global variables are identical however. There are three hidden flags on all properties: ReadOnly, DontEnum, and DontDelete.
When using implicit property declarations like this.foo = 1, the DontDelete attribute is set to false. When you use variable declarations like var bar = 2, the DontDelete attribute is set to true, thus representing the difference between them when you use the delete operator.
In response to your rephrased question:
[T]he term "global variable" appears to be ambiguous. Some use it as a
synonym for "global property", while others define it to mean a global
property which has been defined via a var statement. The intent of my
question is to determine which of these two meanings is correct.
The term is not clearly defined, and therefore you are asking for nothing more than an opinion.
In general, the term "global property" is used when you create a variable using the syntax this.foo = 1, and the term "global variable" is used when you create a variable using the syntax var bar = 2. There's nothing more to discuss.
Neither term has a true bearing on what goes on behind the scenes, thus the best you can do is understand what actually goes on behind the scenes, which you have already done.
Further demanding an absolute definition on two arbitrary terms will simply cause you to be an unpopular person.
I've seen global variables defined with window.global_name.
I wonder why not just using global_name even if this script will be run in closure.
UPD: seems like IE doesn't explicitly add it to the window object, when you declare it inside of a closure
The last object on the scope chain in any ECMAScript environment is always the global object. In browsers, window is to all intents and purposes the global object. If you want to access a property of the global object x or a global variable x (which are almost but not quite the same thing), you should explicitly qualify it with window.x to avoid the possibility of x being resolved as a property of another object on the scope chain, or globalObj.x if you care about portability to non-browser environments. You can get a reference to the global object from anywhere in ECMAScript 3 or non-strict ECMAScript 5 as follows:
var globalObj = (function() { return this; })();
window.x is safer than simply x if there might possibly be another x in the current or preceding scopes. That being said, even window isn't fool-proof because you could define a variable named window.
They have similar effects, but window lets you explicitly declare that you're deliberately using a global. Otherwise, the reader doesn't know whether it's a var further up the scope chain, you just forgot to declare it, etc.
Unless you introduce another scope, e.g. by wrapping your code in a function, window === this === <the global scope>
However, window and this have the advantage that you can use the array syntax (window['something']) so you can access globals even if you have their name only in a string without using evil things like eval.
The answer is yes. If you declare a variable without the var keyword (inside a function), the variable will become implicitely a member of the window object, that is automatically initialized by the browser.
Outside a function, with or without the var keyword, the variable becomes implicitely a member of the window object.