Global "window" object - javascript

The global window object stores properties specific to the environment (for example, window.innerHeight).
But if we print window to the console, we will see the properties highlighted in a different color.
These include Array, Object, and so on, although i thought they are internal objects.
I have a few questions:
What are these "implicit" properties?
Where do JS boundaries end and environment begin?
Can I refer to Array in Node.js, for example?
Thank you.

In the early days of Javascript, there was one master global symbol and everything that was available in the global scope whether it was part of the language itself or part of the browser environment was a property of that master global.
In the browser, that master global is the window object. Thus, you see many things on the window object that are available globally like the Array constructor.
I would guess that this is a side effect of that fact that Javascript was first designed to run in a browser and was not initially a completely stand-alone language with a stand-alone specification.
More recent revisions to the language specification are not adding some new things to the window object any more. For example, when you declare an ES6 class such as:
class Foo {
constructor(greeting) {
this.greeting = greeting;
}
}
You will not find Foo on the window object even though it may be globally available in the browser.
As others have said, the color difference in the debug output has to do with whether the symbols are enumerable or not which is a technical distinction on whether the property shows up in something like Object.keys() or a for/in loop. The property is still there and is accessible either way.

Related

What is the use of cyclic reference in javascript

I was wondering despite of memory leak, what is the use of a circular reference in javascript? Even window object in the browser is circular referenced like window.window.window ...... Why we are using it and where we can use it. What are the good parts of it?
I was wondering despite of memory leak,
There is no memory leak, two objects that reference each other but are not linked anywhere else get garbage collected. The window object will never be collected, so it doesn't matter here nevertheless.
what is the use of a circular reference in javascript?
Like in any other language they can be used for various structures, such as trees (parent <-> child), linked lists (left <-> right) and many-to-many relationships (students <-> classes). Not having them would complicate some forms of traversal and would make programs significantly slower.
Why is window.window a circular reference?
window is not only an object, but it is also the most global scope where all variables are finally looked up. When you use any global variable, such as setTimeout, it gets looked up in the global scope, and therefore the window object.
window.setTimeout === /*window.*/setTimeout
Now if you want to refer to the global object, it has to be looked up in the global scope, which is itself the global object.
window.window === /*window.*/window
Therefore just the window already accesses the circular reference, it is the reason why the global object can be found at all. Otherwise window would have to be a reserved keyword.
see this page, great reasons are there
Why window.window property exists?
The point of having the window property refer to the object itself, was likely to make it easy to refer to the global object. Otherwise, you'd have to do a manual var window = this; assignment at the top of your script.
Another reason, is that without this property you wouldn't be able to write, for example, "window.open('http://google.com/')". You'd have to use "open('http://google.com/')" instead.
.
and see this answer also
https://stackoverflow.com/a/35788599/1475257

Understanding Web API DOM interfaces

I'm trying to learn more about Web APIs. Reading about them I see that among the wide variety of web API's there's the DocumentObjectModel API. Reading about the DOM specifications, I find a list of a lot of DOM interfaces. This makes me feel a little upset. In my ignorance, I think that an API should contain only one interface (only one set of functions and properties), here I find a list of interfaces...and that's the first thing that I don't understand.
Moreover, I usually interact with the DOM using notations like
document.getElementById("idname");
document.getElementByTagName("tagname");
etc ect
I see that some of these DOM interfaces have names that I already know, like "Document" or "Window", I use them (like in the previous two lines of code) but I use them not capitalized ("document" rather than "Document"). I don't understand if there is a link beetwen "document" and "Document", for example...
Finally, I noticed that querying for the global object (in the browser console, for example, simply typing the keyword "this") I have in response an object that (I guess) contains all the properties and functions (or methods) of the global object. And among them there are also functions that have the same names listed in the DOM interfaces list. And that's simply another thing that I noticed that I'm not able to explain.
So, can you help me to understand more deeply DOM API?
Those things arise from an interaction of javascript and the DOM specifications.
The capital-letter Window and Document are interfaces defined by the DOM and HTML specs.
In Javascript, when executed in a browser environment, an instance of Window is the global object and Window is its prototype. document and window are getter properties defined by those interfaces. Since the window is the global object (the top-level this) and variable name resolution walks up the scope chain and finally lands at the global object if it cannot find it elsewhere window will eventually resolve to <global object>.window. Which is the attribute defined on the Window interface, which returns the window instance itself, which also is the global object. It is self-referential.
So the global object ends up having properties defined by javascript, by the dom/html specs and inherited from the prototypes also defined by those various specs.
Some prototypes are also exposed as named properties in the global object and not just the prototype chain of the instances. This is convenient for instanceof checks and feature detection. Some constructors are also exposed, e.g. new Image() creates a new instance of HTMLImageElement the same way document.createElement("img") would.
Additional Document instances can created via various constructors or factories such as DOMParser. Additional Window instances might be accessed through frames, the page's opener or spawned child windows.
Looking at the window object with a debugger may help.

