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


当前回答

我没有在任何答案中看到这个想法,所以只是将其添加到列表中。如果是重复的,请告诉我,我会删除它并对另一个进行投票。

我在我的网站上创建了一种超级全球化。由于每次页面加载时都会加载几个js文件,而其他几十个js文件只加载在一些页面上,所以我将所有“全局”函数都放在一个全局变量中。

在我第一个包含的“全局”文件的顶部是声明

var cgf = {}; // Custom global functions.

然后我删除了几个全局助手函数

cgf.formBehaviors = function()
{
    // My form behaviors that get attached in every page load.
}

然后,如果我需要一个静态变量,我只需将其存储在范围之外,例如文档就绪或行为附件之外。(我使用jquery,但它应该在javascript中工作)

cgf.first = true;
$.on('click', '.my-button', function()
{
    // Don't allow the user to press the submit twice.
    if (cgf.first)
    {
        // first time behavior. such as submit
    }
    cgf.first = false;
}

这当然是一个全局的,而不是静态的,但由于它在每次加载页面时都会重新初始化,所以它可以达到相同的目的。

其他回答

如果您来自基于类的静态类型的面向对象语言(如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();//“静态值”

要在这里浓缩所有的类概念,请测试:

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(){
    console.log(test_var);
  }();

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

  this.init();
};//end constructor

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

Test.prototype = {

 init:function(){
   console.log('in',Test.test_var);
 }

};//end prototype/class


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

 console.log('out',Test.test_var);

 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
 #static
 @prop = "static"

 #instance
 constructor:(prop) ->
   @prop = prop
   console.log(@prop)

 t = new Test('inst_prop');

 console.log(Test.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;
     console.log(this.prop);
    }

    return Test;

  })();

  t = new Test('inst_prop');

  console.log(Test.prop);

还有另一种方法,它解决了我浏览这个线程后的需求。这完全取决于您想要使用“静态变量”实现什么。

全局属性sessionStorage或localStorage允许在会话的生命周期内存储数据,或在明确清除之前存储不确定的更长时间。这允许在页面/应用程序的所有窗口、框架、选项卡面板、弹出窗口等之间共享数据,并且比一个代码段中的简单“静态/全局变量”功能强大得多。

它避免了顶级全局变量(如Window.myglobal)的范围、生存期、语义、动态等方面的所有麻烦。不知道它有多高效,但这对于以适度速度访问的少量数据来说并不重要。

轻松访问为“sessionStorage.mydata=anything”,并以类似方式检索。看见“JavaScript:最终指南,第六版”,David Flanagan,ISBN:978-0-596-80552-4,第20章,第20.1节。通过简单的搜索,或在O’Reilly Safaribooks订阅(价值黄金)中,可以轻松下载为PDF格式。

更新答案:

在ECMAScript 6中,可以使用static关键字创建静态函数:

class Foo {

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

}

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

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

ES6类没有为静态引入任何新的语义。您可以在ES5中这样做:

//constructor
var Foo = function() {}

Foo.bar = function() {
    return 'I am static.'
}

Foo.bar() // returns 'I am static.'

var foo = new Foo()
foo.bar() // throws TypeError

您可以指定Foo的属性,因为在JavaScript中,函数是对象。

在使用jQuery的MVC网站中,我希望确保某些事件处理程序中的AJAX操作只能在前一个请求完成后执行。我使用一个“静态”jqXHR对象变量来实现这一点。

按下以下按钮:

<button type="button" onclick="ajaxAction(this, { url: '/SomeController/SomeAction' })">Action!</button>

我通常使用这样的IIFE作为点击处理程序:

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