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?
The function keyword is replaced with the class keyword. There's a special function named 'constructor' where the initialization of the object is done.
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.
Now, with ES6, there are three ways of defining your variables: var , let , and const .
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.
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With