如何在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将函数视为一级对象,因此作为一个对象,可以将财产分配给函数。

UPDATE:ES6引入了通过class关键字声明类的能力。它是现有的基于原型的继承的语法糖。

static关键字允许您轻松定义类中的静态财产或方法。

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

类MyClass{//类构造函数,等效于//构造函数的函数体构造器(){const privateVariable=“private value”;//构造函数范围内的私有变量this.publicVariable='公共值';//公共财产this.privilegedMethod=函数(){//具有构造函数范围变量访问权限的公共方法console.log(privateVariable);};}//原型方法:publicMethod(){console.log(this.publicVariable);}//所有实例共享的静态财产static staticProperty='静态值';静态静态方法(){console.log(this.staticProperty);}}//我们可以将财产添加到类原型中MyClass.prototype.additionalMethod=函数(){console.log(this.publicVariable);};var myInstance=新建MyClass();myInstance.publicMethod();//“公共价值”myInstance.additionalMethod();//“公共价值”myInstance.privilegedMethod();//“私人价值”MyClass.staticMethod();//“静态值”

其他回答

我通常使用这种方法有两个主要原因:

如果我想存储函数的本地值,我会使用“local.x”、“local.y”、“local.TempData”等。。。!

如果我想存储函数的静态值,我会使用“static.o”、“static.Info”、“static.count”等。。。!

[Update2]:方法相同,但使用IIFE方法!

[Update1]:通过预编辑脚本自动创建函数的“静态”和“本地”对象!

除其他内容外,目前还有一个关于ECMA提案的草案(第2阶段提案),它在类中引入了静态公共字段。(考虑了私人领域)

使用提案中的示例,建议的静态语法如下所示:

class CustomDate {
  // ...
  static epoch = new CustomDate(0);
}

并等同于其他人强调的以下内容:

class CustomDate {
  // ...
}
CustomDate.epoch = new CustomDate(0);

然后,您可以通过CustomDate.epoch访问它。

您可以在提案静态类特性中跟踪新提案。


目前,babel通过您可以使用的转换类财产插件支持此功能。此外,尽管仍在进行中,V8正在实现它。

以下示例和解释来自Nicholas Zakas的《Web开发人员专业JavaScript第二版》一书。这是我一直在寻找的答案,所以我认为在这里添加它会很有帮助。

(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

本例中的Person构造函数可以访问私有变量名,getName()和setName()方法也是如此。使用此模式,name变量将变为静态,并将在所有实例中使用。这意味着在一个实例上调用setName()会影响所有其他实例。调用setName()或创建新的Person实例会将name变量设置为新值。这会导致所有实例返回相同的值。

您可以利用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.

这会得到相同的结果——只是这次返回的是递增的值,而不是显示。

JavaScript中最接近静态变量的是一个全局变量——这只是一个在函数或对象文本范围之外声明的变量:

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

您可以做的另一件事是将全局变量存储在对象文本中,如下所示:

var foo = { bar : 1 }

然后像这样访问变量:foo.bar。