ES6课程:如何反思? [英] ES6 classes : what about instrospection?

查看:123
本文介绍了ES6课程:如何反思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In ES5, I could check the existence of a "class" (constructor function) on the window object:

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

在ES6中,根据这篇文章,全球声明的类是全局变量,而不是浏览器上的全局对象(窗口)的属性:

In ES6, according to this article, globally-declared classes are globals, but not properties of the global object (window, on browsers):


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

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 声明

  • const 声明

  • 类声明

  • let declarations
  • const declarations
  • Class declarations

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

So if I can't use if (window.MyClass), is there a way to do the same?

在没有使用窗口对象的情况下,是否有正确的方法?

Actually is there a proper way to do this without using window object ?

推荐答案


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

In ES5, we could wheck the existence of a class on the window object



Only if the constructor function was a global, which is poor practice.


在ES6中,根据本文,全局声明的类是全局变量,而不是全局对象的属性...

In ES6, according to this article, globally-declared classes are globals, but not properties of the global object...

正确。 (在全局范围内, let const 声明也是如此。)这是在§8.1.1.4:全球环境记录

Correct. (The same is true of let and const declarations at global scope.) This is defined in §8.1.1.4: Global Environment Records:


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

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和更早版本中继续使用全局对象的东西依然会做(加上发生器,因为如果没有这样的话,会更混乱),但是新的东西( let const class 声明)不要。它们是全局变量,而不是全局对象的属性。

(My emphasis) So the things that used to go on the global object in ES5 and earlier still do (plus generators, because it would have been even more confusing if they didn't), but the new things (let, const, and class declarations) don't. They're globals, but not properties of the global object.

回到您的问题...


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

So if I can't use if (window.MyClass), is there a way to do the same?

您可以使用

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

...自 typeof 在一个不可解析的符号上不会引用 ReferenceError 。这也具有检查 MyClass 是否在代码范围内的优点,即使它不是全局。

...since typeof on an unresolvable symbol doesn't throw a ReferenceError. This also has the advantage of checking whether MyClass is in scope for the code, even if it's not global.

那里有一个问题:如果该代码在相同的范围内, MyClass 通过 class (或 let const ),但它 MyClass 在该范围内,即使是 typeof check将会引用一个 ReferenceError ,因为你在 (甚至不使用 typeof ) c>(或 let const )。

There's a gotcha there though: If that code is in the same scope where MyClass is declared via class (or let or const) but it's above MyClass in that scope, even the typeof check will throw a ReferenceError, because you can't access the binding it creates at all (not even with typeof) before the class (or let or const).

例如,这将抛出:

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

从范围开始到类的空格 let const 行被称为时间死区(TMZ),您根本无法访问变量绑定。因此,您必须抓住 ReferenceError

The space from the beginning of the scope to the class, let, or const line is called the temporal dead zone (TMZ) and you can't access the variable binding at all. Consequently, you have to catch the 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模块使其成为广泛的浏览器支持,有几种方法:

Until JavaScript modules make it to broad browser support, there are a couple of ways:


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

  1. Use an Asynchronous Module Definition library of some kind to handle loading your modules. Some examples: RequireJS, SystemJS, CommonJS

有一个全局变量,您将用于引用对象,并使您的各种应用程序全局变量属性那个对象。这是一个典型的方法:

Have a single global variable that you'll use to refer to an object, and make your various application globals properties of that object. Here's a typical way to do that:

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


这也给你一个方便的范围(匿名函数),其中放置任何模块级全局变量。

This also gives you a handy scope (the anonymous function) in which to put any module-level globals.

这篇关于ES6课程:如何反思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