-1

I have read lots of articles and would find it helpful to discuss the points I've listed here. If it's too long for one question I'll split them up and re-post but since they're related, and not long, I thought it'd make sense putting them into one.

1.

First task is to define what happens when something's in the global scope.
From this I gather when something's in the global scope, it can be accessed at any point in any .js file.

2.

Looking at this page

The term "global objects" (or standard built-in objects) here is not to be confused with the global object. Here, "global objects" refer to objects in the global scope.

I interpret that to mean built-in objects are in the global scope (as defined above).

The global object itself can be accessed using the this operator in the global scope. In fact, the global scope consists of the properties of the global object, including inherited properties, if any.

This last sentence almost threatened my understanding. Can I confirm the global scope doesn't consist entirely of the properties of the global object? Because the preceding paragraph said in-built objects were also in the global scope and they are not properties of the global object.

3.

Other objects in the global scope are either created by the user script or provided by the host application. The host objects available in browser contexts are documented in the API reference.

When I connect my .js file to my .html file it connects it to the DOM API which enables window (the global object) to be in the global scope. Is this the right way to phrase what is going on?

4.

MDN mentions global variables. MDN says, in browsers, all global variables are members of the global object. I thought a global variable was another word for a property of the global object (whether you're in a browser or node.js). Is what I'm thinking true?

  • This question is out of scope for Stack Overflow. Questions here should be more specific, for example about a problem you are having or an error you can't figure out. This question would probably be more suitable at https://softwareengineering.stackexchange.com/ I would suggest you re-post the question there. – Karl-Henry Martinsson Jul 30 '20 at 17:24
  • Thanks @Karl-HenryMartinsson for the suggestion. Am I good to just copy 'n' paste the question over there? – tonitone117 Jul 30 '20 at 17:28
  • *"Because the preceding paragraph said in-built objects were also in the global scope and they are not properties of the global object."* What specifically in the paragraph makes you think that it says that? (BTW, I disagree with Karl, but only slightly.) – T.J. Crowder Jul 30 '20 at 17:31
  • 1
    I see several references and links that seem to indicate some level of research. As to out of scope, I don't agree. Isn't Stackoverflow a place where beginning through advanced programmers welcome to post questions about most anything to do with program environments as well as actual programming? –  Jul 30 '20 at 17:38
  • I'm with you @HowardBrown, yes there are several questions, but they're all about the same fundamental thing, just different aspects of it. – T.J. Crowder Jul 30 '20 at 17:45
  • Global simply means that variable can be accessed from any part of your code. as opposed to local, which can only be accessed in the immediate parenthesis. – Rick Jul 30 '20 at 17:47

1 Answers1

1

JavaScript has multiple kinds of globals. There are at least:

  1. Globals that are inherited properties of the global object.
  2. Globals that are own properties of the global object; this includes the built-in globals.
  3. Globals that aren't properties of the global object.

(Those are in order, so if the same name is used at all three levels, the one you get when you use the identifier at global scope will be the one from #3.)

For example:

var theVar;
let theLet;

const hasOwn = Object.prototype.hasOwnProperty;

// On browsers, a global created because an element has an `id` (or in some cases
// `name`) is an inherited property of the global object (note that IE and Legacy
// Edge have older behavior)
console.log("theDiv:");
console.log("theDiv" in this);            // true
console.log(hasOwn.call(this, "theDiv")); // false

// `var` at global scope creates an "own" property of the global object
console.log("theVar:");
console.log("theVar" in this);            // true
console.log(hasOwn.call(this, "theVar")); // true

// `let`, `const`, and `class` declarations at global scope create globals that
// are not properties of the global object
console.log("theLet:");
console.log("theLet" in this);            // false
console.log(hasOwn.call(this, "theLet")); // false

// The built-in globals are own properties of the global object:
console.log("Array:");
console.log("Array" in this);             // true
console.log(hasOwn.call(this, "Array"));  // true
console.log("undefined:");
console.log("undefined" in this);             // true
console.log(hasOwn.call(this, "undefined"));  // true

// Here's an exmaple of the fact that when the same name is used at all levels,
// the inner most (`let` in this case) wins:
const div = document.createElement("div");
div.id = "example";
document.body.appendChild(div); // Inherited global because of `id`
this.example = "own example";   // Global that's an own property
let example = "let example";    // Global created via `let`

console.log("Priority:");
console.log(example === "let example"); // true, innermost wins
.as-console-wrapper {
    max-height: 100% !important;
}
<div id="theDiv"></div>
<div id="example"></div>

With the stage set...

I have read lots of articles and would find it helpful to discuss the points I've listed here. If it's too long for one question I'll split them up and re-post but since they're related, and not long, I thought it'd make sense putting them into one.

1.

First task is to define what happens when something's in the global scope.
From this I gather when something's in the global scope, it can be accessed at any point in any .js file.

Any JavaScript code running in the same realm, yes. Web workers are an example of JavaScript code related to your page but running in a separate realm. Similarly, the global environments of different tabs are in different realms, even when they can access each other (for instance, a parent window accessing a child window).

Looking at this page

The term "global objects" (or standard built-in objects) here is not to be confused with the global object. Here, "global objects" refer to objects in the global scope.

I interpret that to mean built-in objects are in the global scope (as defined above).

Yes. JavaScript's own globals are "own" properties of the global object. For example, you can see in the spec that the Array constructor is explicitly listed as being a property of the global object.

The global object itself can be accessed using the this operator in the global scope....

That's only mostly true. The host environment determines what this is at global scope. On browsers, it's a proxy for the global object rather than actually the global object itself (more in the HTML spec), but you mostly don't need to care about that.

...In fact, the global scope consists of the properties of the global object, including inherited properties, if any.

This last sentence almost threatened my understanding. Can I confirm the global scope doesn't consist entirely of the properties of the global object?

Correct, not only those properties. Those properties plus other things.

...Because the preceding paragraph said in-built objects were also in the global scope and they are not properties of the global object.

I don't see where the paragraph says they aren't properties of the global object.

Other objects in the global scope are either created by the user script or provided by the host application. The host objects available in browser contexts are documented in the API reference.

When I connect my .js file to my .html file it connects it to the DOM API which enables window (the global object) to be in the global scope. Is this true?

The browser determines what this is at global scope (it's that proxy for the global object), and also creates a property called window on the global object that matches what this is at global scope.

this mentions global variables. What are global variables? MDN says, in browsers, all global variables are members of the global object. I previously thought a global variable is just another word for a property of the global object (whether you're in a browser or node.js).

That used to be true, or at least mostly true (I wouldn't guarantee there weren't exceptions). It isn't anymore, as of ES2015, which introduced globals that are not connected to the global object (let, const, and class declarations at global scope).


In the comments the question of whether the global object inherits from a prototype comes up. The answer is: it depends on the host environment, but in the environments I've seen, absolutely, yes. In fact, there are often multiple layers. You can see that using Object.getPrototypeOf and Object.prototype.toString to see if they given special names in the toString tag:

const toString = Object.prototype.toString;
let obj = this;
let description = "global `this`";
while (obj) {
    console.log(`${description} (${toString.call(obj)})`);
    obj = Object.getPrototypeOf(obj);
    description = "prototype of " + description;
}

(Snippets are having trouble today; here's a fiddle: https://jsfiddle.net/tjcrowder/zm1fhsve/)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I have to disappear on you (I don't normally post-and-run), but I can answer any follow-up questions you have when I get back. – T.J. Crowder Jul 30 '20 at 17:43
  • 1
    Wow this looks like an amazing answer @T.J. Crowder I'll be looking over it now. And no problem – tonitone117 Jul 30 '20 at 17:50
  • The first thing I notice is you use the word global - not global properties/objects/variables - to mean anything that has global scope. Then there is just ‘the global object’. I also note your answer's for using JS when connected to a browser. Later I might post and confirm what I found for `node.js`. Just a few things I didn't get: @T.J. Crowder 1. What you were talking about when you say there’s a type of global that are inherited properties of the global object. What would be an example of this? 2. `console.log(“theDiv” in this); //true` Actually returns `false` for me. – tonitone117 Jul 30 '20 at 23:43
  • just tagging you because I don't think my first tag worked – tonitone117 Jul 31 '20 at 14:55
  • 1
    @tonitone117 - Doh! It did, and I started writing a reply, and got sidetracked by research... Will come back to you. – T.J. Crowder Jul 31 '20 at 14:56
  • 1
    @tonitone117 - The above isn't browser-specific. :-) I did use the browser as an example in a couple of places and addressed your browser-specific question in another. Most of this is in the JS spec. 1. One example is the example I gave above: A DOM element with an `id` is a property of an object that the global object inherits from (this has only fairly recently been nailed down; it reflects a near-consensus of what browser implementations do). 2. On what browser? I've looked at Chrome, Firefox, Legacy Edge, and IE, none of them return `false`. – T.J. Crowder Jul 31 '20 at 15:02
  • 1. That sounds so meta! So there is an object (constructor function?) that the global object inherits from. This object (call it globalParent) presumably has a `prototype` property. DOM elements with `id` attributes (which I think are objects? In any case let's call them elementWithId) automatically become globalParent.prototype.elementWithID? If what I said's roughly true, how can I test for this? 2. Unfortunately Chrome. Why would we be expecting a property of the global object called "the Div"? – tonitone117 Jul 31 '20 at 15:35
  • 1
    @tonitone117 - 1. Yes, there's an object (not a constructor function) that the global object inherits from; in fact, on modern browsers there are several layers. Remember that JavaScript's prototypical inheritance doesn't *require* constructor functions, you can create an object that uses another object as its prototype directly, without using a constructor function. 2. We aren't. We're expecting a property called `"theDiv"` (no space), because that's the `id` of the `div` in the document. – T.J. Crowder Jul 31 '20 at 16:56
  • Sorry I forgot to copy the HTML and CSS snippet. I now see that an element with an `id` attribute is saved as the value to a key which the content of the element's id attribute (as a string). Indeed this property is saved to the object that the global object inherits from. Thank-you! I don’t think I would’ve learned this from MDN but you say it’s covered in the ECMA Spec (and also reference the HTML spec). I’m a bit intimidated to read the spec but as my ability grows I might start reading the spec for things I already know about so I can get used to how the spec talks about things. – tonitone117 Jul 31 '20 at 18:56
  • One more thing about language. You start a sentence saying *`let`, `const`, and `class` declarations at global scope create globals*. What do you mean here by 'declarations at global scope'. We established when something is in the global scope it can be seen everywhere in its 'realm'. I'm a bit confused what it means to declare something 'at global scope'. I only understand how after you declare something it 'becomes in' or 'has' global scope – tonitone117 Jul 31 '20 at 19:00
  • @tonitone117 - *"`let`, `const`, and `class` declarations at global scope create globals"* means exactly that. :-) At global scope, `let x;`, `const y = 1;`, and `class Z {}` create globals. Unlike globals created by `var a;` or `function b() { }` at global scope, they aren't properties of the global object, but they're still globals. Code anywhere in the realm can access them by name. – T.J. Crowder Aug 01 '20 at 09:55
  • 1
    @tonitone117 - Re reading the specification, yeah, it's really ... fun. For instance, the spec uses `!` before some internal abstract operations, but it **doesn't** mean "not". That really tripped me up at first. This guide may help: https://timothygu.me/es-howto/ – T.J. Crowder Aug 01 '20 at 10:00
  • *let, const, and class declarations at global scope create globals* does 'at global scope' basically mean the 'highest' line of code. Not within a function or block or anything? I just found the language weird because I understood only 'globals' have global scope. So for something to be declared at global scope to then become a 'global' sounds weird to me. – tonitone117 Aug 01 '20 at 12:30
  • @tonitone117 - Yes, global scope is the scope (or in JavaScript's case, a couple of nested scopes) outside all other scopes. If a declaration is at the top level of the code and that code isn't in a module, it's a global declaration. (If the code *is* in a module, it isn't, it's just a module-level declaration.) – T.J. Crowder Aug 01 '20 at 12:36
  • Okay so for something to be declared at global scope really means declared at the top level of the code (presuming code isn't a module). And things declared there are accessible anywhere in the same realm. It's just that sometimes things declared become property of global object, sometimes they don't. And by definition, properties of the global object 'have' (are not 'declared at') global scope - that is to say, they can be accessed anywhere in the same realm. Hope I'm roughly right. – tonitone117 Aug 01 '20 at 12:51
  • @tonitone117 - That sounds good! About properties of the global object, *some* of them may be declared (using `var` or `function` at global scope), but as you say, some aren't declared at all (`window.example = 42;`), but they're still globals. – T.J. Crowder Aug 01 '20 at 12:56
  • Nice. I think the next thing I'd learn in this progression is what a module is. Hopefully this'll be good (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) Thanks for the help – tonitone117 Aug 01 '20 at 13:05
  • @tonitone117 - My pleasure! On modules and such, just FWIW I wrote a book about the new stuff in JavaScript in ES2015-ES2020, links in my profile. Chapter 13 goes into modules in detail. ;-) – T.J. Crowder Aug 01 '20 at 13:46