ChatGPT解决这个技术问题 Extra ChatGPT

Static variables in JavaScript

How can I create static variables in Javascript?

we can define label or other html tag with "dispaly:none" style attribute and set variable value for this value and operation on this value. Let's not take hard.
The simplest solution I found: don't define a static variable in the class at all. When you want to use a static variable, just define it there and then, e.g. someFunc = () => { MyClass.myStaticVariable = 1; }. Then just create a static method to return the static member, e.g. static getStatic() { return MyClass.myStaticVariable; }. Then you can just call MyClass.getStatic() from outside the class to get hold of the static data !
I create my own static variable, by adding new attribute to HTML element , btn.setAttribute( 'arr' , 0 ) I can get/change that value on anywhere on the script btn.getAttribute('arr')

C
Christian C. Salvadó

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"


Presumably privilegedMethod is not equivalent to a private method in OO because it seems like it could be called on an instance of MyClass? Do you mean it's privileged because it can access privateVariable?
Can't this.constructor be used to access the static variables from "instance methods"? If yes, it's worth adding it to the answer.
You could also mention static functions in your example.
hi, I am not sure I agree with this line // Static variable shared by all instance 'MyClass.staticProperty = "baz";' as to me that infers that you can find baz from 'myInstance.staticProperty' which of course you can't.
Perhaps it should read MyClass.prototype.staticProperty = "baz"; or to be even more correct to OO principles the static property should actually be defined as an anonymous function MyClass.prototype.staticProperty = function () {return staticVar;} and so that all instances access a single variable which could also be altered with a setter.
G
Goozak

You might take advantage of the fact that JS functions are also objects -- which means they can have properties.

For instance, quoting the example given on the (now vanished) article Static variables in Javascript:

function countMyself() {
    // Check to see if the counter has been initialized
    if ( typeof countMyself.counter == 'undefined' ) {
        // It has not... perform the initialization
        countMyself.counter = 0;
    }

    // Do something stupid to indicate the value
    alert(++countMyself.counter);
}

If you call that function several times, you'll see that the counter is being incremented.

And this is probably a much better solution than poluting the global namespace with a global variable.

Here is another possible solution, based on a closure : Trick to use static variables in javascript :

var uniqueID = (function() {
   var id = 0; // This is the private persistent value
   // The outer function returns a nested function that has access
   // to the persistent value.  It is this nested function we're storing
   // in the variable uniqueID above.
   return function() { return id++; };  // Return and increment
})(); // Invoke the outer function after defining it.

Which gets you the same kind of result -- except, this time, the incremented value is returned, instead of displayed.


as a shortcut, you could just do countMyself.counter = countMyself.counter || initial_value; if the static variable is never going to be falsey (false, 0, null, or empty string)
Slightly shorter and clearer: (function() { var id = 0; function uniqueID() { return id++; }; })();
Counter in closure is very faster than in the class in Firefox. jsperf.com/static-counter-in-class-vs-in-closure
Use === for typeof checks else you'll get some weird coercion going on.
@SonySantos Your test shows the opposite for Firefox 40
k
khoomeister

You do it through an IIFE (immediately invoked function expression):

var incr = (function () {
    var i = 1;

    return function () {
        return i++;
    }
})();

incr(); // returns 1
incr(); // returns 2

I'd say this is the most idiomatic way to do it in JavaScript. Too bad it doesn't get too many upvotes thanks to other methods which are probably more palatable to people that come from other languages.
I'd rephrase using 'closure' rather than just 'IIFE'.
Congrats, definitively the best reply, simple is beautiful. Even if it is obvious, may I extend the response:var incr = (function (delta) { var i = 1; return function (delta) return i+=delta;} })();
I have heard them called Anonymous Self-Invoking Functions, otherwise known as "ASIF's" ("as if" you could actually read them.) :)
M
Matt

I've seen a couple of similar answers, but I'd like to mention that this post describes it best, so I'd like to share it with you.

