Definição de class do Javascript ES6 não acessível na janela global

Eu me deparei com uma questão interessante, pelo menos eu acho que é interessante e um pouco chato. Eu tenho uma aula, para essa pergunta eu vou manter isso extremamente simples …

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

Agora, eu posso acessar isso com Foo.pageChange () sem problema, tudo funciona como esperado. A parte difícil e o bit interessante aparecem quando tento acessar isso dinamicamente. Eu tenho um object separado que monitora events e manipula despachando-os conforme necessário. Isso se refere à biblioteca de visualização do Google, onde tenho uma tabela e a tabela tem events vinculados a ela. Eu tenho um object que é responsável por criar tudo isso a partir da saída do PHP. É um pedaço de um sistema, em uma explicação fácil, você pode fazer algo assim em PHP …

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

agora isso vai criar a mesa e todas essas coisas boas. O problema é acessar esse método estático na class Foo em javascript. O que eu tinha antes de criar o Foo como uma class era isso.

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

então no meu manipulador de biblioteca de events thingy seria algo como isto ..

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

e isso funcionaria bem porque o Foo pode ser acessado através da janela [‘Foo’] mas quando você usa a definição de class mostrada no primeiro trecho de código, você não pode mais acessá-lo da janela super global, ele apenas exibe ‘undefined’.

Então, existe alguma maneira de acessar um método estático em uma class, através de uma referência dinâmica, como você pode com o object Foo através da janela global?

Espero que faça sentido e estou explicando corretamente. Se anyhting não faz sentido, por favor, não hesite em perguntar, vou tentar explicar melhor. Agradeço antecipadamente por qualquer ajuda que você possa dar.

Para obter uma referência no object da window , você precisará fazer isso explicitamente:

 window.Foo = class Foo { ... } 

Leia mais sobre as classs que não são propriedades do object window nesta resposta , que também cita a Especificação ECMA2015, Seção 8.1.1.4: Registros globais de ambiente :

Um registro de ambiente global é logicamente um único registro, mas é especificado como um composto que encapsula um registro de ambiente de object e um registro de ambiente declarativo. O object Environment Record tem como object base o object global do Realm associado. Esse object global é o valor retornado pelo método concreto GetThisBinding do registro de ambiente global. (Por exemplo, o object global referenciado pela window em navegadores – TJ) O componente de registro de ambiente de object de um registro de ambiente global contém as ligações para todos os globais internos (cláusula 18) e todas as ligações introduzidas por um FunctionDeclaration , GeneratorDeclaration ou VariableStatement contidos no código global. As ligações para todas as outras declarações ECMAScript no código global estão contidas no componente declarative Environment Record do registro de ambiente global.

Usando um object dedicado

Seria melhor não usar o object global para isso e dedicar um object específico para conter suas classs e basear sua biblioteca de gerenciamento de events nesse object, conforme ilustrado neste snippet simplificado:

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

Eu mesmo tive o mesmo problema por um bom tempo e finalmente descobri uma solução muito simples: usar o eval .

Crie sua turma:

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

Obtê-lo dinamicamente:

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

Eu não gosto de eval , mas neste caso é tão simples quanto rápido. E é a única maneira que encontrei sem adicionar a class à window .

(Eu também tentei (new Function("return Foo;"))() e parece eval é 2-3 vezes mais rápido)