Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class Variables in Javascript

I'm having a bit of trouble trying to get class variables to work in javascript.

I thought that I understood the prototype inheritance model, but obviously not. I assumed that since prototypes will be shared between objects then so will their variables.

This is why this bit of code confuses me.

What is the correct way to implement class variables?

function classA() {};

classA.prototype.shared = 0;

a = new classA;

//print both values to make sure that they are the same
classA.prototype.shared;
a.shared;

//increment class variable
classA.prototype.shared++;

//Verify that they are each 1 (Works)
classA.prototype.shared;
a.shared;

//now increment the other reference
a.shared++;

//Verify that they are each 2 (Doesn't Work)
classA.prototype.shared;
a.shared;

UPDATE: So it seems that everyone is confirming the fact that by incrementing the instance's variable we don't affect the prototype. This is fine, this is what I have documented in my example, but doesn't this seem like an error in the design of the language? Why would this behavior be desirable? I find it weird that when the instance's var is undefined we follow the hidden link to the prototype where we get the value of the var, but we copy it into the instance object.

I also understand that this isn't java/c++/ruby/python, it's a different language. I'm just curious as to why this behavior might be good.

like image 622
esiegel Avatar asked Nov 04 '08 08:11

esiegel


People also ask

Can JavaScript classes have variables?

We can also define private variables in a class. Private variables must be explicitly declared inside the class body and are prefixed by a #. They can only be accessed inside class member functions.

How do you declare a class variable in JavaScript?

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.

What are classes in JavaScript?

Classes are a template for creating objects. They encapsulate data with code to work on that data. Classes in JS are built on prototypes but also have some syntax and semantics that are not shared with ES5 class-like semantics.

What type of variable is a class?

Class variables − Class variables also known as static variables are declared with the static keyword in a class, but outside a method, constructor or a block. There would only be one copy of each class variable per class, regardless of how many objects are created from it.


2 Answers

Static (class level) variables can be done like this:

function classA(){
    //initialize
}

classA.prototype.method1 = function(){
    //accessible from anywhere
    classA.static_var = 1;
    //accessible only from THIS object
    this.instance_var = 2;
}

classA.static_var = 1;  //This is the same variable that is accessed in method1()

Your output seems strange because of the way javascript handles prototypes. Calling any method / retreiving a variable of an instantiated object checks the instance first, THEN the prototype. i.e.

var a = new classA();
classA.prototype.stat = 1;

// checks a.stat which is undefined, then checks classA.prototype.stat which has a value
alert(a.stat); // (a.stat = undefined, a.prototype.stat = 1)

// after this a.stat will not check the prototype because it is defined in the object.
a.stat = 5;  // (a.stat = 5, a.prototype.stat = 1)

// this is essentially a.stat = a.stat + 1;
a.stat++; // (a.stat = 6, a.prototype.stat = 1) 
like image 100
Daniel Beardsley Avatar answered Oct 20 '22 12:10

Daniel Beardsley


I assumed that since prototypes will be shared between objects then so will their variables.

They are, but this:

a.shared++

is not doing what you think it's doing. It's in fact (approximately) sugar syntax for:

(a.shared= a.shared+1)-1

(the -1 being to return the pre-increment value, not that you're actually using the retrun value, but still.)

So this is actually doing an assigment to a.shared. When you assign to an instance member you are always writing to that instance's own members, not touching any members of any of its prototypes. It's the same as saying:

classA.prototype.shared= 1;
a.shared= 2;

So your new a.shared hides the prototype.shared without altering it. Other instances of classA would continue to show the prototype's value 1. If you deleted a.shared you would once again be able to see the prototype's variable that was hidden behind it.

like image 27
bobince Avatar answered Oct 20 '22 11:10

bobince