Is setTimeout located somewhere besides window? - javascript

The reason I ask is b.c. of the strange title for the MDN entry found here:
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
WindowOrWorkerGlobalScope
I'm trying to understand why it is not listed under the window object?

Not all browser environments have a window object that corresponds to the global scope. Currently the various worker environments (Web, Shared, and Service) are good examples of these types of environments.
WindowOrWorkerGlobalScope defines a common set of methods shared by all browser global scopes. Window and WorkerGlobalScope define additional functionality on top of these methods.
This means, for instance, that you an access setTimeout from any browser JS environment but that open is only available in a window global scope and importScripts only in a worker environment.

Related

How does Javascript runtime identify setTimeout() as a WEB API?

When javascript runtime finds setTimeout() method, it sends it to Event table. How does runtime know that setTimeout() is a WEB API? Does it first look for setTimeout() method in the current context and then if not found assumes it as a WEB API?
When javascript runtime finds setTimeout() method, it sends it to Event table.
JavaScript doesn't "know" or care what setTimeout does. :-) It's just that setTimeout is one of the functions defined in the host environment provided to the JavaScript engine by the host (the browser, in your example). When you use JavaScript to call the function, the function's implementation (provided by the host environment) is executed with the information you provide. It's the host, not the JavaScript engine, that knows what to do with the arguments you provide to setTimeout.
When the host (the browser or Node.js or whatever) needs to create a new runtime environment (for instance, for a window), one of the things it does is create an object to be the host-provided global object for that environment (more properly called a realm), including putting any properties on that object (like setTimeout) that provide host-defined features. It provides that object to the JavaScript engine via what the JavaScript specification calls the InitializeHostDefinedRealm abstract operation. When the JavaScript engine runs your code that uses setTimeout, it sees the identifier setTimeout and looks in the current execution context to see if setTimeout is defined there; if it isn't, the engine looks at the parent execution context, and so on, until it reaches the global execution context, which gets its globals from the host-provided global environment (in part; it also has other globals). So, having found the function matching setTimeout, the JavaScript engine calls that function — which runs the host-defined code for the function, which sets the timer.
So the JavaScript engine doesn't know what setTimeout does, just that there is a setTimeout function on the global object it got from the host.
In terms of identifying which function to run, it doesn't make any difference whether a function is built into the engine, or added at run-time (this fact is really useful, allowing functions to be "polyfilled" if the engine doesn't provide them).
When you write foo(), JS actually looks for a variable with that name (this unification of variables, properties, functions and methods is an unusual feature of JS). It looks for it first in the local scope, then in the parent of that scope, and so on up the "scope chain".
The last place it looks is the "global object", which in a browser is the window object. So if you define window.foo as a function, you can call foo() from anywhere that doesn't have its own function called foo in scope.
Built-in functions work just the same way: when the JS engine starts up, it (conceptually) defines a whole bunch of functions on the window object, with special implementations referring to internal operations in the engine rather than composed of JS code.
So when you call setTimeout, JS walks up the scope chain, and if it doesn't find anything else, will find the setTimeout function registered by the engine, and runs it. The engine then does whatever it wants to do with that - hopefully, something that complies with the behaviours described in the current ECMAScript standard.

Global "window" object

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.

Will `typeof window === 'object'` always be true?

Assuming window isn't shadowed, will typeof window === 'object' always be true? Is this safe?
Context: I'm trying to export a module to the global scope using browserify and I want to include a check to see if this module is run in the browser and if it is, I want to export it to the global object.
If you have the real window, defined by the runtime, it will always be an object. The typeof operator (§12.5.6) has a limited number of return values (table 15), and there's no special one for window. If they expand that table, it could change, but the only applicable result in ES1 through ES7 is 'object'.
Bear in mind that Node doesn't define window at all (so typeof would be 'undefined') and you can shadow it, as you mention. In a browser with a standard DOM implementation, window will be the object defined in §7.3 of the DOM specification. For JavaScript, this should be an object and I believe all browsers expose it as such.
In webpack, you would use the output.library property and set output.libraryTarget to 'var', then the bundle sets up the global for you. I imagine browserify has an equivalent.
The answer is: It depends.
Short answer:
If you're in a browser, then yes, window will always be an object. If you're on a JavaScript standalone engine such as Node.js, then probably no.
More details:
A window is one of the top-hierarchy objects on a browser. It is the parent of the whole DOM tree present inside a browser window (or tab), and the context reference where most of functions and event listeners will often run.
So in any browser that expects to work properly, there will be a window object. (some side/experimental projects may have modified JavaScript engines and not implement window, but this is highly unlikely and definitely not the kind of thing that is going to be used by "mainstream users")
However, when we talk about JavaScript engines running outside browsers, things get a little different. On a server-side JavaScript runtime such as Node.js, the purpose is not to work with windows/tabs, URLs and DOM tree parsing such as a browser do. So you will not have this object available and running typeof window will return 'undefined' on those environments.
To add a variable to global scope, browserify exposes global which in the browser represents window.
Per the browserify docs (emphasis mine)
Additionally, if you use any of these variables, they will be defined in the bundled output in a browser-appropriate way:
process
Buffer
global - top-level scope object (window)
__filename - file path of the currently executing file
__dirname - directory path of the currently executing file
As far as the question being asked:
Assuming window isn't shadowed, will typeof window === 'object' always be true?
Yes given that it's running in a browser environment.

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.

Window object and properties persistance

I know the Window object is the "master" object of the browser (tab) to which everything is appended - core methods, globally declared variables, functions, even the DOM. It is above everything.
When I go to a different page in the same browser window (tab) I suppose the window object remains the same (only the dom changes), because the history and other stuff is accessible. Why I don't quite grasp is why the global variables that are attached to the window object (even using window.myvariable) don't persist.
To me the only possible explanation is because it is made this way. If so what happens, do the "non core" window elements (methods and variables that were set by the code) get erased; is every new page visit a new instance of the window object (sounds the most obvious way to me) or ...?
I can't find any useful info on this matter, usually people only know that you can't pass variables between pages (except cookies, web storage, window title), but why/how (the mechanics, not reasons) this happens are hard to come by. Thanks.
Every tab in your browser is independent window object and has its own set of global variables and thus your assumption of sharing window object is not correct. Your javascript is not and should not be allowed to SEE between tabs. If that was possible then imagine one webpage you open sniffing data and other information between tabs. Your tabs are not allowed to do your browsing history sniffing ( they can get the length of the history, I think, though).
How can the browser be secure (If you are browser's vendor)?
First, it can chose not to support certain capabilities, period such as reading client's file system arbitrarily.
Second, restrict some of the features they provide.
You might want to take a look at Same-Origin Policy and certain restrictions that are relaxed that might be helpful.
All the global JavaScript variables, functions & objects automatically become member of the window object and they are persisted as long as the the new page is not loaded/visited in the same browser window (tab).
Whenever new page is loaded or we redirect to new page within same tab then scope of these functions and variables from previous document ends and they are removed from the window object. And globally declared variables and functions for newly loaded document (from scripts associated with document) gets attached to the window object

Categories

Resources