javascript static - JavaScript中的靜態變量

15 Answers

如果您來自基於類的靜態類型的面向對象語言(如Java,C ++或C#),我假設您正在嘗試創建與“類型”關聯但不是實例的變量或方法。

使用“經典”方法和構造函數的例子可能可以幫助你理解基本的OO JavaScript的概念:

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

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

  this.privilegedMethod = function () {  // Public Method

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

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

var myInstance = new MyClass();

staticProperty屬性在MyClass對staticProperty中定義(這是一個函數),並且與其創建的實例無關,JavaScript將函數視為一級對象 ,因此作為對象,您可以將屬性分配給函數。

variable es6



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

    return function () {
        return i++;

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

function Person(){
  if(Person.count == undefined){
    Person.count = 1;
    Person.count ++;

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


ECMAScript 6中 ,您可以使用static關鍵字創建靜態函數:

class Foo {

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


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

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

ES6類不會為靜態引入任何新的語義。 你可以像這樣在ES5中做同樣的事情:

var Foo = function() {} = function() {
    return 'I am static.'
} // returns 'I am static.'

var foo = new Foo() // throws TypeError



    class MyClass {
      static get myStaticVariable() {
        return "some static variable";


    aMyClass = new MyClass();
    console.log(aMyClass.myStaticVariable, "is undefined");


還有其他類似的答案,但沒有一個對我很有吸引力。 這就是我最終的結果:

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


var my_id = 123;


Object.defineProperty(window, 'my_id', {
    get: function() {
            return 123;
    configurable : false,
    enumerable : false

JavaScript中最接近靜態變量的是一個全局變量 - 這僅僅是一個在函數或對象文本範圍外聲明的變量:

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;


var foo = { bar : 1 }



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(){

  Test.test_var = 'protected';//protected variable: accessible only form inherited methods (prototype) AND child/inherited classes

};//end constructor

Test.test_var = "static";//static variable: accessible everywhere (I mean, even out of prototype, see domready below)

Test.prototype = {


};//end prototype/class

//for example:
$(document).ready(function() {


 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


#this is coffeescript
class Test
 @prop = "static"

 constructor:(prop) ->
   @prop = prop

 t = new Test('inst_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;

    return Test;


  t = new Test('inst_prop');



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

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 .

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

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.

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.

For private static variables, I found this way:

function Class()

Class.prototype = new function()
    _privateStatic = 1;
    this.get = function() { return _privateStatic; } = function() { _privateStatic++; }

var o1 = new Class();
var o2 = new Class();;

console.log(o2.get()); // 2