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


当前回答

所以我从其他答案中看到的是,它们没有解决面向对象编程中静态属性的基本架构要求。

面向对象编程实际上有两种不同的风格,一种是基于类的(C++、C#、Java等),另一种是原型的(Javascript)。在基于类的语言中,“静态属性”应该与类关联,而不是与实例化对象关联。这个概念实际上在Javascript这样的原型语言中更为直观,因为您只需将属性指定为父原型的值即可。

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

并从从该构造函数实例化的每个对象访问它,就像这样。。。

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

现在,如果您继续更改MyObject.prototype.staticAttribute,则更改将级联到立即继承它的子对象。

然而,有一些“陷阱”可能会严重破坏此属性的“静态”特性,或者只留下安全漏洞。。。

首先,确保通过将构造函数封装在另一个函数(如jQuery ready方法)中,从全局命名空间中隐藏构造函数

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

第二,也是最后一点,即使您这样做,该属性仍然可以从您自己的脚本的任何其他部分进行编辑,因此可能是代码中的错误覆盖了某个子对象的属性,并将其从父原型分离,因此如果您更改父属性,它将不再级联并更改子对象的静态属性。看看这个jsfiddle。在不同的场景中,我们可以使用Object.freeze(obj)来停止对子对象的任何更改,也可以在构造函数中设置setter和getter方法并访问闭包,这两者都具有相关的复杂性。

在我看来,“静态属性”的基于类的思想和这个Javascript实现之间似乎没有完美的相似之处。因此,我认为从长远来看,使用一种对Javascript更友好的不同代码模式可能会更好。比如一个中央数据存储或缓存,甚至一个专用的帮助对象来保存所有必要的静态变量。

其他回答

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

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

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

var foo = { bar : 1 }

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

如果您正在使用新的类语法,那么现在可以执行以下操作:

类MyClass{静态获取myStaticVariable(){返回“一些静态变量”;}}console.log(MyClass.myStaticVariable);aMyClass=新建MyClass();console.log(aMyClass.myStaticVariable,“未定义”);

这有效地在JavaScript中创建了一个静态变量。

窗口级变量有点像静态变量,因为您可以使用直接引用,这些变量可用于应用程序的所有部分

您可以使用static关键字在JavaScript中定义静态函数:

class MyClass {
  static myStaticFunction() {
    return 42;
  }
}

MyClass.myStaticFunction(); // 42

在撰写本文时,您仍然无法在类中定义静态财产(函数除外)。静态财产仍然是第三阶段的建议,这意味着它们还不是JavaScript的一部分。然而,没有什么可以阻止您像分配给任何其他对象一样简单地分配给类:

class MyClass {}

MyClass.myStaticProperty = 42;

MyClass.myStaticProperty; // 42

最后一点:小心使用带有继承的静态对象-所有继承的类共享对象的相同副本。

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

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