ES6类:什么是instrospection? [英] ES6 classes : what about instrospection?

查看:221
本文介绍了ES6类:什么是instrospection?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

在ES6中,根据本文,全局声明的类是全局变量,而不是全局对象的属性( window ,在浏览器上):

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 li>
  • 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 c>也是如此。)这在§8.1.1.4:全球环境记录: / p>

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


全局环境记录在逻辑上是单个记录,但它被指定为封装对象Environment Record和声明性环境记录的组合。对象Environment Record具有作为其基本对象的相关领域的全局对象。这个全局对象是由全局环境记录的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 code>声明)不要

(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.

有一个getcha有:如果该代码在同一范围内 MyClass 通过类声明(或 let const ),但它在 MyClass ,即使 typeof 检查也会抛出 ReferenceError 无法访问 typeof

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).

例如,这将抛出:

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类:什么是instrospection?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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