如何在Javascript中创建静态变量?
当前回答
您可以利用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。
还有另一种方法,它解决了我浏览这个线程后的需求。这完全取决于您想要使用“静态变量”实现什么。
全局属性sessionStorage或localStorage允许在会话的生命周期内存储数据,或在明确清除之前存储不确定的更长时间。这允许在页面/应用程序的所有窗口、框架、选项卡面板、弹出窗口等之间共享数据,并且比一个代码段中的简单“静态/全局变量”功能强大得多。
它避免了顶级全局变量(如Window.myglobal)的范围、生存期、语义、动态等方面的所有麻烦。不知道它有多高效,但这对于以适度速度访问的少量数据来说并不重要。
轻松访问为“sessionStorage.mydata=anything”,并以类似方式检索。看见“JavaScript:最终指南,第六版”,David Flanagan,ISBN:978-0-596-80552-4,第20章,第20.1节。通过简单的搜索,或在O’Reilly Safaribooks订阅(价值黄金)中,可以轻松下载为PDF格式。
在Javascript中有4种模拟函数局部静态变量的方法。
方法1:使用函数对象财产(在旧浏览器中受支持)
function someFunc1(){
if( !('staticVar' in someFunc1) )
someFunc1.staticVar = 0 ;
alert(++someFunc1.staticVar) ;
}
someFunc1() ; //prints 1
someFunc1() ; //prints 2
someFunc1() ; //prints 3
方法2:使用闭包,变体1(旧浏览器支持)
var someFunc2 = (function(){
var staticVar = 0 ;
return function(){
alert(++staticVar) ;
}
})()
someFunc2() ; //prints 1
someFunc2() ; //prints 2
someFunc2() ; //prints 3
方法3:使用闭包,变体2(在旧浏览器中也支持)
var someFunc3 ;
with({staticVar:0})
var someFunc3 = function(){
alert(++staticVar) ;
}
someFunc3() ; //prints 1
someFunc3() ; //prints 2
someFunc3() ; //prints 3
方法4:使用闭包,变体3(需要支持EcmaScript 2015)
{
let staticVar = 0 ;
function someFunc4(){
alert(++staticVar) ;
}
}
someFunc4() ; //prints 1
someFunc4() ; //prints 2
someFunc4() ; //prints 3
严格模式的方法4
'use strict'
{
let staticVar = 0 ;
var someFunc4 = function(){
alert(++staticVar) ;
} ;
}
someFunc4() ; //prints 1
someFunc4() ; //prints 2
someFunc4() ; //prints 3
关于ECMAScript 2015引入的类。其他答案并不完全清楚。
下面是一个示例,演示如何使用ClassName.var synthax创建静态var-staticVar:
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
为了访问静态变量,我们使用.constructor属性,该属性返回对创建类的对象构造函数的引用。我们可以在两个创建的实例上调用它:
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
对于私有静态变量,我是这样发现的:
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