In ES5, we can overturn the existence of a class on a window object
Only if the constructor function is global, which is bad practice.
In ES6 , according to this article, globally declared classes are global, but not properties of a global object ...
Correctly. (The same goes for let and const declarations in the global scope.) This is defined in §8.1.1.4: Global environment reports :
A global environment record is logically a single record, but it is listed as a composite encapsulation of an Environment Record and a declarative environment record. The Environment Record object has as its base the global object of the associated Realm. This global object is the value returned by the specific Recordset GetThisBinding global record method. (For example, the global object referenced by window in browsers is - TJ) The write component of the object environment of the global environment record contains the bindings for all built-in global variables (Section 18) and all the bindings entered by FunctionDeclaration, GeneratorDeclaration or VariableStatement contained in the global code. Associations for all other ECMAScript declarations in the global code are contained in the declarative component of the environment record of the global environmental state record.
(My emphasis) So, everything that was previously done on a global object in ES5 and earlier (plus generators, because it would be even more confusing if they did not), but new things ( let , const and class ) are not . They are global, but not properties of a global object.
Back to your question ...
So, if I cannot use if (window.MyClass) , is there a way to do the same?
you can use
if (typeof MyClass === "function") {
... since typeof on an unsolvable character does not throw a ReferenceError . It also has the advantage of checking if MyClass code accessible, even if it is not global.
There is something like: if this code is in the same area where MyClass declared via class (or let or const ), but above MyClass in this area, even typeof check will throw a ReferenceError because you cannot access the binding , it creates at all (not even with typeof ) up to class (or let or const ).
For example, this will throw:
if (typeof MyClass === "function") { // ReferenceError here // Yup, it defined // ... } // ... class MyClass { }
The space from the beginning of the region to the class , let or const is called the temporary dead zone (TDZ), and you cannot access variable bindings at all. Therefore, you should catch a ReferenceError :
let exists = false; try { exists = typeof MyClass === "function"; } catch (e) { }
Is there really a way to do this without using a window object?
Until JavaScript modules become available for widespread browser support, there are several ways:
Use the asynchronous module definition library to control module loading. Some examples: RequireJS, SystemJS, CommonJS
Have the only global variable that you will use to refer to the object, and make your various global application properties of that object. Here's a typical way to do this:
var MyApp = MyApp || {}; if (!MyApp.ThisModule) { // You can leave this `if` out // if there no chance of the file // being loaded more than once MyApp.ThisModule = function(module) { module.MyClass = class MyClass { // ...class definition here... } }({}); }
It also gives you a convenient area (anonymous function) in which you can place any global global levels.