Javascript ES6 class definition not available in global window

I ran into an interesting problem, at least I think it is 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 this with Foo.pageChange () without any problems, everything works as expected. The hard part and interesting bit comes when I try to access it dynamically. I have a separate object that tracks events and processes them when necessary. This applies to the Google visualization library, where I have a table, and the table has events associated with it. I have an object that is responsible for creating all of this from PHP output. This is one feature of the system, in a simple explanation you can do something similar in PHP ...

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

now it will create a table and all that is good. The problem is accessing this static method in the Foo class in javascript. What I had before creating Foo in the class was as follows.

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

then in my event library handler this would look something like this.

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

and this will work fine, since Foo can be obtained through the ['Foo'] window, but when you use the class definition shown in the first code snippet, you can no longer access it from the super-global window, it simply displays "undefined" .

So, is there a way to access the static method in the class through a dynamic link, as you can, using a Foo object through a global window?

I hope this makes sense, and I explain it correctly. If any question does not make sense, please feel free to ask, I will try to explain better. Thank you in advance for any help you can give.

+7
javascript ecmascript-6 class
source share
2 answers

To get a reference to the window object, you need to do this explicitly:

 window.Foo = class Foo { ... } 

Read more about classes that are not properties of the window object in this answer , which is also quoted in the ECMA2015 Specification, Section 8.1.1.4: Global Environment Reports :

A global environment record is logically a single record, but it is listed as a composite encapsulation of an Environment Record and a declarative environment record. The Environment Record object has as its base the global object of the associated Realm. This global object is the value returned by the specific Recordset GetThisBinding global record method. (For example, the global object referenced by window in browsers is - TJ) The recording component of the object environment of the global recording environment contains bindings for all built-in global variables (section 18) and all bindings entered by FunctionDeclaration, GeneratorDeclaration or VariableStatement contained in the global code. Associations for all other ECMAScript declarations in the global code are contained in the declarative component of the environment record of the global environmental state record.

Using Selected Object

It’s better not to use a global object for this and dedicate a specific object to contain your classes and base your event management library on this object, as shown 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(); } }()); 
+7
source share

I had the same problem for quite some time, and I finally found a very simple solution: using eval .

Create your class:

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

Get dynamically:

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

I don't like eval , but in this case it is as simple as fast. And this is the only way I found without adding a class to the window .

(I also tried (new Function("return Foo;"))() and it looks eval 2-3 times faster)

0
source share

All Articles