V8 / JS runtime: how are JavaScript window functions available without prefix "window" - javascript

I don't know much about the JS console but I'm moving into command line programming and it would be good to know my native environment before I start using shell/node in a foreign one
My guess is that all command line statements are invoked with (window) eval(/* whatever user typed before hitting enter/*) but this seems like horrible practice. The context is definitely bound as "Window" if I console.log(this) but I'm not sure why / how
It's almost like the user cd'd into the window object to set it as the context

All JavaScript has a global scope. In the browser, the global scope is called "window" and it is a reference to the window object. In node, it is called "global" and refers to the global JS namespace in node.
The "window" global in a browser has a bunch of properties on it. Things like "console" or "location". When you want to talk to those pieces of code, you can optionally prefix the call with "window.". Example: to log something to the console you can type:
window.console.log("HELLO");
or you can leave the "window." off of the call, like such:
console.log("HELLO");
The global "window" object in the browser is the only optional object on the page. Any time you see a reference to a variable that wasn't declared using "var" (or "let" and "const" in ES6), that means that the variable is just a property on the global object.

Related

What is the purpose of passing WindowProxy as the global this value?

Background
The HTML spec introduces the concept of the WindowProxy.
It says:
A WindowProxy is an exotic object that wraps a Window ordinary object,
indirecting most operations through to the wrapped object. Each
browsing context has an associated WindowProxy object. When the
browsing context is navigated, the Window object wrapped by the
browsing context's associated WindowProxy object is changed.
The WindowProxy platform object is created when the browsing context is created by the host, as defined in ECMAScript's InitializeHostDefinedRealm (step 8). It is directly set to be the global this value.
At that same point, the Window object is created, set to be the global object.
Through the ECMAScript spec, we see that whenever a lookup of an identifier happens, it first searches the environment record of the current execution context, and if not found continues out all the way out to the Global Environment Record, which in turn looks for the identifier on the global object.
As far as I can see, this set of operations never uses the global this value.
Questions
Are there any operations in ECMAScript that use the global this value? If so, which?
How exactly does setting the global this value to WindowProxy result in the desired proxy behavior?
Edit
This StackOverflow question answers the high-level purpose of WindowProxy. My question above is related to the ECMAScript spec and how exactly the standard built-in operations get delegated to the WindowProxy object, by virtue of it being the global this value.
Article with some interesting, but vague, information not related to the ECMAScript spec.
I'm not sure if this is the only reason, but this at least allows to have the built-ins bound to the WindowProxy instead of on the Window, which may not be unique to the browsing-context.
This is done in https://tc39.es/ecma262/#sec-global-environment-records
A Global Environment Record is logically a single record but it is specified as a composite encapsulating an Object Environment Record and a Declarative Environment Record. The Object Environment Record has as its base object the global object of the associated Realm Record. This global object is the value returned by the Global Environment Record's GetThisBinding concrete method. The Object Environment Record component of a Global Environment Record contains the bindings for all built-in globals (clause 19) and all bindings introduced by a FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration, or VariableStatement contained in global code. The bindings for all other ECMAScript declarations in global code are contained in the Declarative Environment Record component of the Global Environment Record.
You can see an example where this is observable in this JSFiddle* where we store the built-in function eval (hereafter storedEval) originating from a same-origin <iframe>.
From the <iframe>'s context we declare a global variable window.foo = "first frame".
Calling storedEval("this.foo") from the parent document we get back the string "first frame". This means that our storedEval function correctly is bound with the <iframe>'s context.
Then we navigate the <iframe> to a new document. At this point, the global object has been replaced, this.foo is undefined in the new <iframe> context.
Now, if we call again storedEval("this.foo") from the parent document, we also get undefined. And if we then set window.foo in the new <iframe> document, we'd get that new value.
This is because the built-in eval is bound to the WindowProxy, and not to the global Window object. Failing to do so, we'd keep a reference of the previous Window, even after its document has been navigated away.
* The example is outsourced because StackSnippet's null-orgined iframes don't allow cross-access, even from srcdoc

Why `this` returns Empty object when Compiled on regular IDE(like visual studio code)?

In Browser window, when I log this in window context it gives me output: Window object.
But here, In normal IDE(like visual studio code) when I compile it, gives me an empty object. why? And How this happens?
console.log(this) // in browsers output: window
// In IDE, output: {}
function test(){
return this
}
console.log(test()) // output is global // Why not empty
Main question is why this return me an empty object, when I run on Normal IDE?Thanks for your answers.
this refres to global scope in console.log(this). In case of browser, it is window, in case of nodejs it is Global object. In case of vs code, they have empty object as global object as they can't afford to implement browser or nodejs global object apis and properties. As it is there for debugging, so empty global object suffices.
From MDN:
A global object is an object that always exists in the global scope.
In JavaScript, there's always a global object defined. In a web
browser, when scripts create global variables, they're created as
members of the global object. (In Node.js this is not the case.) The
global object's interface depends on the execution context in which
the script is running. For example:
In a web browser, any code which the script doesn't specifically start
up as a background task has a Window as its global object. This is the
vast majority of JavaScript code on the Web. Code running in a Worker
has a WorkerGlobalScope object as its global object. Scripts running
under Node.js have an object called global as their global object.
In window (browser) if you'll run:
console.log(this === window)
it will print true while if you'll run in node REPL:
this === global
it will return true

How does the 'window' object become the global object of a front end JS script?

Hello Stackoverflow community!
I kind of know what the window and global object is, but I would like to know how this works under the hood / behind the scene.
How does the browser add this window object as the global object to our script and why?
Thanks
Creation phaase a.k.a Global Execution Context.
When running code at the base level, JS engine will automatically do the following:
Create a global object, which means all your code will sit inside of this global object. If you are using in browser environment, this global object is window. It all depends on where do you execute your JS code.
Create a special variable called "this". At the global level, "this" would equal the Global (window) Object.
A reference to the outer environment if there is one. This means where something sits physically in the code you write and what's around it, a.k.a Lexical 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.

Why do I pass the window object in to the module pattern?

Here is a self executing anonymous method.
It seems to be good practice to pass in window as global. If window is available everywhere already why is this done?
(function (global) {
/* my code */
global["someName"] = someObject;
})(window);
It skips the code having to do a scope lookup since global is scoped inside the function.
Edit -- It's a performance optimization. Scoping in javascript is limited to function scope. global in this case is being defined within that scope, so when the code hits global[...] it looks at it's immediate scope (within the function) and finds global right away. Without that it would then have to move up to the closure scope, which in this case is the global javascript namespace, and search that entire scope for window.
The browser's JavaScript interpreter has to determine the scope of any variables it finds, starting at the most local scope and working its way outward. Using a function closure with window as the parameter global reduces the need to extend further up the scope chain to find window.
window is available everywhere, but using global the way it is in your example is more performant.

Categories

Resources