Here's some code taken from it, which I have modified to get a complete example which hopefully gives benefit to the community because it can be used as a design template for classes.

It also answers your question:

function Podcast() {

    // private variables
    var _somePrivateVariable = 123;

    // object properties (read/write)
    this.title = 'Astronomy Cast';
    this.description = 'A fact-based journey through the galaxy.';
    this.link = 'http://www.astronomycast.com';

    // for read access to _somePrivateVariable via immutableProp 
    this.immutableProp = function() {
        return _somePrivateVariable;
    }

    // object function
    this.toString = function() {
       return 'Title: ' + this.title;
    }
};

// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
    console.log('Downloading ' + podcast + ' ...');
};

Given that example, you can access the static properties/function as follows:

// access static properties/functions
console.log(Podcast.FILE_EXTENSION);   // 'mp3'
Podcast.download('Astronomy cast');    // 'Downloading Astronomy cast ...'

And the object properties/functions simply as:

// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString());       // Title: The Simpsons
console.log(podcast.immutableProp());  // 123

Note that in podcast.immutableProp(), we have a closure: The reference to _somePrivateVariable is kept inside the function.

You can even define getters and setters. Take a look at this code snippet (where d is the object's prototype for which you want to declare a property, y is a private variable not visible outside of the constructor):

// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
    get: function() {return this.getFullYear() },
    set: function(y) { this.setFullYear(y) }
});

It defines the property d.year via get and set functions - if you don't specify set, then the property is read-only and cannot be modified (be aware you will not get an error if you try to set it, but it has no effect). Each property has the attributes writable, configurable (allow to change after declaration) and enumerable (allow to use it as enumerator), which are per default false. You can set them via defineProperty in the 3rd parameter, e.g. enumerable: true.

What is also valid is this syntax:

// getters and setters - alternative syntax
var obj = { a: 7, 
            get b() {return this.a + 1;}, 
            set c(x) {this.a = x / 2}
        };

which defines a readable/writable property a, a readonly property b and a write-only property c, through which property a can be accessed.

Usage:

console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21

Notes:

To avoid unexpected behaviour in case you've forgotten the new keyword, I suggest that you add the following to the function Podcast:

// instantiation helper
function Podcast() {
    if(false === (this instanceof Podcast)) {
        return new Podcast();
    }
// [... same as above ...]
};

Now both of the following instantiations will work as expected:

var podcast = new Podcast(); // normal usage, still allowed
var podcast = Podcast();     // you can omit the new keyword because of the helper

The 'new' statement creates a new object and copies all properties and methods, i.e.

var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"

Note also, that in some situations it can be useful to use the return statement in the constructor function Podcast to return a custom object protecting functions the class internally relies on but which need to be exposed. This is explained further in chapter 2 (Objects) of the article series.

You can say that a and b inherit from Podcast. Now, what if you want to add a method to Podcast that applies to all of them after a and b have been instanciated? In this case, use the .prototype as follows:

Podcast.prototype.titleAndLink = function() {
    return this.title + " [" + this.link + "]";
};

Now call a and b again:

console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"

You can find more details about prototypes here. If you want to do more inheritance, I suggest looking into this.

The article series I've mentioned above are highly recommended to read, they include also the following topics:

Functions Objects Prototypes Enforcing New on Constructor Functions Hoisting Automatic Semicolon Insertion Static Properties and Methods

Note that the automatic semicolon insertion "feature" of JavaScript (as mentioned in 6.) is very often responsible for causing strange issues in your code. Hence, I would rather regard it as a bug than as a feature.

If you want to read more, here is a quite interesting MSDN article about these topics, some of them described there provide even more details.

What is interesting to read as well (also covering the topics mentioned above) are those articles from the MDN JavaScript Guide:

A re-introduction to JavaScript

Working with Objects

If you want to know how to emulate c# out parameters (like in DateTime.TryParse(str, out result)) in JavaScript, you can find sample code here.

