How can I create static variables in Javascript?
In addition to the rest, there's currently a draft (stage-2 proposal) on ECMA Proposals that introduces static public fields in classes. (private fields were considered)
Using the example from the proposal, the proposed static syntax will look like this:
class CustomDate {
// ...
static epoch = new CustomDate(0);
}
and be equivalent to the following which others have highlighted:
class CustomDate {
// ...
}
CustomDate.epoch = new CustomDate(0);
You can then access it via CustomDate.epoch.
You can keep track of the new proposal in proposal-static-class-features.
Currently, babel supports this feature with the transform class properties plugin which you can use. Additionally, though still in progress, V8 is implementing it.
There are 4 ways to emulate function-local static variables in Javascript.
Method 1: Using function object properties (supported in old browsers)
function someFunc1(){
if( !('staticVar' in someFunc1) )
someFunc1.staticVar = 0 ;
alert(++someFunc1.staticVar) ;
}
someFunc1() ; //prints 1
someFunc1() ; //prints 2
someFunc1() ; //prints 3
Method 2: Using a closure, variant 1 (supported in old browsers)
var someFunc2 = (function(){
var staticVar = 0 ;
return function(){
alert(++staticVar) ;
}
})()
someFunc2() ; //prints 1
someFunc2() ; //prints 2
someFunc2() ; //prints 3
Method 3: Using a closure, variant 2 (also supported in old browsers)
var someFunc3 ;
with({staticVar:0})
var someFunc3 = function(){
alert(++staticVar) ;
}
someFunc3() ; //prints 1
someFunc3() ; //prints 2
someFunc3() ; //prints 3
Method 4: Using a closure, variant 3 (requires support for EcmaScript 2015)
{
let staticVar = 0 ;
function someFunc4(){
alert(++staticVar) ;
}
}
someFunc4() ; //prints 1
someFunc4() ; //prints 2
someFunc4() ; //prints 3
Method 4 for strict mode
'use strict'
{
let staticVar = 0 ;
var someFunc4 = function(){
alert(++staticVar) ;
} ;
}
someFunc4() ; //prints 1
someFunc4() ; //prints 2
someFunc4() ; //prints 3
If you wanted to make a global static variable:
var my_id = 123;
Replace the variable with the below:
Object.defineProperty(window, 'my_id', {
get: function() {
return 123;
},
configurable : false,
enumerable : false
});
To condense all class concepts here, test this:
var Test = function() {
// "super private" variable, accessible only here in constructor. There are no real private variables
//if as 'private' we intend variables accessible only by the class that defines the member and NOT by child classes
var test_var = "super private";
//the only way to access the "super private" test_var is from here
this.privileged = function(){
console.log(test_var);
}();
Test.test_var = 'protected';//protected variable: accessible only form inherited methods (prototype) AND child/inherited classes
this.init();
};//end constructor
Test.test_var = "static";//static variable: accessible everywhere (I mean, even out of prototype, see domready below)
Test.prototype = {
init:function(){
console.log('in',Test.test_var);
}
};//end prototype/class
//for example:
$(document).ready(function() {
console.log('out',Test.test_var);
var Jake = function(){}
Jake.prototype = new Test();
Jake.prototype.test = function(){
console.log('jake', Test.test_var);
}
var jake = new Jake();
jake.test();//output: "protected"
});//end domready
Well, another way to take a look to best practices in these things, is to just see how coffeescript translates these concepts.
#this is coffeescript
class Test
#static
@prop = "static"
#instance
constructor:(prop) ->
@prop = prop
console.log(@prop)
t = new Test('inst_prop');
console.log(Test.prop);
//this is how the above is translated in plain js by the CS compiler
Test = (function() {
Test.prop = "static";
function Test(prop) {
this.prop = prop;
console.log(this.prop);
}
return Test;
})();
t = new Test('inst_prop');
console.log(Test.prop);
static keywordTC39 moved the STATIC keyword to being Stage-4 Language Feature as of APRIL, 2021. It took a long time to make the static JS features an official set of JS language features, the wait was due to lacking browser support, however; Major browsers now support the static keyword, and its open season for public static fields & private static fields.
class ColorFinder {
static #red = "#ff0000";
static #green = "#00ff00";
static #blue = "#0000ff";
static colorName(name) {
switch (name) {
case "red": return ColorFinder.#red;
case "blue": return ColorFinder.#blue;
case "green": return ColorFinder.#green;
default: throw new RangeError("unknown color");
}
}
// Somehow use colorName
}
You can define static functions in JavaScript using the static keyword:
class MyClass {
static myStaticFunction() {
return 42;
}
}
MyClass.myStaticFunction(); // 42
As of this writing, you still can't define static properties (other than functions) within the class. Static properties are still a Stage 3 proposal, which means they aren't part of JavaScript yet. However, there's nothing stopping you from simply assigning to a class like you would to any other object:
class MyClass {}
MyClass.myStaticProperty = 42;
MyClass.myStaticProperty; // 42
Final note: be careful about using static objects with inheritance - all inherited classes share the same copy of the object.
For private static variables, I found this way:
function Class()
{
}
Class.prototype = new function()
{
_privateStatic = 1;
this.get = function() { return _privateStatic; }
this.inc = function() { _privateStatic++; }
};
var o1 = new Class();
var o2 = new Class();
o1.inc();
console.log(o1.get());
console.log(o2.get()); // 2
In ES6/ES 2015 the class keyword was introduced with an accompanied static keyword. Keep in mind that this is syntactic sugar over the prototypal inheritance model which javavscript embodies. The static keyword works in the following way for methods:
class Dog {
static bark () {console.log('woof');}
// classes are function objects under the hood
// bark method is located on the Dog function object
makeSound () { console.log('bark'); }
// makeSound is located on the Dog.prototype object
}
// to create static variables just create a property on the prototype of the class
Dog.prototype.breed = 'Pitbull';
// So to define a static property we don't need the `static` keyword.
const fluffy = new Dog();
const vicky = new Dog();
console.log(fluffy.breed, vicky.breed);
// changing the static variable changes it on all the objects
Dog.prototype.breed = 'Terrier';
console.log(fluffy.breed, vicky.breed);
I normally use this method for 2 main reasons:
if I want to store functions local values, I use something like "Local.x", "Local.y", "Local.TempData", etc ...!
If I want to store functions static values, I use something like "Static.o", "Static.Info", "Static.count", etc ...!
[Update2]: Same method, but uses IIFE approach!
[Update1]: "Static" and "Local" objects For Functions are created automatically By Pre-Editing Scripts!
I used the prototype and that way it worked:
class Cat {
constructor() {
console.log(Cat.COLLECTION_NAME);
}
}
Cat.COLLECTION_NAME = "cats";
or using an static getter:
class Cat {
constructor() {
console.log(Cat.COLLECTION_NAME);
}
static get COLLECTION_NAME() {
return "cats"
}
}
I have universal method:
stat_flags = {};flags.popup_save_inited = true;Example:
class ACTGeneratedPages {
constructor(table_data, html_table_id) {
this.flags = {};//static flags for any processes
//any your code here
}
call_popup(post_id) {
let _this = this;
document.getElementById('act-popup-template').style.display = 'block';
if (!this.flags.popup_save_inited) {//second time listener will not be attached
document.querySelector('.act-modal-save').addEventListener('click', function (e) {
//saving data code here
return false;
});
}
this.flags.popup_save_inited = true;//set flag here
}
}
ES6 classes support static functions that behave much like static functions in other object-oriented languages:
class MyClass {
static myFunction() {
return 42;
}
}
typeof MyClass.myFunction; // 'function'
MyClass.myFunction(); // 42
General static properties are still a stage 3 proposal, which means you need Babel's stage 3 preset to use them. But with Babel, you can do this:
class MyClass {
static answer = 42;
}
MyClass.answer; // 42
you can reassign the function after static variables have been declared
function IHaveBeenCalled() {
console.log("YOU SHOULD ONLY SEE THIS ONCE");
return "Hello World: "
}
function testableFunction(...args) {
testableFunction=inner //reassign the function
const prepend=IHaveBeenCalled()
return inner(...args) //pass all arguments the 1st time
function inner(num) {
console.log(prepend + num);
}
}
testableFunction(2) // Hello World: 2
testableFunction(5) // Hello World: 5
this uses ...args which is slower, is there a way to use scope of parent function for the 1st time instead of passing all arguments ?
my use case:
function copyToClipboard(...args) {
copyToClipboard = inner //reassign the function
const child_process = require('child_process')
return inner(...args) //pass all arguments the 1st time
function inner(content_for_the_clipboard) {
child_process.spawn('clip').stdin.end(content_for_the_clipboard)
}
}
if you want to use child_process outside of scope, you can assign it to a property of copyToClipboard
function copyToClipboard(...args) {
copyToClipboard = inner //reassign the function
copyToClipboard.child_process = require('child_process')
return inner(...args) //pass all arguments the 1st time
function inner(content_for_the_clipboard) {
copyToClipboard.child_process.spawn('clip').stdin.end(content_for_the_clipboard)
}
}