【问题标题】:ES6 classes : what about instrospection?ES6 类:内省呢?
【发布时间】:2015-07-31 01:05:51
【问题描述】:

在 ES5 中,我可以检查窗口对象上是否存在“类”(构造函数):

if (window.MyClass) {
... // do something
}

在 ES6 according to this article 中,全局声明的类是全局的,但不是全局对象的属性(window,在浏览器上):

但现在也有一些不是全局对象属性的全局变量。在全局范围内,以下声明会创建此类变量:

  • let 声明
  • const 声明
  • 类声明

如果我不能使用if (window.MyClass),有没有办法做同样的事情?

实际上有没有不使用窗口对象的正确方法?

【问题讨论】:

  • “意思是它们在window全局范围内是不可访问的”...提升和全局范围有什么关系?
  • 感谢您的回答。确实,很抱歉造成混乱,吊装没什么可看的。无论如何,你有什么建议来检查班级的存在吗? es6 模块可能吗?
  • 检查声明类的根模块是否声明了?
  • 嗨,我正在考虑以模块的形式组织我的工作。如果我在模块中导出一些类。如果该类存在,我可以检查该模块吗? (只是一个 eda)
  • 好问题。今天在尝试将使用伪类的项目重构为新的 ES6 类时遇到了这个问题。打破了我的 window[className] 调用(需要这个,因为我正在使用 jquery 从输入按钮中提取类名)。

标签: javascript class ecmascript-6 introspection


【解决方案1】:

在 ES5 中,我们可以判断窗口对象上是否存在类

仅当构造函数是全局的,这是不好的做法。

在 ES6 according to this article 中,全局声明的类是全局的,但不是全局对象的属性...

正确。 (letconst 在全局范围内的声明也是如此。)这是在 §8.1.1.4: Global Environment Records 中定义的:

全局环境记录在逻辑上是单个记录,但它被指定为封装对象环境记录和声明性环境记录的组合。对象环境记录具有关联领域的全局对象作为其基础对象。这个全局对象是全局环境记录的 GetThisBinding 具体方法返回的值。 (例如,window 在浏览器上引用的全局对象——TJ) 全局环境记录的对象环境记录组件包含所有内置全局变量的绑定(第 18 条)和由包含在全局代码中的 FunctionDeclarationGeneratorDeclarationVariableStatement 引入的所有绑定。全局代码中所有其他 ECMAScript 声明的绑定都包含在全局环境记录的声明性环境记录组件中。

(我的重点) 所以在 ES5 和更早的版本中用于全局对象的东西仍然可以(加上生成器,因为如果不这样做会更加混乱),但是 事物(letconstclass 声明)不要。它们是全局变量,但不是全局对象的属性。

回到你的问题...

如果我不能使用if (window.MyClass),有没有办法做同样的事情?

你可以使用

if (typeof MyClass === "function") {

...因为typeof 在无法解析的符号上不会抛出ReferenceError。这还具有检查MyClass 是否在代码范围内的优点,即使它不是全局的。

这里有一个问题:如果该代码在通过 class(或 letconst)声明 MyClass 的同一范围内,但它在 上方 MyClass在该范围内,即使typeof 检查也会抛出ReferenceError,因为在class (或letconst)。

例如,这会抛出:

if (typeof MyClass === "function") {  // ReferenceError here
    // Yup, it's defined
    // ...
}
// ...
class MyClass {
}

从作用域开始到classletconst 行之间的空间称为时间死区 (TDZ),您无法访问该变量完全有约束力。因此,您必须赶上ReferenceError

let exists = false;
try {
    exists = typeof MyClass === "function";
} catch (e) {
}

实际上有没有不使用窗口对象的正确方法?

在 JavaScript 模块获得广泛的浏览器支持之前,有几种方法:

  1. 使用某种异步模块定义库来处理模块的加载。一些例子:RequireJS、SystemJS、CommonJS

  2. 有一个全局变量,您将使用它来引用一个对象,并使您的各种应用程序全局属性成为该对象。这是一种典型的方法:

    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...
            }
        }({});
    }
    

这也为您提供了一个方便的范围(匿名函数),可以在其中放置任何模块级全局变量。

【讨论】:

    猜你喜欢
    • 2018-11-24
    • 1970-01-01
    • 2014-07-25
    • 2023-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    相关资源
    最近更新 更多