Those of you who are working with IE (which has no console for JavaScript unless you open the developer tools using F12 and open the console tab) might find the following snippet useful. It allows you to use console.log(msg); as used in the examples above. Just insert it before the Podcast function.

For your convenience, here's the code above in one complete single code snippet:

let console = { log: function(msg) { let canvas = document.getElementById("log"), br = canvas.innerHTML==="" ? "" : "
"; canvas.innerHTML += (br + (msg || "").toString()); }}; console.log('For details, see the explaining text'); function Podcast() { // with this, you can instantiate without new (see description in text) if (false === (this instanceof Podcast)) { return new Podcast(); } // private variables var _somePrivateVariable = 123; // object properties this.title = 'Astronomy Cast'; this.description = 'A fact-based journey through the galaxy.'; this.link = 'http://www.astronomycast.com'; this.immutableProp = function() { return _somePrivateVariable; } // object function this.toString = function() { return 'Title: ' + this.title; } }; // static property Podcast.FILE_EXTENSION = 'mp3'; // static function Podcast.download = function(podcast) { console.log('Downloading ' + podcast + ' ...'); }; // access static properties/functions Podcast.FILE_EXTENSION; // 'mp3' Podcast.download('Astronomy cast'); // 'Downloading Astronomy cast ...' // access object properties/functions var podcast = new Podcast(); podcast.title = 'The Simpsons'; console.log(podcast.toString()); // Title: The Simpsons console.log(podcast.immutableProp()); // 123 // getters and setters var d = Date.prototype; Object.defineProperty(d, "year", { get: function() { return this.getFullYear() }, set: function(y) { this.setFullYear(y) } }); // getters and setters - alternative syntax var obj = { a: 7, get b() { return this.a + 1; }, set c(x) { this.a = x / 2 } }; // usage: console.log(obj.a); console.log(obj.b); // output: 7, 8 obj.c=40; console.log(obj.a); console.log(obj.b); // output: 20, 21 var a=new Podcast(); var b=new Podcast(); a.title="a"; b.title="An "+b.title; console.log(a.title); // "a" console.log(b.title); // "An Astronomy Cast" Podcast.prototype.titleAndLink = function() { return this.title + " [" + this.link + "]"; }; console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]" console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"

Notes:

Some good tips, hints and recommendations about JavaScript programming in general you can find here (JavaScript best practices) and there ('var' versus 'let'). Also recommended is this article about implicit typecasts (coercion).

A convenient way to use classes and compile them into JavaScript is TypeScript. Here is a playground where you can find some examples showing you how it works. Even if you're not using TypeScript at the moment, you can have a look because you can compare TypeScript with the JavaScript result on a side-by-side view. Most examples are simple, but there is also a Raytracer example which you can try out instantly. I recommend especially looking into the "Using Classes", "Using Inheritance" and "Using Generics" examples by selecting them in the combobox - these are nice templates you can instantly use in JavaScript. Typescript is used with Angular.

To achieve encapsulation of local variables, functions etc in JavaScript, I suggest to use a pattern like the following (JQuery uses the same technique):

Of course, you can - and should - put the script code in a separate *.js file; this is just written inline to keep the example short.

Self-invocing functions (also known as IIFE = Immediately Invoked Function Expression) are described in more detail here.


g
gpilotino

you can use arguments.callee to store "static" variables (this is useful in anonymous function too):

function () {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 1;
  arguments.callee.myStaticVar++;
  alert(arguments.callee.myStaticVar);
}

As far as I can understand, this method has one (only one?) advantage over pascal MARTIN's way: you can use it on anonymous functions. An example of this would be great
arguments.callee is deprecated.
I pretty much ridicule JS all the time, but callee seemed a nice thing to have. I wonder why the hack did they decide to deprecate this... :|
M
Max Heiber

Updated answer:

In ECMAScript 6, you can create static functions using the static keyword:

class Foo {

  static bar() {return 'I am static.'}

}

//`bar` is a property of the class
Foo.bar() // returns 'I am static.'

//`bar` is not a property of instances of the class
var foo = new Foo()
foo.bar() //-> throws TypeError

ES6 classes don't introduce any new semantics for statics. You can do the same thing in ES5 like this:

//constructor
var Foo = function() {}

Foo.bar = function() {
    return 'I am static.'
}

Foo.bar() // returns 'I am static.'

var foo = new Foo()
foo.bar() // throws TypeError

You can assign to a property of Foo because in JavaScript functions are objects.


Foo.bar; returns the function assigned to it, not the string returned by the function as your comment implies.
Can you add some information on how to set (overwrite) a static value in those both examples?
@Wilt in both cases, a "static" property is just a property on the function, so you set it and overwrite it just like you would any other property in JavaScript. In both cases, you can set the bar property of Foo to 3 like this: Foo.bar = 3;
j
jim_zike_huang
function Person(){
  if(Person.count == undefined){
    Person.count = 1;
  }
  else{
    Person.count ++;
  }
  console.log(Person.count);
}

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

B
Benoit Garret

The following example and explanation are from the book Professional JavaScript for Web Developers 2nd Edition by Nicholas Zakas. This is the answer I was looking for so I thought it would be helpful to add it here.

(function () {
    var name = '';
    Person = function (value) {
        name = value;
    };
    Person.prototype.getName = function () {
        return name;
    };
    Person.prototype.setName = function (value) {
        name = value;
    };
}());
var person1 = new Person('Nate');
console.log(person1.getName()); // Nate
person1.setName('James');
console.log(person1.getName()); // James
person1.name = 'Mark';
console.log(person1.name); // Mark
console.log(person1.getName()); // James
var person2 = new Person('Danielle');
console.log(person1.getName()); // Danielle
console.log(person2.getName()); // Danielle

The Person constructor in this example has access to the private variable name, as do the getName() and setName() methods. Using this pattern, the name variable becomes static and will be used among all instances. This means calling setName() on one instance affects all other instances. Calling setName() or creating a new Person instance sets the name variable to a new value. This causes all instances to return the same value.


looks constructor + prototype (hybrid)
This places the Person object in the global namespace. Not a solution i would recommend.
I dont think this is a true static variable because it is instantiated differently with each new object. A static object should be consistent across all objects inheriting from the parent prototype?
@Ghola The intention here was to explain how to create a static variable. Proper namespacing and avoiding globals is a separate topic which may have added to the complexity of the answer. It's up to the user to determine how to attach the constructor without polluting. If it's good enough for Nicholas Zakas, it's good enough for me.
@lindsaymacvean It's a static variable because the single value is shared across all instances. It's OK for the value to change. If one instance changes the value, all instances will be affected. It's not likely it would be used exactly the same as the example above. Allowing the value to be set during instantiation is just to show it's possible. A more likely use case would be to only have the getter and setter or at least check to make sure it's being set to something other than undefined.
A
Automatico

If you are using the new class syntax then you can now do the following:

class MyClass { static get myStaticVariable() { return "some static variable"; } } console.log(MyClass.myStaticVariable); aMyClass = new MyClass(); console.log(aMyClass.myStaticVariable, "is undefined");

This effectively creates a static variable in JavaScript.


This is useful when building static utility classes!
But now the question is how do you persist a value and allow changes to it with a setter. A closure would be needed or a property on MyClass defined outside of the class construct.
C
COil

About the class introduced by ECMAScript 2015. The other answers are not totally clear.

Here is an example showing how to create a static var staticVar with the ClassName.var synthax:

class MyClass {
    constructor(val) {
        this.instanceVar = val;
        MyClass.staticVar = 10;
    }
}

var class1 = new MyClass(1);
console.log(class1.instanceVar);      // 1
console.log(class1.constructor.staticVar); // 10

// New instance of MyClass with another value
var class2 = new MyClass(3);
console.log(class1.instanceVar);      // 1
console.log(class2.instanceVar);      // 3

To access the static variable we use the .constructor property that returns a reference to the object constructor function that created the class. We can call it on the two created instances:

MyClass.staticVar = 11;
console.log(class1.constructor.staticVar); // 11
console.log(class2.constructor.staticVar); // 11 <-- yes it's static! :)

MyClass.staticVar = 12;
console.log(class1.constructor.staticVar); // 12
console.log(class2.constructor.staticVar); // 12

H
Hemant

If you want to declare static variables for creating constants in your application then I found following as most simplistic approach

ColorConstants = (function()
{
    var obj = {};
    obj.RED = 'red';
    obj.GREEN = 'green';
    obj.BLUE = 'blue';
    obj.ALL = [obj.RED, obj.GREEN, obj.BLUE];
    return obj;
})();

//Example usage.
var redColor = ColorConstants.RED;

f
funroll

There are other similar answers, but none of them quite appealed to me. Here's what I ended up with:

var nextCounter = (function () {
  var counter = 0;
  return function() {
    var temp = counter;
    counter += 1;
    return temp;
  };
})();

D
Dimitris Fasarakis Hilliard

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.


G
GetFree

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

S
Sнаđошƒаӽ

You can create a static variable in JavaScript like this below. Here count is the static variable.

var Person = function(name) {
  this.name = name;
  // first time Person.count is undefined, so it is initialized with 1
  // next time the function is called, the value of count is incremented by 1
  Person.count = Person.count ? Person.count + 1 : 1;
}

var p1 = new Person('User p1');
console.log(p1.constructor.count);   // prints 1
var p2 = new Person('User p2');
console.log(p2.constructor.count);   // prints 2

You can assign values to the static variable using either the Person function, or any of the instances:

// set static variable using instance of Person
p1.constructor.count = 10;         // this change is seen in all the instances of Person
console.log(p2.constructor.count); // prints 10

// set static variable using Person
Person.count = 20;
console.log(p1.constructor.count); // prints 20

This is one of the good approach to declare static variable and access it in JavaScript.
A
Andrew Hare

The closest thing in JavaScript to a static variable is a global variable - this is simply a variable declared outside the scope of a function or object literal:

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

The other thing you could do would be to store global variables inside an object literal like this:

var foo = { bar : 1 }

And then access the variabels like this: foo.bar.


this one helped me to upload multiple files..... var foo = {counter:1}; function moreFiles() { fileName = "File" + foo.counter; foo.counter = foo.counter + 1;
J
JoolzCheat

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
});

L
Luca Reghellin

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);

