Window object properties behavior - javascript

When we have normal javascript objects, we can access there properties by using a syntax like objectName.proprtyName. If we just use propertyName only, then we will get an error as below -
const myObj = {
userIdName : "John"
};
console.log(myObj.userIdName); //John
console.log(userIdName); //error "Not defined"
However, in the case of in-built window object, we can use both window.propertyName and propertyName alone as below -
console.log(window.alert);
console.log(alert);
//both return same result
What exactly is responsible for this behavior of the window object? Can we replicate the same behavior for any explicitly built object like the object in the first snippet? (Although nobody would want to pollute the global scope, but I just have this query)
Edit - I have received comment that this question is a duplicate of another question. This question is very much similar to my answer except one difference - I am looking for a way to replicate the same globally accessible behavior of the window object.

What exactly is responsible for this behavior of the window object?
JavaScript has two major types of environment records (a construct to "hold" name -> value associations): a declarative record and an object record.
A declarative environment record stores those association in an implementation specific manner. This is the most common type of environment record and is created when you call a function for example.
An object environment record uses, as indicated by the name, an actual JavaScript object as the "backend". That means every entry in that environment becomes a property of that "binding object" and vice versa.
The global environment uses such an object environment and that binding object is available via window in browsers.
Can we replicate the same behavior for any explicitly built object like the object in the first snippet?
It is possible with the deprecated with statement still exists and creates an object environment record using the provided object as a binding object. From the spec:
The with statement adds an object Environment Record for a computed object to the lexical environment of the running execution context. It then executes a statement using this augmented lexical environment. Finally, it restores the original lexical environment.
var obj = {foo: 42};
with (obj) {
console.log(foo);
}

Related

why don't const and let statements get defined on the window object [duplicate]

This question already has answers here:
What is the difference between "let" and "var"?
(39 answers)
Closed 3 years ago.
Let's take the following code for example:
const constVar = 'some string';
let letVar = 'some string';
var varVar = 'some string';
(function() {
console.log(window.constVar); // prints undefined
console.log(window.letVar); // prints undefined
console.log(window.varVar); // prints 'some string'
})();
According to the description of the const statement by mdn:
This declaration creates a constant whose scope can be either global or local to the block in which it is declared.
And I assume let works in the same way.
In this case, the "block" is contained within the global scope. I guess the important distinction here is that while const constVar is "globally" accessible it still doesn't define it on the window object.
Which leads me to think that global scope and the window object are disparate. Which ultimately leads to 2 questions.
Why do variables declared using the var keyword get defined on window and variables declared with const and let not defined on window?
What is the difference between "global scope" and the window object provided to us by browsers.
1. Why do variables declared using the var keyword get defined on window and variables declared with const and let not defined on window?
Because the specification says so. If you are asking for the reason behind that decision, then you should reach out to the specification maintainers.
Classes do not become properties of the global object either btw.
2. What is the difference between "global scope" and the window object provided to us by browsers.
There are two types of base environment records according to the spec:
Declarative Environment Record
Object Environment Record
A Declarative Environment Record is basically your standard environment that you get when calling a function. All bindings (variables, constants, etc) are defined in some internal data structure that cannot be accessed from normal code.
An Object Environment Record on the other hand uses an actual JavaScript object to store bindings. This is used for example by the now deprecated with statement:
with({foo: 42}) {
console.log(foo);
}
Now, a Global Environment Record actually consists of two environment records: A declarative environment record and an object environment record. The object environment is backed by the global object, i.e. window and contains var declarations and other globals that the browser provides. The declarative environment contains the let, const, class, etc declarations.
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
This declaration creates a constant whose scope can be either global or local to the block in which it is declared.
Global constants do not become properties of the window object, unlike var variables. An initializer for a constant is required; that is, you must specify its value in the same statement in which it's declared (which makes sense, given that it can't be changed later).
To answer your 2nd question, global variable can be accessed through window object. However, there is an exception for const.

Are JavaScript execution contexts and JavaScript objects the same thing from a logical point of view?

