2

I know this must be really basic stuff but I don’t understand how the scope is working. I want the closed variable be known in the entire JavaScript file.

I have something like that (in jQuery):

var closed = 0;

$(function(){
  console.log(closed);
});

But closed is getting logged as false. I tried many things with load and onload functions, but I failed.

Sebastian Simon
  • 14,320
  • 6
  • 42
  • 61

2 Answers2

2

var closed = 0; in the global scope doesn’t create a number and remains being the boolean false.

The reason for this is that closed refers to window.closed in this circumstance; it’s always a boolean, and redefining it produces a linter warning like “Redefinition of closed.

This read-only property indicates whether the referenced window is closed or not.


Variables that behave like this can be found in these lists:

Run the snippet to get a full list of variable names that you can’t safely use in the global scope:

const props = Object.entries(Object.getOwnPropertyDescriptors(window)),
  undesirable = {
    set: (desc) => desc,
    configurable: (desc) => !desc,
    writable: (desc) => !desc
  };

Array.from(document.querySelectorAll("[id]"))
  .forEach((span) => span.innerHTML = props
    .filter(([prop, {[span.id]: desc}]) => undesirable[span.id](desc))
    .map(([prop]) => `<code>${prop}</code>`)
    .join(", "))
code{
  background: #eee;
  padding: 1px 3px;
}
<p>Properties that have a setter which may change the type or invoke some action, when a value is set to it:</p>
<span id="set"></span>

<hr/>

<p>Properties that are not configurable:</p>
<span id="configurable"></span>

<hr/>

<p>Properties that are read-only:</p>
<span id="writable"></span>

You’ll notice, it’s a lot. It’s also a lot of short, common variable names like name, length [1], [2], status [1], [2], self, top, menubar, and parent. Furthermore, regarding the invocation of some action when assigning to a setter, something like var location = "Podunk, USA"; actually redirects you to the location ./Podunk, USA.

There’s a related issue of using function names like lang, checked, autocomplete or animate in event attributes like onclick: there, not only the window properties are included in the scope chain, but also all scopable properties of the entire prototype chain of the current HTMLDocument and of the current specific Element (e.g. using <a onclick=""></a> provides access to everything starting at HTMLAnchorElement.prototype).

All this is also explained in this answer to a related question.


Moral of the story: avoid global variables like these. They’ll just clash with other global properties. Always use scoped variables, such as in IIFEs:

(function(){
  const closed = 0; // or `let` or `var`

  $(function(){
    console.log(closed);
  });
})();

Just using const or let in global scope instead of var, as Ankit Agarwal’s answer suggests, works for most variable names, but not all — const closed = 123; let history = "Hello, world!"; all work, but const window = 123;, const top = 123; or let document; don’t.

Since I don’t use jQuery for most of my code, I prefer to wrap everything in a DOMContentLoaded listener where I can scope all the variables I need, and, in addition, use "use strict";:

// My personal boiler-plate:

addEventListener("DOMContentLoaded", function(){ "use strict";
  // Code goes here.
});
Sebastian Simon
  • 14,320
  • 6
  • 42
  • 61
  • I currently don’t understand why (at least) `window`, `top` and `document` behave differently from all other properties when `const` or `let` is used in global scope. Maybe I or someone else can figure this out and refine the explanations given in this answer. – Sebastian Simon Apr 06 '20 at 19:10
0

Use let instead of var as closed is a global variable used by JavaScript runtime so to make it local to the scope of the code you can use let instead of var which set the variable to global scope considering the global closed property.

let closed=0;
$( function() {
    console.log(closed);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Ankit Agarwal
  • 28,439
  • 5
  • 29
  • 55
  • Exactly what I needed Thanks. –  Jun 27 '18 at 12:24
  • 1
    @MinirockAkeru This answer didn’t explain _why_ you get `false` though. Not all variables behave like this. – Sebastian Simon Jun 27 '18 at 12:34
  • This doesn’t even work in most cases. It works for `closed`, but wouldn’t work for `top`, even if they’re both non-writable, configurable, enumerable, non-setter getters on `window`. – Sebastian Simon Apr 06 '20 at 18:41