Javascript ES6 类定义在窗口全局中不可访问

IT技术 javascript class ecmascript-6
2021-02-03 17:47:08

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

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 可以通过 window['Foo'] 访问,但是当你使用第一个代码片段中显示的类定义时,你不能再从 window 超级全局访问它,它只输出'undefined'。

那么,有没有什么方法可以通过动态引用访问类中的静态方法,就像您可以通过 window 全局访问 Foo 对象一样?

我希望这是有道理的,我正在正确解释它。如果任何事情没有意义,请随时提问,我会尽量解释得更好。预先感谢您提供的任何帮助。

2个回答

要获得window对象的引用,您需要明确地这样做:

window.Foo = class Foo { ... }

window这个答案中阅读更多关于不是对象属性的类,它还引用了ECMA2015 规范,第 8.1.1.4 节:全球环境记录

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

@Bergi,好的,我明白了。我添加了一个部分。
2021-03-28 17:47:08
当然,但是 OP 的事件库处理程序 thingy基于window,我理解这个问题是......通过全局窗口?. 也许我误解了?
2021-03-29 17:47:08
不,你正确理解了这个问题,我只是想让你添加类似“......当你明确地将类分配给某个地方时,最好不要使用全局命名空间,而是使用包含你想要工作的类的专用对象与您的活动”。我认为图书馆的东西也可以改变。
2021-04-09 17:47:08
我可以看到这样的工作。我认为最困难的部分是,我实际上是在开发这个库,供我公司的其他开发人员使用。他们中的大多数人在 JS 中并不是很强大,而只是想在 JS 文件中包含一些简单的函数 pageChange() {}。虽然我把我的建成了一个class。所以我希望找到一个适用于两种编程风格的解决方案,因为 window[fnName].apply() 对它们都适用,但我更喜欢有一个类并以这种方式定义方法。
2021-04-09 17:47:08
您还可以提出一个更好的解决方案来污染全局范围吗?
2021-04-12 17:47:08

我自己也遇到了同样的问题很长一段时间,我终于找到了一个非常简单的解决方案:使用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 倍)

你在哪里打电话评估?你在哪里实例化这个类?
2021-04-13 17:47:08