My understanding of JavaScript is that on script execution a global execution context is created - what I understand to be a series of key:value pairs in reserved memory space - much like a regular JavaScript object.
On function execution, a new execution context is created with access to the 'parent' execution context. This seems (to me) at least to be the equivalent of re-initializing the JavaScript execution environment. Except that non of the key:value pairs initially set up in the global object need to be added to the new execution context since the child execution context has access to the parent's key:values pairs.
So for example:
function Y() {
this.prop = 4;
};
Y.prototype.doY = function() {
console.log(this.prop);
};
function X(){
this.prop = 5;
this.y = Object.create(Y.prototype);
Y.call(this.y);
};
// I can instantiate the object like so:
var x = new X();
// Which is equivalent to the following:
var x = Object.create(X.prototype);
X.call(x);
// Then I can add a function to the object that the X constructor points to via the X.prototype reference:
X.prototype.doX = function() {
console.log(this.prop)
};
// And then i can execute doX() in the context of the x object
x.doX(); // 5
x.y.doY(); // 4
On execution, doX function creates an execution context referenced from within the x object. The x object in turn is referenced within the global object.
Likewise, on execution the doY function creates an execution context that is referenced from within the x.y object.
It seems to me that an execution context as created by function execution is basically equivalent to a JavaScript object from a logical point of view:
Both allow for variable declaration NOT visible to parent objects/execution contexts
Both contain some kind of internal reference to parent object/execution context
It seems that both objects and execution context are just a list of key:values, the whole list being referenced by a single (ONLY a single) parent object (i.e. the y object exists as a reference within the x execution context) - or the global object as the root parent object (the x object exists as a reference within the global execution context).
So the question is: Is JavaScript execution context the same as a JavaScript object? If not, what is the difference?
This question: Are Execution Context and Variable Object actually same thing in JavaScript? mentions that in terms of implementation, that an execution context and an object are NOT the same thing.
Would it be correct to say that execution context inherits from Object? Or is implementation of objects/execution contexts completely non-related... One difference that I can see is that on creation, an execution context is 'processed' from top to bottom (lexically speaking) allowing an author to specify imperative commands - i.e. instruct the computer to do things. But in terms of architecture, this difference seems like an extension of the idea of an object rather than something completely different.
It seems to me that a 'running JavaScript environment' if such a thing exists, is basically a tree. The root node is the global execution context, and creating object adds nodes to the root node, or (as in the case of y above), adds nodes to the child nodes. Child nodes then reference parent nodes via a property to allow for scoping to parent execution context.
Then in terms of closures, which involve creation (and execution) of an execution context, on return the resultant object seems EXACTLY like a regular object since the 'execution context' as referenced by the closure will never again be executed (i.e. the same function, re-executed would create a new execution context and closure).
So from an "applied" point of view, is there ever a time that this -> i.e. a self reference to the current execution context, is NOT the same as the object from which a function call is made (aside from when using call, apply, or bind)? i.e. in the case of x.y.doY(), the function doY is called from the x.y object.
Execution contexts are conceptually objects, yes, as are several other things in the specification. That doesn't make them the "same" as JavaScript objects. They're a specification device and may not literally exist at runtime at all; code cannot directly reference them. For the full picture, read Executable Code and Execution Contexts in the spec.
Is JavaScript execution context the same as a JavaScript object?
No. A JavaScript object can be directly referenced by code, has a prototype, and has specific behaviors described for it which are not described for execution contexts, etc.
Would it be correct to say that execution context inherits from Object?
No, nothing in the spec suggests that to be the case.
It seems to me that a 'running JavaScript environment' if such a thing exists, is basically a tree.
Sort of, fairly indirectly. The spec doesn't describe any link from an execution context to its parent or child contexts. Instead, the lexical environment objects which are part of the context's state (specifically the LexicalEnvironment and VariableEnvironment state components) have a link to their parent lexical environment for the purposes of binding resolution. (The parent lexenv doesn't have a link to its children in the spec.) But they, too, are purely a specification device which may not literally exist at runtime and cannot be directly referenced by code.
So it's absolutely correct to think of them as objects, that's how the spec describes them, but they aren't JavaScript objects in the way that term is normally understood — something code can directly reference and act upon.
No, they are not the same thing. Not at all.
First, you seem to be confusing execution contexts with environment records. The former are basically call stack frames, the latter ones store variable values and form a tree as you described. Let's talk about environment records.
Environment records feature a key-value mapping and a link to their parent environment. In that regard, they are similar to a JS object with its properties and prototype link indeed. In fact, in a with statement or the global scope a so called object environment record is backed by an actual JS object.
However, they are still very different. Most environment records are declarative, that means their shape is determined before they are used. They are like an object that is not extensible. Also they cannot have getter/setter properties. And they differ in many more minor details.
But most importantly, environment records are just specification type values. They "are specification artefacts that do not necessarily correspond to any specific entity within an ECMAScript implementation. Specification type values may be used to describe intermediate results of ECMAScript expression evaluation but such values cannot be stored as properties of objects or values of ECMAScript language variables." So no, they do not inherit from Object at all.
Your question seems to ask: what can execution contexts record do that cannot be recorded in javascript objects?
You've got well documented answers already. So my contribution will be practical examples.
How would you manage the following 2 examples from a key/value perspective:
// Execution context of anonymous functions
(function (x) {
var y = x+1;
console.log(y);
}) (1);
// Life cycle of objects versus reference
var x = {a:1};
var y = x;
x = {b:1};
console.log(y);
If you start inventing keys that are not in the code, you should realize that this approach is limited. And so, not working if you push beyond the limits.

What does the window object contain?

I was exploring the this keyword in the global scope, and discovered that this in that context refers to the window.
I logged the value of this to the console, and saw a huge list shown in the image below.
What does the list I'm seeing contain, and how is it populated?
First, a brief definition for readers of what a lexical environment is, as well as how it relates to the global environment, and in turn how the global environment relates to the global object.
A lexical environment consists of:
an environment record, which stores the identifier bindings created within the scope of the environment,
a reference to an outer environment, and
references to any environments contained within.
Lexical environments inherit variable definitions declared in the environments they are contained within, and are created each time a function declaration, a block statement, or a catch clause of a try statement is evaluated. Variable definitions are not accessible outside the lexical environment they were defined in.
The following example:
defines a global variable using a var declaration, initialized to a function expression, which creates a new lexical environment,
defines a variable in the new environment, again using a var declaration, this time initialized to a string value, and
demonstrates that the variable is not accessible outside of the environment it is defined in:
var hello = function() {
var world = "fubar";
console.log(world); // "fubar";
}
console.log(world); // ReferenceError: world is not defined
The global environment is a lexical environment whose outer environment reference is null, and which includes an associated global object whose properties provide some of the global environment's identifier bindings, specifically excluding variables defined using let or const declarations, as well as other possible exclusions.
var hello = "world";
console.log(hello, window.hello); // "world", "world"
let foo = "bar";
console.log(foo, window.foo) // "bar", undefined
Now, to answer your question in context:
What does the list I'm seeing contain, and how is it populated?
The list you are seeing contains the properties of the global object, which consists of:
prepopulated identifier bindings supplied by the browser - some of which are standard, others are specific to the JavaScript engine or browser implementation -
global variables set by scripts running on the current page, or
global variables set by browser extensions you may have installed.
The information contained in this answer should conform to the ECMAScript 2015 Language Specification, which also contains definitions for most of the terms used here, and I strongly encourage you to skim over that document any time you're in the mood for some light reading.
If you find a discrepancy between this answer and the ECMAScript Language Specification, please feel free to edit this answer to conform.
These are all the functions that are part of the window object.
Think of it this way. All functions are part of an object. 'this' in running code returns the object context that the function is running in. It may be the object that the function was defined under, but 'this' can be dynamically changed in code, so more accurately its the object context that the function is running in.
window is the global object in a browser, so when you're not inside a function that is part of a sub-object to window, you are in the window object context.
for instance,
var o = { test: function(){ alert(this) } }
o.test();
will alert the o object, not window.
You can call functions directly that are in the same context, which is why you can type Infinity in the console, and it returns Infinity which is part of window.
JavaScript will also look up parent objects (window in this case) to the declared object as well, so in your browser console, this works:
var o = { test: function(){ alert(Infinity) } }
o.test();

A javascript 'let' global variable is not a property of 'window' unlike a global 'var' [duplicate]

This question already has answers here:
Do let statements create properties on the global object?
(5 answers)
Closed 6 years ago.
I used to check if a global var has been defined with:
if (window['myvar']==null) ...
or
if (window.myvar==null) ...
It works with var myvar
Now that I am trying to switch to let, this does not work anymore.
var myvar='a';
console.log(window.myvar); // gives me a
let mylet='b';
console.log(window.mylet); // gives me undefined
Question:
With a global let, is there any place I can look if something has been defined like I could with var from the window object?
More generally:
Is var myvar='a' equivalent to window.myvar='a'?
I hear people say that at the global level, let and var are/behave the same, but this is not what I am seeing.
I hear people say that at the global level, let and var are/behave the
same, but this is not what I am seeing.
Eh, yes and no. To answer your question, in the large majority of cases let and var are the same when declared globally, but there are some differences.
To explain: A global environment record is where JS keeps all the logic and memory values for the code in play. However, this global environment record is really a composite encapsulating an object environment record and a declarative environment record.
Some more explanation:
A declarative environment record stores the bindings in an internal data structure. It's impossible to get a hold of that data structure in any way (think about function scope).
An object environment record uses an actual JS object as data structure. Every property of the object becomes a binding and vice versa. The global environment has an object environment record whose "binding object" is the global object. This would be the Realm, which in most cases is the window object.
So, per the ECMA spec, only FunctionDeclarations, GeneratorDeclarations, and VariableStatements create bindings in the global environment's object environment record.
All other declarations (i.e const and let) are stored in the global environment's declarative environment record, which is not based on the global object. They still declare a variable, but are not a VariableStatement.
TL;DR: Both are still global, but vars are stored in the window object, while lets are stored in a declarative environment that you can't see (just like you can't access a variable in a function scope from outside of the function). When declared globally, both statements are pretty much identical in use.