Why do we prepend global variables with `window.`?

In a lot of code examples I see around the internet, global variables such as innerWidth, onresize, navigator, etc., are written as window.innerWidth, window.onresize, window.navigator, respectively.
Why are some of these globals prepended with window. and others, such as document and console typically not prepended?
Edit:
I know how OOP works and that I am accessing various properties of the window object. I'm no novice to JavaScript. I'm sorry if my question may have been unclear. I have been programming in JS for years but have never questioned this convention, hence my question.
In essence, I am asking why we don't put window. before document, but we put it before innerWidth. Is it simply a matter of clarity? In theory, shouldn't I be able to reference any of the globals without the window. prefix and have no problem?
It's unfortunate but window in your browser refers to one object which represents two logically distinct concepts :
an instance of Window, an object with well defined properties like Window.innerWidth, logically mapped to your browser's window (or rather the tab, today, but that distinction is hidden from your script)
the global object to whom all global variables are attached as properties
Semantically, it's cleaner to not prefix the global variables, unrelated with the Window concept, with window..
Now note that this introduces a problem when you refer to your global specific variable like myThing : it's hard to know if you're knowingly referring to a global variable or if it's declared in some intermediate scope (or if you just forgot to declare the variable with var). which leads to a situation in which you won't use window. only for properties of the instance of Window but also for your specific global variables. Of course in practice you'll avoid global variables as much as possible.
Not prefixing with window. also has the advantage, when you forget a var declaration or a library import, to make your code fail fast in a not subtle way (which is better than failing in production in a hard to debug way) :
window.undeclaredVariable // no error, just an undefined value
undeclaredVariable // reference error
JavaScript would probably have been better with a distinction between those two concepts (something like global or root as in node).
All the global functions and variables are attached to the object activator, this object dependent of your host environment (browser, node, etc), in the browser environment the object activator is the window object, so each global function could be access with window.console, this.console or just console, I think the prepend is useful to have a more readable code.
You could access to global scoped variables without the window prepend just innerWidth.
Think of it like objects. You are trying to get the innerWidth of the window object its self. Document is the same way. You are trying to get those variables that describe the document itself instead of the window as a whole. And console is just that, a console that you console.log to for debugging. It also has its own properties.
They may be global variables, but they still belong to and describe a specific "object" that you must call on first. If that makes sense.

What does the standard (HTML5 and EcmaScript 5.1) say about extending host objects in the browser?

