协慌网

登录 贡献 社区

JavaScript 中的静态变量

如何在 Javascript 中创建静态变量?

答案

如果您来自基于类的静态类型的面向对象的语言(例如 Java,C ++ 或 C#) ,那么我假设您正在尝试创建与 “类型” 相关但与实例无关的变量或方法。

使用带有构造函数的 “经典” 方法的示例可能会帮助您了解基本的 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是在 MyClass 对象(它是一个函数)中定义的,与创建的实例无关,JavaScript 将函数视为一等对象,因此,作为对象,您可以为函数分配属性。

更新: ES6 引入了class关键字声明类的功能。它是对现有基于原型的继承的语法糖。

static关键字使您可以轻松地在类中定义静态属性或方法。

让我们看一下上面用 ES6 类实现的示例:

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"

您可能会利用 JS 函数也是对象这一事实,这意味着它们可以具有属性。

例如,引用(现在已消失)文章 “ 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);
}

如果您多次调用该函数,则会看到计数器在增加。

与用全局变量污染全局名称空间相比,这可能是一个更好的解决方案。


这是基于闭包的另一种可能的解决方案: 欺骗在 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.

可以得到相同的结果 - 这次不同的是,返回的是增量值,而不是显示出来。

您可以通过 IIFE(立即调用的函数表达式)执行此操作:

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

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

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