What really is a declarative environment record and how does it differ from an activation object?

Okay, so I lately have been reading about ES-5 lexical environment scope and I am not sure if I really understand what is going on with how variables are stored in EcmaScript. I did some research but it didn't clarified my information, only brought me up to two questions. So there they are:
The first one is about ES-3 activations objects/variable objects. After reading ES-3 Specification and some sources on the Internet I can assume that they are just normal object, for example like those created by new Object, but none of the sources says "yes, this is just a plain object" directly. Moreover, Dmitry Soshnikov wrote on his blog (the emphasis is mine):
Schematically and for examples, it is possible to present variable object as a normal ECMAScript object
and that quotation doesn't let me be sure about what really an activation object is. So this is the first question: is an activation object a regular EcmaScript object? If not, then what is it otherwise?
In ES-5 we now have object environment records, which seem to be more or less the same that ES-3 activation objects, and declarative environment records, which replaced activation objects in functions and try-catch statement. So, assuming that object environment records are just plain EcmaScript objects, then what is a declarative environment record? The specification doesn't clarify this, furthermore, from what I've read there I cannot imagine that this is not implemented as an object. So, again, if declarative environment records are not ES objects, then what are they and how are they implemented and represented during the code execution?
Thank you very much in advance for brightening that topic for me.
EDIT: I think I need to clarify what is this question about. The main thing that I want to know is what is the exact difference between activation objects/object environment records and declarative environment records. That's what I'm interested in most.
First of all you have to be aware that all of these terms just describe concepts. They don't dictate any kind of implementation. But because this can be hard to imagine/visualize it can be helpful to think about these concepts as instantiations of something you know, like maps or tables.
Declarative environment records (DER) and object environment records (OER) have one thing in common: They are both environment records (ER), which are defined in the specification as:
An Environment Record records the identifier bindings that are created within the scope of its associated Lexical Environment.
This basically means that an ER keeps track of variable and function names and their associated values.
Consider this example:
var foo = 42;
function bar() { };
The corresponding ER would have two entries, one for foo and one for bar. If you imagine an ER to be a table, then it would look like
name value
----------------------
foo 42
bar <function object>
Now on to the difference between DER and OER. A DER might be the easiest to understand.
Declarative Environment Record
The term declarative should sound familiar since we are often talking of variable declarations and function declarations. The specification says:
Each declarative environment record is associated with an ECMAScript program scope containing variable and/or function declarations. A declarative environment record binds the set of identifiers defined by the declarations contained within its scope.
So, when you see
var foo = 42;
or
function bar() {
}
then you can assume that their names and values are stored in a DER.
Object Environment Record
OERs are less common, but in each JS application there exist at least one OER. The specification describes it as
Each object environment record is associated with an object called its binding object. An object environment record binds the set of identifier names that directly correspond to the property names of its binding object.
Have you ever wondered why the properties of the window object are global variables? That's because the ER of the global scope is an OER: window is the binding object and for each of its properties a corresponding entry is created in the OER. This is also in the specification:
The global environment’s Environment Record is an object environment record whose binding object is the global object.
Here is an example: Lets assume out binding object is
var obj = {
answer: 42
};
then the OER would be
name value
------------------------
answer 42
Note that in this case, the binding object (obj) is really a JavaScript object. You are in the same situation when you are using the with statement:
var obj = { foo: 42; };
with (obj) {
foo = foo / 2;
}
console.log(obj);
with creates a OER and populates it with the property names and values from the passed object. That's why you can access them without explicitly referring to them via obj.*. The OER also makes sure to update the binding object with the new value if one was assigned to one of the identifiers.
Activation Object
It looks like that in ES3, activation objects (AO) where automatically created when a function was executed and it was holding a reference to the special arguments object. This seems to be related to DERs, but still to be something independent.
The concept of AOs doesn't seem to exist anymore in ES5 and I assume that it was unnecessary, since arguments can be added directly to the DER of the execution context.
Execution Context
A new execution context (EC) is established whenever a function is executed and is used to keep track of the state of the execution:
An execution context contains whatever state is necessary to track the execution progress of its associated code.
This means the engine can add whatever information it needs to track the execution progress. But the specification also defines components that an EC must have, one of which is the VariableEnvironment, which is an ER (probably always a DER, but I don't know for sure). That means an ER is a part of an EC.

Categories

Resources