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
How to Avoid 'Cannot Read Property of Undefined' Errors
Preloading Images With JavaScript
How to Find Object in Array by Property in JavaScript
Force Browser to Refresh CSS, JavaScript, etc
How to Get Border Width in Jquery/Javascript
Example of How to Load Static CSS Files from Node_Modules Using Webpack
Rails: Post 422 (Unprocessable Entity) in Rails? Due to the Routes or the Controller
Detect Click Outside React Component
Does JavaScript Have "Short-Circuit" Evaluation
Ecmascript Template Literals Like 'Some ${String}' Are Not Working
Arrow Function Without Curly Braces
Why Is Null an Object and What's the Difference Between Null and Undefined
Jquery Drag/Resize with CSS Transform Scale
Webkit-Transform Overwrites Z-Index Ordering in Chrome 13
How to Check If CSS Value Is Supported by the Browser