在全局窗口

时间:2016-06-08 19:46:47

标签: javascript class ecmascript-6

我遇到了一个有趣的问题,至少我觉得它很有趣,而且有点烦人。我有一节课,对于这个问题,我会非常简单......

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

现在,我可以通过Foo.pageChange()访问它没问题,一切都按预期工作。当我尝试动态访问它时,困难的部分和有趣的位进来。 我有一个单独的对象监视事件并处理根据需要调度它们。这与Google可视化库有关,我在其中有一个表,并且表中包含与之关联的事件。我有一个对象负责从PHP输出创建所有这些。它只是一个系统,简单的解释你可以在PHP中做这样的事情......

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

现在,这将创建表和所有好东西。问题是在javascript中访问Foo类中的静态方法。在创建Foo之前​​我所拥有的就是这个。

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

然后在我的事件库处理程序中,它看起来像这样..

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

这样可以正常工作,因为可以通过窗口['Foo']访问Foo 但是当你使用第一个代码片段中显示的类定义时,你不能再从超级全局窗口访问它,它只输出'undefined'。

那么,有没有办法通过动态引用来访问类中的静态方法,就像通过全局窗口使用Foo对象一样?

我希望这是有道理的,我正在解释它。如果没有任何意义,请随意提问,我会尽力解释。提前感谢您提供任何帮助。

2 个答案:

答案 0 :(得分:14)

要获得window对象的引用,您需要明确地执行此操作:

window.Foo = class Foo { ... }

this answer中详细了解不属于window对象属性的类,其中也引用了ECMA2015 Specification, Section 8.1.1.4: Global Environment Records

  

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

使用专用对象

最好不要为此使用全局对象,并将特定对象专用于包含您的类并将事件管理库基于该对象,如此简化代码段所示:

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

答案 1 :(得分:2)

我自己也遇到了同样的问题,我终于找到了一个非常简单的解决方案:使用eval

创建你的课程:

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

动态获取:

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

我不喜欢eval,但在这种情况下,它就像快速一样简单。这是我在没有将课程添加到window的情况下找到的唯一方法。

(我也尝过(new Function("return Foo;"))(),看起来eval快了2-3倍)