N
Neeraj Kumar

There's another approach, which solved my requirements after browsing this thread. It depends on exactly what you want to achieve with a "static variable".

The global property sessionStorage or localStorage allows data to be stored for the life of the session, or for an indefinite longer period until explicitly cleared, respectively. This allows data to be shared among all windows, frames, tab panels, popups etc of your page/app and is much more powerful than a simple "static/global variable" in one code segment.

It avoids all hassle with the scope, lifetime, semantics, dynamics etc of top-level global variables, ie Window.myglobal. Don't know how efficient it is, but that's not important for modest amounts of data, accessed at modest rates.

Easily accessed as "sessionStorage.mydata = anything" and retrieved similarly. See "JavaScript: The Definitive Guide, Sixth Edition", David Flanagan, ISBN: 978-0-596-80552-4, Chapter 20, section 20.1. This is easily downloadable as a PDF by simple search, or in your O'Reilly Safaribooks subscription (worth its weight in gold).


j
j D3V

2021 UPDATE

In 2021 you can simply use the static keyword

TC39 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.

Below is a generalized example of what the new way to implement static JavaScript class members looks like

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
}

Example above was taken from the TC39 Repository, Static-Fields

To read more about the implementation of this new JS language feature (CLICK HERE).

To read more about the feature itself, as well as seeing examples that demonstarte the syntax used for static fields (CLICK HERE).


