Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ES6 class variable alternatives

Currently in ES5 many of us are using the following pattern in frameworks to create classes and class variables, which is comfy:

// ES 5 FrameWork.Class({      variable: 'string',     variable2: true,      init: function(){      },      addItem: function(){      }  }); 

In ES6 you can create classes natively, but there is no option to have class variables:

// ES6 class MyClass {     const MY_CONST = 'string'; // <-- this is not possible in ES6     constructor(){         this.MY_CONST;     } } 

Sadly, the above won't work, as classes only can contain methods.

I understand that I can this.myVar = true in constructor…but I don't want to 'junk' my constructor, especially when I have 20-30+ params for a bigger class.

I was thinking of many ways to handle this issue, but haven't yet found any good ones. (For example: create a ClassConfig handler, and pass a parameter object, which is declared separately from the class. Then the handler would attach to the class. I was thinking about WeakMaps also to integrate, somehow.)

What kind of ideas would you have to handle this situation?

like image 465
wintercounter Avatar asked Mar 20 '14 09:03

wintercounter


People also ask

Which JavaScript feature is the alternative to the ES6 classes the class keyword )?

The function keyword is replaced with the class keyword. There's a special function named 'constructor' where the initialization of the object is done.

Can JavaScript classes have variables?

To declare a variable within a class, it needs to be a property of the class or, as you did so, scoped within a method in the class. It's all about scoping and variables are not supported in the scope definition of a class.

How many ways can you define a variable in ES6?

Now, with ES6, there are three ways of defining your variables: var , let , and const .

How can we declare a variable which can't be updated in ES6?

The const. The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned.


2 Answers

2018 update:

There is now a stage 3 proposal - I am looking forward to make this answer obsolete in a few months.

In the meantime anyone using TypeScript or babel can use the syntax:

varName = value 

Inside a class declaration/expression body and it will define a variable. Hopefully in a few months/weeks I'll be able to post an update.

Update: Chrome 74 now ships with this syntax working.


The notes in the ES wiki for the proposal in ES6 (maximally minimal classes) note:

There is (intentionally) no direct declarative way to define either prototype data properties (other than methods) class properties, or instance property

Class properties and prototype data properties need be created outside the declaration.

Properties specified in a class definition are assigned the same attributes as if they appeared in an object literal.

This means that what you're asking for was considered, and explicitly decided against.

but... why?

Good question. The good people of TC39 want class declarations to declare and define the capabilities of a class. Not its members. An ES6 class declaration defines its contract for its user.

Remember, a class definition defines prototype methods - defining variables on the prototype is generally not something you do. You can, of course use:

constructor(){     this.foo = bar } 

In the constructor like you suggested. Also see the summary of the consensus.

ES7 and beyond

A new proposal for ES7 is being worked on that allows more concise instance variables through class declarations and expressions - https://esdiscuss.org/topic/es7-property-initializers

like image 168
Benjamin Gruenbaum Avatar answered Nov 23 '22 04:11

Benjamin Gruenbaum


Just to add to Benjamin's answer — class variables are possible, but you wouldn't use prototype to set them.

For a true class variable you'd want to do something like the following:

class MyClass {} MyClass.foo = 'bar'; 

From within a class method that variable can be accessed as this.constructor.foo (or MyClass.foo).

These class properties would not usually be accessible from to the class instance. i.e. MyClass.foo gives 'bar' but new MyClass().foo is undefined

If you want to also have access to your class variable from an instance, you'll have to additionally define a getter:

class MyClass {     get foo() {         return this.constructor.foo;     } }  MyClass.foo = 'bar'; 

I've only tested this with Traceur, but I believe it will work the same in a standard implementation.

JavaScript doesn't really have classes. Even with ES6 we're looking at an object- or prototype-based language rather than a class-based language. In any function X () {}, X.prototype.constructor points back to X. When the new operator is used on X, a new object is created inheriting X.prototype. Any undefined properties in that new object (including constructor) are looked up from there. We can think of this as generating object and class properties.

like image 25
lyschoening Avatar answered Nov 23 '22 05:11

lyschoening