Static Variables in JavaScript

Static variables in JavaScript

If you come from a class-based, statically typed object-oriented language (like Java, C++ or C#) I assume that you are trying to create a variable or method associated to a "type" but not to an instance.

An example using a "classical" approach, with constructor functions maybe could help you to catch the concepts of basic OO JavaScript:

function MyClass () { // constructor function
var privateVariable = "foo"; // Private variable

this.publicVariable = "bar"; // Public variable

this.privilegedMethod = function () { // Public Method
alert(privateVariable);
};
}

// Instance method will be available to all instances but only load once in memory
MyClass.prototype.publicMethod = function () {
alert(this.publicVariable);
};

// Static variable shared by all instances
MyClass.staticProperty = "baz";

var myInstance = new MyClass();

staticProperty is defined in the MyClass object (which is a function) and has nothing to do with its created instances, JavaScript treats functions as first-class objects, so being an object, you can assign properties to a function.

UPDATE: ES6 introduced the ability to declare classes through the class keyword. It is syntax sugar over the existing prototype-based inheritance.

The static keyword allows you to easily define static properties or methods in a class.

Let's see the above example implemented with ES6 classes:

class MyClass {

// class constructor, equivalent to

// the function body of a constructor

constructor() {

const privateVariable = 'private value'; // Private variable at the constructor scope

this.publicVariable = 'public value'; // Public property

this.privilegedMethod = function() {

// Public Method with access to the constructor scope variables

console.log(privateVariable);

};

}

// Prototype methods:

publicMethod() {

console.log(this.publicVariable);

}

// Static properties shared by all instances

static staticProperty = 'static value';

static staticMethod() {

console.log(this.staticProperty);

}

}

// We can add properties to the class prototype

MyClass.prototype.additionalMethod = function() {

console.log(this.publicVariable);

};

var myInstance = new MyClass();

myInstance.publicMethod(); // "public value"

myInstance.additionalMethod(); // "public value"

myInstance.privilegedMethod(); // "private value"

MyClass.staticMethod(); // "static value"

Javascript local static variable

In addition to using properties of the function object, as you do in your example, there are 3 other ways to emulate function-local static variables in Javascript.

All of them rely on a closure, but using different syntax.

Method 1 (supported in old browsers):

var someFunc1 = (function(){
var staticVar = 0 ;
return function(){
alert(++staticVar) ;
}
})() ;

someFunc1() ; //prints 1
someFunc1() ; //prints 2
someFunc1() ; //prints 3

Method 2 (also supported in old browsers):

var someFunc2 ;
with({staticVar:0})
var someFunc2 = function(){
alert(++staticVar) ;
} ;

someFunc2() ; //prints 1
someFunc2() ; //prints 2
someFunc2() ; //prints 3

Method 3 (requires support for EcmaScript 2015):

{
let staticVar = 0 ;
function someFunc3(){
alert(++staticVar) ;
}
}

someFunc3() ; //prints 1
someFunc3() ; //prints 2
someFunc3() ; //prints 3

Method 3 for strict mode:

'use strict'
{
let staticVar = 0 ;
var someFunc3 = function(){
alert(++staticVar) ;
} ;
}

someFunc3() ; //prints 1
someFunc3() ; //prints 2
someFunc3() ; //prints 3

How do I use a static variable in ES6 class?

Your class has no static variables (if by static variable you mean static property). getCount returns NaN (after you call increaseCount) because Animal has no count property initially. Then increaseCount does undefined + 1 which is NaN. Instances created by new Animal have a count property initially, but Animal itself does not until you call increaseCount. this within a static method refers to the Animal class (constructor function) itself (if you call it via Animal.methodName(...)).

You could give Animal a count property:

Animal.count = 0;

Live Example:

class Animal {

constructor() {

}

static increaseCount() {

this.count += 1;

}

static getCount() {

return this.count;

}

}

Animal.count = 0;

Animal.increaseCount();

console.log(Animal.getCount());

Animal.increaseCount();

console.log(Animal.getCount());

Correctly declare static variables in JavaScript classes

Static class fields are a stage 3 proposal, meaning they're not yet an official part of the JavaScript language. (Stage 4 is the final stage.) You can read more about the proposal here and the proposal process here.

Currently, Chrome (as of version 72) is the only browser that supports static class fields.

To use this feature in other browsers you would need to use Babel with @babel/plugin-proposal-class-properties to transpile your code. If you're not already using Babel, however, this might be overkill.

Alternatively, you can assign a property to the class after initializing it. This isn't semantically identical, but works for your (and, indeed, most) use cases.

class AddOrSelectAddress {
// ...
}

AddOrSelectAddress.body = 'some initial value';

You can see this working in the below snippet.

class AddOrSelectAddress {

static changeBody(val) {

this.body = val;

}

static someMethod() {

console.log('in someMethod body is', this.body);

}

static someOtherMethod() {

console.log('in someOtherMethod body is', this.body);

}

}

AddOrSelectAddress.body = 'some initial value';

AddOrSelectAddress.someMethod();

AddOrSelectAddress.changeBody('some other value');

AddOrSelectAddress.someOtherMethod();

Working of static variables in JavaScript

StaticExample is an object. A function object, but an object nonetheless.

You assign a new property to it: StaticExample.staticProp = "Hello".

StaticExample also happens to have a property prototype.

The property StaticExample.prototype.constructor points to StaticExample.

Now, you can obviously access StaticExample.staticProp, because it's simply a property of an object that you assigned.

You can also replace the value of StaticExample.prototype.constructor with something else; now StaticExample.prototype.constructor doesn't point to StaticExample anymore. But StaticExample is still StaticExample and it still has the property staticProp that you created on it. You didn't replace the StaticExample object in any way. What you did replace was StaticExample.prototype.constructor, which is a different property of a different object.

How to define a static variable inside a JS class

In up-to-date JavaScript environments, you can use the static keyword when inside a class to assign properties to the instance itself - the code in your question works fine now.

class SomeClass {
static someStaticProperty = {}
}
console.log(SomeClass.someStaticProperty);

declare static variable in javascript

JS variables are local to a function or they are global. Since you declared i outside a function, it's global.

To prove this, save this as test.html, open it in your browser and press the button a few times. I simplified your function a bit!

<script>
var i=0
function mul(){
alert("i: " + i++)
}
</script>
<button onclick='mul()'>Press me</button>

How to declare a static variable in Javascript

function Person(){
this.name = "Peter";
Person.counter++;
alert(Person.counter);
}

Person.counter = 0;

var p1 = new Person();
var p2 = new Person();

Make the "static" variable a property of the Person function, rather than the prototype, and use Person instead of this inside the constructor.

This is possible because JavaScript functions are first-class (i.e. they are objects), so can have properties of their own.

Here's a working example of the above code.

are static variables thread safe in javascript

That code won't run into threading issues, no.

Node.js isn't single-threaded, but unless you create additional JavaScript threads via the workers module, your code runs on a single thread, and even if you do create worker threads those threads run isolated from one another and from the main thread (they don't share a global environment; but they can communicate via messsaging and share memory in a very specific, bounded way via SharedArrayBuffer).


Side note: Using JSON to deep copy objects is not best practice. It's lossy (any non-enumerable property is dropped, any property whose value is undefined or a function is dropped, any property named with a Symbol is dropped, any inherited property is dropped, and prototypes are not maintained), it will fail for anything with circular references, and it makes an unnecessary round-trip through text. See this question's answers for various approaches to doing deep copy in JavaScript.

Javascript: Using function properties as static variables and optimization

V8 developer here. I don't remember that putting properties on function objects has ever caused problems. Do you have a source for that claim? Maybe it's a misunderstanding.

At any rate, these days you can definitely do that without issues.



Related Topics



Leave a reply



Submit