What do the recent standards say about extending host objects and their prototypes? E.g. is extending NodeList with a method _forEach or Document with a method _my_query properly defined?
Will I see anything I add to Object.prototype on host objects by the standard?
How do real implementations behave with respect to the relevant standards?
Note: I am not asking whether it is a good idea to extend host objects or their prototypes (although Object.defineProperty makes things a bit easier when it comes to enumerating issues).
ECMAScript 5 does not say anything about host objects' prototype chain.
This is defined in WebIDL.
Specifically, take a look at ECMAScript bindings section, which says:
Unless otherwise specified, the [[Prototype]] internal property of
objects defined in this section is the Object prototype object.
and this, from the following section:
Each ECMAScript global environment ([ECMA-262], section 10.2.3) must
have its own unique set of each of the initial objects, created before
control enters any ECMAScript execution context associated with the
environment, but after the global object for that environment is
created. The [[Prototype]]s of all initial objects in a given global
environment must come from that same global environment.
There's even an example:
iframe.appendChild instanceof Function; // Evaluates to true
Finally, Interface Prototype Object section says (emphasis mine):
The named properties object for a given interface A must have an
internal [[Prototype]] property whose value is as follows:
If A is not declared to inherit from another interface, then the value
of the internal [[Prototype]] property of A is the Array prototype
object ([ECMA-262], section 15.4.4) if the interface was declared with
[ArrayClass], or the Object prototype object otherwise
([ECMA-262], section 15.2.4).
Otherwise, A does inherit from another interface. The value of the
internal [[Prototype]] property of A is the interface prototype object
for the inherited interface.
So now if we look at DOM Level 3, and Document interface we can see that it inherits from Node interface. Node interface does not explicitly inherit from anything else, which means it inherits from Object.prototype.
This is theory :)
In practice, not all browsers follow this behavior, although most of the recent ones certainly do.
The ECMASCRIPT5 spec states :
A web server provides a different host environment for server-side
computation including objects representing requests, clients, and
files; and mechanisms to lock and share data. By using browser-side
and server-side scripting together, it is possible to distribute
computation between the client and server while providing a customised
user interface for a Web-based application.
Each Web browser and server that supports ECMAScript supplies its own host environment,
completing the ECMAScript execution environment.
I do not think it says anything else. This can be read to mean that an implementation can conform to the spec and implement the browser objects however it wants. This has been the case in the past. It does seem logical though to apply the power of the language to the external environment and I believe that all "modern" browsers now do that.
the dom/html elements have an prototype chain as follows:
HTMLElement > Element > Node > Object
hooking in anywhere in the chain where it makes the senes is probly the best bet.

Cross Browser Valid JavaScript Names

Before you quickly post with "RTFM" or with a bunch of links I have visited, I am fully aware of the documented reserved variable names not to use.
The best lists I could find are here:
http://es5.github.com/x7.html#x7.6.1.1
and
http://www.javascripter.net/faq/reserved.htm
What I am asking for are the variable names that are invalid on 1 or 2 browsers only.
For example I can define print but this will cause an error as print is already defined on the global scope window. Why isn't this documented as a reserve keyword?
Is there a big list of variable names to avoid?
What I am asking for are the variable names that are invalid on 1 or 2 browsers only.
If any such words exist, that browser would be non–compliant with ECMA-262. Only the reserved words in ECMA-262 are "invalid variable names" (provided the name is otherwise compliant with the criteria for variable names, such as allowed characters).
Why isn't [print] documented as a reserve keyword?
Reserved words can only be defined by standards that have a concept of reserved word, the only standard relevant to scripting DOMs in browsers that has that concept is ECMA-262. And it doesn't list print as a reserved word, so it isn't one.
There are various DOM standards that define host objects and their properties, the closest they might get to the concept of reserved word is that of a read–only property, or one that is not writeable. window.print is defined in HTML5, which doesn't define it as not being writable or that it should throw errors if assigned to or attempts are made to modify it. So it doesn't exhibit any behaviour approaching that of a reserved word.
Is there a big list of variable names to avoid?
No, because there aren't any. However, host objects (like window) have default properties that are writeable, you should avoid overwriting them. They should be listed in various places, like the HTML5 specification and browser vendor documentation.
e.g. the following links for the window object:
W3C HTML5 window object: http://www.w3.org/TR/html5/browsers.html#the-window-object
MDN window object: https://developer.mozilla.org/en/DOM/window
MSDN window object: http://msdn.microsoft.com/en-us/library/ms535873(v=vs.85).aspx
In addition, there is a simple for..in loop (per Berji's answer) to discover the enumerable properties at a particular time, however that may not be a comprehensive list of all possible property names and will include user defined properties along with default browser properties without distinction.
It is a better strategy to adopt a naming convention that avoids likely property names and minimise the use of global variables (i.e. user defined properties of the window object).
If you want a big list of browser-defined variables to extend the official list of reserved keywords, type the following into your console on an empty page (about:blank):
>>> Object.getOwnPropertyNames(window)
>>> Object.getOwnPropertyNames(Object.getPrototypeOf(window)) // sometimes not Object
which will yield an Array of strings you definitely should not use. It includes "print", too.
Yet it will be browser-dependent, because some do not implement all the cool HTML5-drafted stuff that uses the Window interface; e.g. you won't find "Worker" in IE9, "openDatabase" in FF and so on. Also, it might not list legacy properties like "onload", altough you will be able to to get a property descriptor for it (and "onload" in window === true).

Categories

Resources