Okay, but to be clear this explicitly adds static class features right? I followed the links and "static variables" are not mentioned. They list static public fields, private methods and private fields. None of which are the same as static variables. So the older answers here are still valid?
@HeathRaftery No, your right, I see what I did. I should have typed "static fields", or even "static class-members", and I wrote "static-variables". You could of edited it, I mean like you didn't have to, but you would have been right if you did.
A
Aran-Fey

In JavaScript variables are static by default. Example:

var x = 0;

function draw() {
    alert(x); //
    x+=1;
}

setInterval(draw, 1000);

The value of x is incremented by 1 every 1000 milliseconds It will print 1,2,3 so forth


That's a different case. Your example is about scopes.
Y
Yash

Function's / classes allows only single constructor for its object scope. Function Hoisting, declarations & expressions

Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. var functionClass = function ( ) { var currentClass = Shape; _inherits(currentClass, superClass); function functionClass() { superClass.call(this); // Linking with SuperClass Constructor. // Instance Variables list. this.id = id; return this; } }(SuperClass)

Closures - closure's copies are function with preserved data.

Each closure's copies are created to a function with their own free values or references, Whenever you use function inside another function, a closure is used. A closure in JavaScript is like maintaining a copy of all the local variables of its parent function by the innerFunctions. function closureFun( args ) { // Local variable that ends up within closure var num = args; num++; return function() { console.log(num); } } var closure1 = closureFun( 5 ); var closure2 = closureFun( 777 ); closure1(); // 5 closure2(); // 777 closure2(); // 778 closure1(); // 6

ES5 Function Classes: uses Object.defineProperty ( O, P, Attributes )

The Object.defineProperty() method defines a new property directly on an object, or modifies an existing property on an object, and returns the object.

Created some methods by using ``, So that every once can understand the function classes easily.

'use strict';
var Shape = function ( superClass ) {
    var currentClass = Shape;
    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Shape(id) { superClass.call(this); // Linking with SuperClass Constructor.
        // Instance Variables list.
        this.id = id;   return this;
    }
    var staticVariablesJOSN = { "parent_S_V" : 777 };
    staticVariable( currentClass, staticVariablesJOSN );

    // Setters, Getters, instanceMethods. [{}, {}];
    var instanceFunctions = [
        {
            key: 'uniqueID',
            get: function get() { return this.id; },
            set: function set(changeVal) { this.id = changeVal; }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Object);

var Rectangle = function ( superClass ) {
    var currentClass = Rectangle;

    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Rectangle(id, width, height) { superClass.call(this, id); // Linking with SuperClass Constructor.

        this.width = width;
        this.height = height;   return this;
    }

    var staticVariablesJOSN = { "_staticVar" : 77777 };
    staticVariable( currentClass, staticVariablesJOSN );

    var staticFunctions = [
        {
            key: 'println',
            value: function println() { console.log('Static Method'); }
        }
    ];
    staticMethods(currentClass, staticFunctions);

    var instanceFunctions = [
        {
            key: 'setStaticVar',
            value: function setStaticVar(staticVal) {
                currentClass.parent_S_V = staticVal;
                console.log('SET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
            }
        }, {
            key: 'getStaticVar',
            value: function getStaticVar() {
                console.log('GET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
                return currentClass.parent_S_V;
            }
        }, {
            key: 'area',
            get: function get() {
                console.log('Area : ', this.width * this.height);
                return this.width * this.height;
                }
        }, {
            key: 'globalValue',
            get: function get() {
                console.log('GET ID : ', currentClass._staticVar);
                return currentClass._staticVar;
            },
            set: function set(value) {
                currentClass._staticVar = value;
                console.log('SET ID : ', currentClass._staticVar);
            }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Shape);

// ===== ES5 Class Conversion Supported Functions =====
function defineProperties(target, props) {
    console.log(target, ' : ', props);
    for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
function staticMethods( currentClass, staticProps ) {
    defineProperties(currentClass, staticProps);
};
function instanceMethods( currentClass, protoProps ) {
    defineProperties(currentClass.prototype, protoProps);
};
function staticVariable( currentClass, staticVariales ) {
    // Get Key Set and get its corresponding value.
    // currentClass.key = value;
    for( var prop in staticVariales ) {
        console.log('Keys : Values');
        if( staticVariales.hasOwnProperty( prop ) ) {
            console.log(prop, ' : ', staticVariales[ prop ] );
            currentClass[ prop ] = staticVariales[ prop ];
        }
    }
};
function _inherits(subClass, superClass) {
    console.log( subClass, ' : extends : ', superClass );
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, 
            { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
    if (superClass)
        Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

Below code snippet is to test about Each instance has their own copy of instance members and common static members.

var objTest = new Rectangle('Yash_777', 8, 7);
console.dir(objTest);

var obj1 = new Rectangle('R_1', 50, 20);
Rectangle.println(); // Static Method
console.log( obj1 );    // Rectangle {id: "R_1", width: 50, height: 20}
obj1.area;              // Area :  1000
obj1.globalValue;       // GET ID :  77777
obj1.globalValue = 88;  // SET ID :  88
obj1.globalValue;       // GET ID :  88  

var obj2 = new Rectangle('R_2', 5, 70);
console.log( obj2 );    // Rectangle {id: "R_2", width: 5, height: 70}
obj2.area;              // Area :  350    
obj2.globalValue;       // GET ID :  88
obj2.globalValue = 999; // SET ID :  999
obj2.globalValue;       // GET ID :  999

console.log('Static Variable Actions.');
obj1.globalValue;        // GET ID :  999

console.log('Parent Class Static variables');
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  777
obj1.setStaticVar(7);   // SET Instance Method Parent Class Static Value :  7
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  7

Static method calls are made directly on the class and are not callable on instances of the class. But you can achieve the calls for static members from inside an instance. Using syntax: this.constructor.staticfunctionName();

class MyClass {
    constructor() {}
    static staticMethod() {
        console.log('Static Method');
    }
}
MyClass.staticVar = 777;

var myInstance = new MyClass();
// calling from instance
myInstance.constructor.staticMethod();
console.log('From Inside Class : ',myInstance.constructor.staticVar);

// calling from class
MyClass.staticMethod();
console.log('Class : ', MyClass.staticVar);

ES6 Classes: ES2015 classes are a simple sugar over the prototype-based OO pattern. Having a single convenient declarative form makes class patterns easier to use, and encourages interoperability. Classes support prototype-based inheritance, super calls, instance and static methods and constructors.

Example: refer my previous post.


v
vkarpov15

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.


B
Bostone

Window level vars are sorta like statics in the sense that you can use direct reference and these are available to all parts of your app


A much better description of such vars is 'global', rather than static.
T
Todd L

Working with MVC websites that use jQuery, I like to make sure AJAX actions within certain event handlers can only be executed once the previous request has completed. I use a "static" jqXHR object variable to achieve this.

Given the following button:

<button type="button" onclick="ajaxAction(this, { url: '/SomeController/SomeAction' })">Action!</button>

I generally use an IIFE like this for my click handler:

var ajaxAction = (function (jqXHR) {
    return function (sender, args) {
        if (!jqXHR || jqXHR.readyState == 0 || jqXHR.readyState == 4) {
            jqXHR = $.ajax({
                url: args.url,
                type: 'POST',
                contentType: 'application/json',
                data: JSON.stringify($(sender).closest('form').serialize()),
                success: function (data) {
                    // Do something here with the data.
                }
            });
        }
    };
})(null);

c
charlie

If you want to use prototype then there is a way

var p = function Person() {
    this.x = 10;
    this.y = 20;
}
p.prototype.counter = 0;
var person1 = new p();
person1.prototype = p.prototype;
console.log(person1.counter);
person1.prototype.counter++;
var person2 = new p();
person2.prototype = p.prototype;
console.log(person2.counter);
console.log(person1.counter);

Doing this you will be able to access the counter variable from any instance and any change in the property will be immediately reflected!!


l
lindsaymacvean

So what I see with the other answers is that they don't address the fundamental architectural requirement of a static attribute in object oriented programming.

Object oriented programming actually has two different styles one is 'class based' (C++, C#, Java etc), the other is 'prototypal' (Javascript). In class based languages a 'static attribute' is supposed to be associated with the class and not the instantiated objects. This concept actually works much more intuitively in a prototypal languages like Javascript because you just assign the attribute as a value of the parent prototype like so.

function MyObject() {};
MyObject.prototype.staticAttribute = "some value";

And access it from every one of the objects that is instantiated from this constructor like so...

var childObject1 = new MyObject(); // Instantiate a child object
var childObject2 = new MyObject(); // Instantiate another child object
console.log(childObject.staticAttribute); // Access the static Attribute from child 1
console.log(childObject.staticAttribute); // Access the static Attribute from child 2

Now if you go ahead and change the MyObject.prototype.staticAttribute the change will cascade down to the child objects that immediately inherit it.

However there are a few 'gotchas' that could significantly undermine the 'static' nature of this attribute, or just leave security vulnerability...

First make sure to hide the constructor from the Global namespace by enclosing it inside another function like the jQuery ready method

 $(document).ready(function () {
    function MyObject() {
        // some constructor instructions
    };
    MyObject.prototype.staticAttribute = "some value";
    var childObject = new MyObject(); // instantiate child object
    console.log(childObject.staticAttribute); // test attribute
});

Second and lastly, even if you do this, the attribute is still editable from any of the other parts of your own script, so it could be the case that a bug in your code writes over the attribute on one of the child objects and detaches it from the parent prototype, so if you change the parent attribute it will no longer cascade and change the static attribute for the child object. See this jsfiddle. In different scenarios we could either Object.freeze(obj) to stop any changes to the child object, or we could set up a setter and getter method in the constructor and access a closure, both of these have associated complexities.

It seems to me that there is not a perfect analogue between the class-based idea of a 'static attribute' and this Javascript implementation. So I think it might be better in the long run to use a different code pattern that is more Javascript friendly. Such as a central datastore or cache or even a dedicated helper object to hold all the necessary static variables.


d
danielson317

I didn't see this idea in any of the answers so just adding it to the list. If it's a duplicate just let me know and i'll delete it and upvote the other.

I created a sort of super global in my website. Since I have several js files that are loaded on every page load and dozens of other js files that are only loaded on some pages I put all of the "global" function into a single global variable.

At the top of my first included "global" files is the declaration

var cgf = {}; // Custom global functions.

Then I delcare several global helper functions

cgf.formBehaviors = function()
{
    // My form behaviors that get attached in every page load.
}

Then if I need a static variable I just store it outside scope such as outside the document ready or outside the behavior attachment. (I use jquery but it should work in javascript)

cgf.first = true;
$.on('click', '.my-button', function()
{
    // Don't allow the user to press the submit twice.
    if (cgf.first)
    {
        // first time behavior. such as submit
    }
    cgf.first = false;
}

This of course is a global not a static but as it is reinitialized on every page load it accomplishes the same purpose.


d
drneel

In JavaScript, there is no term or keyword static, but we can put such data directly into function object (like in any other object).

function f() {
    f.count = ++f.count || 1 // f.count is undefined at first
    alert("Call No " + f.count)
}

f(); // Call No 1

f(); // Call No 2

M
Martin Wantke

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

This is not a valid solution: the _privateStatic is actually created as a global object (i.e. as member of window when used in a browser). So while it is static, it is not private and does not belong to Class.