简体   繁体   English

在窗口全局中无法访问 Javascript ES6 类定义

[英]Javascript ES6 class definition not accessible in window global

I have come across an interesting issue, at least I think it's interesting, and a little annoying.我遇到了一个有趣的问题,至少我认为它很有趣,而且有点烦人。 I have a class, for this question I will keep it extremely simple...我有一堂课,对于这个问题,我会保持非常简单......

class Foo {
    static pageChange() {
        console.log('The page changed');
    }
}

Now, I can access that with Foo.pageChange() no problem, everything works as expected.现在,我可以使用 Foo.pageChange() 访问它,没问题,一切都按预期工作。 The hard part, and interesting bit comes in when I try to access this dynamically.当我尝试动态访问它时,困难的部分和有趣的部分就出现了。 I have a separate object that monitors events and handles dispatching them as needed.我有一个单独的对象来监视事件并根据需要处理它们的调度。 This pertains to the Google visualization library, where I have a table, and the table has events tied to it.这与 Google 可视化库有关,我在其中有一个表格,并且该表格有与之相关的事件。 I have an object that is responsible for creating all of this from PHP output.我有一个对象负责从 PHP 输出创建所有这些。 It is one heck of a system, in an easy explanation you can do something like this in PHP...这是一个系统,简单地说,你可以在 PHP 中做这样的事情......

GoogleVisLibrary::renderChart(
    array(
        'chartType' => 'table',
        'chartData' => $this->chartData,
        'chartOptions' => $this-chartOptions,
        'events' => array(
             'sort' => 'Foo.pageChange'
        )
);

now that will create teh table and all that good stuff.现在这将创建桌子和所有这些好东西。 The problem is accessing that static method in the Foo class in javascript.问题是在javascript中访问Foo类中的那个静态方法。 What I had prior to creating the Foo as a class was this.在将 Foo 创建为一个类之前,我所拥有的就是这个。

var Foo = {
    pageChange: function() {
         console.log('page changed');
    }
}

then in my event library handler thingy it would look something like this..然后在我的事件库处理程序中,它看起来像这样..

for(var i = 0, l = events.length; i < l; i++) {
    window[events.className][events.fnName].apply();
}

and that would work fine because Foo can be accessed through window['Foo'] but when you use the class definition shown in the first code snippet, you can no longer access it from the window super global, it just outputs 'undefined'.这可以正常工作,因为 Foo 可以通过 window['Foo'] 访问,但是当您使用第一个代码片段中显示的类定义时,您不能再从窗口超级全局访问它,它只会输出“未定义”。

So, is there any way to access a static method in a class, through a dynamic reference like you can with the Foo object through the window global?那么,有什么方法可以通过动态引用访问类中的静态方法,就像您可以通过全局窗口使用 Foo 对象一样?

I am hoping that makes sense and I am explaining it correctly.我希望这是有道理的,我正在正确地解释它。 If anyhting doesn't make sense please feel free to ask, I will try to explain better.如果anyhting没有意义,请随时询问,我会尽力解释得更好。 Thank you in advance for any help you can give.提前感谢您提供的任何帮助。

To get a reference on the window object, you'll need to do that explicitly:要获取window对象的引用,您需要明确地执行此操作:

window.Foo = class Foo { ... }

Read more about classes not being properties of the window object in this answer , which also quotes the ECMA2015 Specification, Section 8.1.1.4: Global Environment Records :此答案中阅读有关不是window对象属性的类的更多信息,该答案还引用了ECMA2015 规范,第 8.1.1.4 节:全局环境记录

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.这个全局对象是全局环境记录的 GetThisBinding 具体方法返回的值。 (Eg, the global object referenced by window on browsers — TJ) 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. (例如,浏览器上的window引用的全局对象 - TJ)全局环境记录的对象环境记录组件包含所有内置全局变量的绑定(第 18 条)以及由FunctionDeclarationGeneratorDeclarationVariableStatement引入的所有绑定在全球代码中。 The bindings for all other ECMAScript declarations in global code are contained in the declarative Environment Record component of the global Environment Record.全局代码中所有其他 ECMAScript 声明的绑定包含在全局环境记录的声明性环境记录组件中。

Using a dedicated object使用专用对象

It would be better not to use the global object for this, and dedicate a specific object to contain your classes and base your event managing library on that object, as illustrated in this simplified snippet:最好不要为此使用全局对象,而是使用一个特定的对象来包含您的类并将您的事件管理库基于该对象,如下面的简化片段所示:

 (function () { var classes = { Foo: class Foo { static pageChange() { console.log('The page changed'); } } } ///////////// var events = [{ className: 'Foo', fnName: 'pageChange' }]; for(var event of events) { classes[event.className][event.fnName].apply(); } }());

I got the same problem myself for quite a while, and I finally discovered a very simple solution : using eval .我自己也遇到了同样的问题很长一段时间,我终于找到了一个非常简单的解决方案:使用eval

Create your class :创建您的课程:

class Foo {
  static pageChange() {...}
}

Get it dynamically :动态获取:

eval('Foo');   // return the Foo constructor
eval('Foo').pageChange;   // return the pageChange static method
eval('Foo')['pageChange'];  // same

I dislike eval , but in this case it is as simple as fast.我不喜欢eval ,但在这种情况下,它非常简单。 And it's the only way I found without adding the class to window .这是我发现没有将类添加到window的唯一方法。

(I also tried (new Function("return Foo;"))() and it appears eval is 2-3 times faster) (我也尝试过(new Function("return Foo;"))()看起来eval快了 2-3 倍)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM