ES6 类 :内省呢?
ES6 classes : what about instrospection?
在 ES5 中,我可以检查 window 对象上是否存在 "class"(构造函数):
if (window.MyClass) {
... // do something
}
在 ES6 中,according to this article,全局声明的 类 是全局变量,但不是全局对象的属性(window
,在浏览器上):
But there are now also global variables that are not properties of the global object. In global scope, the following declarations create such variables:
let
declarations
const
declarations
- Class declarations
所以如果我不能使用 if (window.MyClass)
,有没有办法做到这一点?
实际上有没有不使用 window 对象的正确方法?
In ES5, we could wheck the existence of a class on the window object
只有构造函数是全局的,这是不好的做法。
In ES6, according to this article, globally-declared classes are globals, but not properties of the global object...
正确。 (全局范围内的 let
和 const
声明也是如此。)这在 §8.1.1.4: 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. This global object is the value returned by the global Environment Record’s GetThisBinding concrete method. (E.g., the global object referenced by window
on browsers — T.J.) The object Environment Record component of a global Environment Record contains the bindings for all built-in globals (clause 18) and all bindings introduced by a FunctionDeclaration, GeneratorDeclaration, 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.
(我的重点) 所以在 ES5 和更早的版本中,全局对象上的东西仍然存在(加上生成器,因为如果它们会更混乱没有),但是 new 东西(let
、const
和 class
声明)不。它们是全局变量,但不是全局对象的属性。
回到你的问题...
So if I can't use if (window.MyClass)
, is there a way to do the same?
你可以使用
if (typeof MyClass === "function") {
...因为无法解析的符号上的 typeof
不会抛出 ReferenceError
。这也有检查 MyClass
是否在代码范围内的优点,即使它 不是 全局的。
不过这里有一个陷阱:如果该代码与通过 class
(或 let
或 const
)声明 MyClass
的范围相同,但它是 above MyClass
在该范围内,即使 typeof
检查也会抛出 ReferenceError
,因为您无法访问它创建的绑定 在 class
(或 let
或 const
)之前 (甚至没有 typeof
)。
例如,这将抛出:
if (typeof MyClass === "function") { // ReferenceError here
// Yup, it's defined
// ...
}
// ...
class MyClass {
}
从范围开始到class
、let
或const
行的space称为时间死区 (TDZ) 并且您根本无法访问变量绑定。因此,您必须赶上 ReferenceError
:
let exists = false;
try {
exists = typeof MyClass === "function";
} catch (e) {
}
Actually is there a proper way to do this without using window object ?
在 JavaScript 模块获得广泛的浏览器支持之前,有两种方法:
使用某种异步模块定义库来处理加载模块。一些示例:RequireJS、SystemJS、CommonJS
有一个单一的全局变量,您将使用它来引用一个对象,并使您的各种应用程序成为该对象的全局属性。这是一个典型的方法:
var MyApp = MyApp || {};
if (!MyApp.ThisModule) { // You can leave this `if` out
// if there's no chance of the file
// being loaded more than once
MyApp.ThisModule = function(module) {
module.MyClass = class MyClass {
// ...class definition here...
}
}({});
}
这也为您提供了一个方便的作用域(匿名函数),可以在其中放置任何模块级全局变量。
在 ES5 中,我可以检查 window 对象上是否存在 "class"(构造函数):
if (window.MyClass) {
... // do something
}
在 ES6 中,according to this article,全局声明的 类 是全局变量,但不是全局对象的属性(window
,在浏览器上):
But there are now also global variables that are not properties of the global object. In global scope, the following declarations create such variables:
let
declarationsconst
declarations- Class declarations
所以如果我不能使用 if (window.MyClass)
,有没有办法做到这一点?
实际上有没有不使用 window 对象的正确方法?
In ES5, we could wheck the existence of a class on the window object
只有构造函数是全局的,这是不好的做法。
In ES6, according to this article, globally-declared classes are globals, but not properties of the global object...
正确。 (全局范围内的 let
和 const
声明也是如此。)这在 §8.1.1.4: 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. This global object is the value returned by the global Environment Record’s GetThisBinding concrete method. (E.g., the global object referenced by
window
on browsers — T.J.) The object Environment Record component of a global Environment Record contains the bindings for all built-in globals (clause 18) and all bindings introduced by a FunctionDeclaration, GeneratorDeclaration, 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.
(我的重点) 所以在 ES5 和更早的版本中,全局对象上的东西仍然存在(加上生成器,因为如果它们会更混乱没有),但是 new 东西(let
、const
和 class
声明)不。它们是全局变量,但不是全局对象的属性。
回到你的问题...
So if I can't use
if (window.MyClass)
, is there a way to do the same?
你可以使用
if (typeof MyClass === "function") {
...因为无法解析的符号上的 typeof
不会抛出 ReferenceError
。这也有检查 MyClass
是否在代码范围内的优点,即使它 不是 全局的。
不过这里有一个陷阱:如果该代码与通过 class
(或 let
或 const
)声明 MyClass
的范围相同,但它是 above MyClass
在该范围内,即使 typeof
检查也会抛出 ReferenceError
,因为您无法访问它创建的绑定 在 class
(或 let
或 const
)之前 (甚至没有 typeof
)。
例如,这将抛出:
if (typeof MyClass === "function") { // ReferenceError here
// Yup, it's defined
// ...
}
// ...
class MyClass {
}
从范围开始到class
、let
或const
行的space称为时间死区 (TDZ) 并且您根本无法访问变量绑定。因此,您必须赶上 ReferenceError
:
let exists = false;
try {
exists = typeof MyClass === "function";
} catch (e) {
}
Actually is there a proper way to do this without using window object ?
在 JavaScript 模块获得广泛的浏览器支持之前,有两种方法:
使用某种异步模块定义库来处理加载模块。一些示例:RequireJS、SystemJS、CommonJS
有一个单一的全局变量,您将使用它来引用一个对象,并使您的各种应用程序成为该对象的全局属性。这是一个典型的方法:
var MyApp = MyApp || {}; if (!MyApp.ThisModule) { // You can leave this `if` out // if there's no chance of the file // being loaded more than once MyApp.ThisModule = function(module) { module.MyClass = class MyClass { // ...class definition here... } }({}); }
这也为您提供了一个方便的作用域(匿名函数),可以在其中放置任何模块级全局变量。