ES6课程:内省怎么样?

问题描述 投票:8回答:1

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

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

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

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

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

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

实际上有没有一个正确的方法来做到这一点,而不使用窗口对象?

javascript class ecmascript-6 introspection
1个回答
10
投票

在ES5中,我们可以在窗口对象上存在类

只有构造函数是全局的,这是不好的做法。

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

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

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

(我的重点)所以过去在ES5及更早版本中继续使用全局对象的东西(加上生成器,因为如果不这样做会更加令人困惑),但新东西(letconstclass声明)不。它们是全局变量,但不是全局对象的属性。

回到你的问题......

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

你可以用

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

...因为typeof在一个无法解决的符号上不会抛出ReferenceError。这也有一个好处,即检查MyClass是否在代码的范围内,即使它不是全局的。

虽然那里有一个问题:如果那个代码在MyClass通过class(或letconst)宣布MyClass的相同范围,但是在该范围内它高于typeof,即使是ReferenceError检查也会抛出typeof,因为你无法访问它在class(或letconst)之前完全创建(甚至不用if (typeof MyClass === "function") { // ReferenceError here // Yup, it's defined // ... } // ... class MyClass { } )。

例如,这将抛出:

class

从范围开始到letconstReferenceError线的空间称为时间死区(TDZ),您根本无法访问变量绑定。因此,你必须赶上let exists = false; try { exists = typeof MyClass === "function"; } catch (e) { }

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

实际上有没有一个正确的方法来做到这一点,而不使用窗口对象?

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

  1. 使用某种异步模块定义库来处理加载模块。一些例子:RequireJS,SystemJS,CommonJS
  2. 有一个全局变量,您将用它来引用一个对象,并使该对象的各种应用程序全局变量属性。这是一种典型的方法: qazxswpoi

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

© www.soinside.com 2019 - 2024. All rights reserved.