7

This is going to be a relatively long question, but one I would really like to understand. Final question formulated at the bottom of the question.

I have read the answers to this question:
ES6 class variable alternatives

The question on why this is not accepted syntax in ES6:

class MyClass {
    const MY_CONST = 'string';
    constructor(){
        this.MY_CONST;
    }
}

1) The first answer mentions:

Remember, a class definition defines prototype methods - defining variables on the prototype is generally not something you do.

I don't get this; static variables in a class based language would appear to serve the same purpose as properties defined on the prototype in JS.
Obviously not an instance variable like a person's name, but it could be a default MAX_SPEED for a vehicle, or a counter that is shared by all instances. If the instance doesn't override the prototype's MAX_SPEED, it returns to the default. Isn't that the exact purpose of a static variable?

2) The following post (ES6 spec proposal) formulates:

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.

I don't see the actual difference in declaring / initialising an instance/class variable with default value within the class itself (outside the constructor)? What does it matter if it's on the prototype? If it concerns an instance variable with a default value that will be likely for all instances (yet overridable), I don't see what is the problem. So what is this intention about exactly?

3) The second answer on the question ES6 class variable alternatives confuses me (though not from a technical pov).

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

This indicates that it is clearly possible to declare a class variable on the class (or underlying function) as implemented in this example: http://www.es6fiddle.net/iehn0hxp/

class Car{
  constructor(){
    //Set instance variable 
    this.instance_var = 220; 
    //Set class variable 
    this.constructor.class_var = 240; 
  }
}

var Mercedes = new Car(); 
var Audi = new Car(); 

//Instance property 
console.log(Mercedes.instance_var); //220 
//Class property 
console.log(Car.class_var); //240

//Set instance property 
Mercedes.instance_var = 120; //Well I don't know really :-) 
console.log(Mercedes.instance_var); //120 

//Class property 
Car.class_var = 140; 
console.log(Car.class_var); //140 
//Can be accessed from the constructor property on the instance
console.log(Mercedes.constructor.class_var); //140 
console.log(Audi.constructor.class_var); //140 

So in the end it is possible to declare a static property from within the class; so I don't see what is the difference declaring it within the constructor, versus just defining it on the class, vs defining it from outside? In the end it just seems to be a trivial technical modification to put it in the constructor vs as an actual class definition (the result will be the same).

Is it really just a design choice to only make methods available?
Ultimate question:

Because I don't understand how being a prototype-language changes the philosophy of having properties on the prototype against static variables on a class. It looks the same to me.

I hope that my question is clear, shout if not.

Community
  • 1
  • 1
html_programmer
  • 18,126
  • 18
  • 85
  • 158
  • 2
    *"The question on why this is not accepted syntax in ES6"* Likely because they could not finalize / decide upon this feature in time. There already is a proposal for ES7, but it's still at stage 0. https://gist.github.com/jeffmo/054df782c05639da2adb . There seems to be a lot of back and forth about details and semantics. Getting a language right is not that easy :) – Felix Kling Sep 13 '15 at 03:51
  • @FelixKling I can imagine it's really not easy. I absolutely don't mind the current syntax, as long as I get the situation right. It got pretty confusing last night. – html_programmer Sep 13 '15 at 11:48

1 Answers1

8

I don't get this; static variables in a class based language would appear to serve the same purpose as properties defined on the prototype in JS.

No, static variables are more like properties defined on the constructor. Variables on the prototype would be closer to instance variables, but they’re not nearly as useful because they’re shared between instances. (So if you modify a mutable property on the prototype, it will be reflected in all other instances of that type.)

This also answers your other questions, I think, but to recap:

  • variables on the prototype are not like static variables in that they appear to belong to every instance rather than just the class

  • variables on the prototype are not like instance variables in that each instance of the class doesn’t have its own instance of the variable

  • therefore, variables on the prototype are not that useful and they should be assigned to in the constructor (instance variables) or assigned to the constructor (class variables)

  • they’re also properties, not variables

And a non-ES6-sugared example:

function Something() {
    this.instanceProperty = 5;
}

Something.staticProperty = 32;

Something.prototype.prototypeProperty = 977;

var s = new Something();
console.log(s.instanceProperty); // 5
console.log(s.prototypeProperty); // 977? If you want a class property,
                                  // this is not what you want
console.log(s.staticProperty); // undefined; it’s not on the instance
console.log(Something.staticProperty); // 32; rather, it’s on the class
console.log(Something.prototypeProperty); // undefined; this one isn’t
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • Thanks for elaborate answer. You're right, it's rather like properties defined on the constructor, your example makes that abundantly clear, it was a thinking mistake I made. What I still have trouble with understanding is why the ES6 spec proposal doesn't want to allow the definition of static variables on the class (talking about class terminology), but rather outside. I suppose that it's just making a mapping to set them as a property on the constructor when transpiling? Aside from where you rectified me, this is what I actually don't get. – html_programmer Sep 13 '15 at 02:06
  • Also setting instance variables (say defaults) should happen either in the constructor of the class or from outside. Why? I mean they still call it a "class" in ES6, and I suppose it is not impossible for transpilers to translate it to adequate JS (?). – html_programmer Sep 13 '15 at 02:07
  • @KimGysen: I’d imagine that, since instance methods go inside the class, they didn’t want to cause confusion or require the use of some keyword. After all, it’s not difficult to add static variables outside of the class block, and they can go immediately after the class. I don’t understand your second question, sorry. – Ry- Sep 13 '15 at 02:18
  • The second question related to `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.` So they also refer to instance properties. I assume that they mean initializing class instance variables outside the constructor. I guess it's just a choice after all. It doesn't bother me, as long as I get it right. – html_programmer Sep 13 '15 at 02:25
  • how would you go about seal/freeze the instance's properties, such as `Something` ? – vsync Jun 24 '18 at 21:38
  • @vsync: `Object.seal(this)` in the constructor? – Ry- Jun 25 '18 at 04:54
  • I wonder if there's an option to let the Object's internal prototype functions modify the `this` properties, but not allow that from the outside, after a Constructor was Instantiated – vsync Jun 25 '18 at 07:26
  • @vsync: There isn’t, and that sounds unnecessary. – Ry- Jun 25 '18 at 09:28