JavaScript中的静态变量

时间:2009-10-08 04:31:25

标签: javascript variables static closures

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

43 个答案:

答案 0 :(得分:821)

如果您来自基于类的,静态类型的面向对象语言(如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将函数视为first-class objects,因此作为对象,您可以将属性分配给一个功能。

答案 1 :(得分:519)

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

例如,引用(现已消失的)文章Static variables in 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);
}

如果您多次调用该函数,您将看到计数器正在递增。

这可能是一个比使用全局变量来规划全局命名空间更好的解决方案。


这是另一种可能的解决方案,基于闭包:Trick to use static variables in 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.

这会给你带来相同的结果 - 除了这次,增加的值被返回,而不是显示。

答案 2 :(得分:84)

你通过IIFE(立即调用函数表达式)来实现:

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

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

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

答案 3 :(得分:39)

你可以使用arguments.callee存储“静态”变量(这在匿名函数中也很有用):

function () {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 1;
  arguments.callee.myStaticVar++;
  alert(arguments.callee.myStaticVar);
}

答案 4 :(得分:28)

function Person(){
  if(Person.count == undefined){
    Person.count = 1;
  }
  else{
    Person.count ++;
  }
  console.log(Person.count);
}

var p1 = new Person();
var p2 = new Person();
var p3 = new Person();

答案 5 :(得分:28)

我已经看到了几个相似的答案,但我想提及this post最能说明这一点,所以我想与你分享。

这里有一些从中获取的代码,我已经修改了这个代码以获得一个完整的示例,希望它能为社区带来好处,因为它可以用作类的设计模板。

它还回答了你的问题:

function Podcast() {

    // private variables
    var _somePrivateVariable = 123;

    // object properties (read/write)
    this.title = 'Astronomy Cast';
    this.description = 'A fact-based journey through the galaxy.';
    this.link = 'http://www.astronomycast.com';

    // for read access to _somePrivateVariable via immutableProp 
    this.immutableProp = function() {
        return _somePrivateVariable;
    }

    // object function
    this.toString = function() {
       return 'Title: ' + this.title;
    }
};

// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
    console.log('Downloading ' + podcast + ' ...');
};

鉴于该示例,您可以按如下方式访问静态属性/功能

// access static properties/functions
Podcast.FILE_EXTENSION;                // 'mp3'
Podcast.download('Astronomy cast');    // 'Downloading Astronomy cast ...'

对象属性/功能简单如下:

// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString());       // Title: The Simpsons
console.log(podcast.immutableProp());  // 123

注意在podcast.immutableProp()中,我们有一个 closure对_somePrivateVariable的引用保留在函数内。

您甚至可以定义 getter和setter 。看一下这段代码片段(其中d是您想要声明属性的对象原型,y是一个在构造函数外部不可见的私有变量):

// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
    get: function() {return this.getFullYear() },
    set: function(y) { this.setFullYear(y) }
});

它通过d.yearget函数定义属性set - 如果您没有指定set,那么该属性是只读的,不能是修改(请注意,如果您尝试设置它,将不会收到错误,但它没有任何效果)。每个属性都具有属性writableconfigurable(允许在声明后更改)和enumerable(允许将其用作枚举器),默认为false。您可以在第3个参数中通过defineProperty设置它们,例如enumerable: true

这种语法也有效:

// getters and setters - alternative syntax
var obj = { a: 7, 
            get b() {return this.a + 1;}, 
            set c(x) {this.a = x / 2}
        };

定义了可读/可写属性a,只读属性b和只写属性c,通过它可以访问属性a

<强>用法:

console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21

注意:

为避免意外行为,如果您忘记了new关键字,我建议您将以下内容添加到Podcast函数中:

// instantiation helper
function Podcast() {
    if(false === (this instanceof Podcast)) {
        return new Podcast();
    }
// [... same as above ...]
};

现在,以下两个实例都将按预期工作:

var podcast = new Podcast(); // normal usage, still allowed
var podcast = Podcast();     // you can omit the new keyword because of the helper

&#39; new&#39; statement创建一个新对象并复制所有属性和方法,即

var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"

另请注意,在某些情况下,在构造函数return中使用Podcast语句返回保护类内部依赖的函数的自定义对象会很有用在哪,但需要暴露。这将在文章系列的第2章(对象)中进一步解释。

您可以说ab继承自Podcast。现在,如果您想在ab实例化之后向Podcast添加适用于所有这些方法的方法,该怎么办?在这种情况下,请使用.prototype,如下所示:

Podcast.prototype.titleAndLink = function() {
    return this.title + " [" + this.link + "]";
};

现在再次致电ab

console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"

您可以找到有关原型here的更多详细信息。如果你想做更多的继承,我建议你研究this


上面提到的article series 强烈推荐要阅读,它们还包括以下主题:

  1. 功能
  2. 物件
  3. 原型
  4. 在构造函数上实施新功能
  5. 起重
  6. 自动分号插入
  7. 静态属性和方法
  8. 注意 automatic semicolon insertion &#34;功能&#34; JavaScript(如6.中所述)经常导致代码中出现奇怪的问题。因此,我宁愿将其视为一个错误,而不是一个功能。

    如果您想阅读更多内容,here是一篇非常有趣的 MSDN文章,有关这些主题的内容,其中一些内容提供了更多详细信息。

    有趣的阅读(也涵盖上述主题)是来自MDN JavaScript Guide的文章:

    如果您想知道如何在JavaScript中模拟c#out参数(例如在DateTime.TryParse(str, out result)中),您可以找到 sample code here.


    那些使用IE 的人(除非您使用 F12 打开开发人员工具,否则没有JavaScript控制台,并打开控制台选项卡)可能会发现以下代码段有用。它允许您使用上面示例中使用的console.log(msg);。只需在Podcast函数之前插入它。

    为方便起见,请在上面的代码中输入一个完整的单个代码段:

    &#13;
    &#13;
    let console = { log: function(msg) {  
      let canvas = document.getElementById("log"), br = canvas.innerHTML==="" ? "" : "<br/>";
      canvas.innerHTML += (br + (msg || "").toString());
    }};
    
    console.log('For details, see the explaining text');
    
    function Podcast() {
    
      // with this, you can instantiate without new (see description in text)
      if (false === (this instanceof Podcast)) {
        return new Podcast();
      }
    
      // private variables
      var _somePrivateVariable = 123;
    
      // object properties
      this.title = 'Astronomy Cast';
      this.description = 'A fact-based journey through the galaxy.';
      this.link = 'http://www.astronomycast.com';
    
      this.immutableProp = function() {
        return _somePrivateVariable;
      }
    
      // object function
      this.toString = function() {
        return 'Title: ' + this.title;
      }
    };
    
    // static property
    Podcast.FILE_EXTENSION = 'mp3';
    // static function
    Podcast.download = function(podcast) {
      console.log('Downloading ' + podcast + ' ...');
    };
    
    
    // access static properties/functions
    Podcast.FILE_EXTENSION; // 'mp3'
    Podcast.download('Astronomy cast'); // 'Downloading Astronomy cast ...'
    
    // access object properties/functions
    var podcast = new Podcast();
    podcast.title = 'The Simpsons';
    console.log(podcast.toString()); // Title: The Simpsons
    console.log(podcast.immutableProp()); // 123
    
    // getters and setters
    var d = Date.prototype;
    Object.defineProperty(d, "year", {
      get: function() {
        return this.getFullYear()
      },
      set: function(y) {
        this.setFullYear(y)
      }
    });
    
    // getters and setters - alternative syntax
    var obj = {
      a: 7,
      get b() {
        return this.a + 1;
      },
      set c(x) {
        this.a = x / 2
      }
    };
    
    // usage:
    console.log(obj.a); console.log(obj.b); // output: 7, 8
    obj.c=40;
    console.log(obj.a); console.log(obj.b); // output: 20, 21
    
    var a=new Podcast();
    var b=new Podcast();
    a.title="a"; b.title="An "+b.title;
    console.log(a.title); // "a"
    console.log(b.title); // "An Astronomy Cast"
    
    Podcast.prototype.titleAndLink = function() {
        return this.title + " [" + this.link + "]";
    };
        
    console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
    console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
    &#13;
    <div id="log"></div>
    &#13;
    &#13;
    &#13;


    注意:

    • 有关JavaScript编程的一些好的提示,提示和建议,您可以找到 here (JavaScript best practices) there ('var' versus 'let') 。此建议还推荐 about implicit typecasts (coercion)

    • 使用类并将其编译为JavaScript的便捷方法是 TypeScript。 Here is a playground您可以在其中找到一些示例,说明它是如何工作的。 即使您目前还没有使用TypeScript,也可以查看,因为您可以在并排视图中将TypeScript与JavaScript结果进行比较。大多数示例都很简单,但也有一个Raytracer示例,您可以立即尝试。 我建议特别关注&#34;使用类&#34;,&#34;使用继承&#34;和#34;使用泛型&#34;通过在组合框中选择它们的示例 - 这些是可以立即在JavaScript中使用的漂亮模板。 Typescript与Angular.

    • 一起使用
    • 为了在JavaScript中实现局部变量,函数等的封装,我建议使用如下的模式(JQuery使用相同的技术):

    &#13;
    &#13;
    <html>
    <head></head>
    <body><script>
        'use strict';
        // module pattern (self invoked function)
        const myModule = (function(context) { 
        // to allow replacement of the function, use 'var' otherwise keep 'const'
    
          // put variables and function with local module scope here:
          var print = function(str) {
            if (str !== undefined) context.document.write(str);
            context.document.write("<br/><br/>");
            return;
          }
          // ... more variables ...
    
          // main method
          var _main = function(title) {
    
            if (title !== undefined) print(title);
            print("<b>last modified:&nbsp;</b>" + context.document.lastModified + "<br/>");        
            // ... more code ...
          }
    
          // public methods
          return {
            Main: _main
            // ... more public methods, properties ...
          };
    
        })(this);
    
        // use module
        myModule.Main("<b>Module demo</b>");
    </script></body>
    </html>
    &#13;
    &#13;
    &#13;

    当然,您可以 - 并且应该 - 将脚本代码放在单独的*.js文件中;这只是内联编写以保持示例简短。

答案 6 :(得分:24)

更新回答:

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函数是对象。

答案 7 :(得分:16)

以下示例和说明来自Nicholas Zakas的“专业JavaScript for Web Developers 2nd Edition”一书。这是我正在寻找的答案,所以我认为在这里添加它会很有帮助。

(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变量设置为新值。这会导致所有实例返回相同的值。

答案 8 :(得分:10)

如果您使用新的class syntax,那么现在可以执行以下操作:

&#13;
&#13;
    class MyClass {
      static get myStaticVariable() {
        return "some static variable";
      }
    }

    console.log(MyClass.myStaticVariable);

    aMyClass = new MyClass();
    console.log(aMyClass.myStaticVariable, "is undefined");
&#13;
&#13;
&#13;

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

答案 9 :(得分:8)

关于ECMAScript 2015引入的class。其他答案并不完全清楚。

以下示例说明如何使用staticVar创建静态变量ClassNamevar synthax:

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

答案 10 :(得分:8)

如果你想在你的应用程序中声明用于创建常量的静态变量,那么我发现以下是最简单的方法

ColorConstants = (function()
{
    var obj = {};
    obj.RED = 'red';
    obj.GREEN = 'green';
    obj.BLUE = 'blue';
    obj.ALL = [obj.RED, obj.GREEN, obj.BLUE];
    return obj;
})();

//Example usage.
var redColor = ColorConstants.RED;

答案 11 :(得分:6)

您可以在JavaScript中创建一个静态变量,如下所示。这里count是静态变量。

var Person = function(name) {
  this.name = name;
  // first time Person.count is undefined, so it is initialized with 1
  // next time the function is called, the value of count is incremented by 1
  Person.count = Person.count ? Person.count + 1 : 1;
}

var p1 = new Person('User p1');
console.log(p1.constructor.count);   // prints 1
var p2 = new Person('User p2');
console.log(p2.constructor.count);   // prints 2

您可以使用Person函数或任何实例为静态变量赋值:

// set static variable using instance of Person
p1.constructor.count = 10;         // this change is seen in all the instances of Person
console.log(p2.constructor.count); // prints 10

// set static variable using Person
Person.count = 20;
console.log(p1.constructor.count); // prints 20

答案 12 :(得分:6)

还有其他类似的答案,但没有一个对我很有吸引力。这就是我最终得到的结果:

var nextCounter = (function () {
  var counter = 0;
  return function() {
    var temp = counter;
    counter += 1;
    return temp;
  };
})();

答案 13 :(得分:5)

默认情况下,JavaScript变量静态实施例

patchValues() {
  const control = <FormArray>this.resumeForm.controls['social_profiles'];
  this.data.Social_profiles.forEach(x => { // iterate the array
     control.push(this.patch(x.network, x.url)) // push values
  });
}

patch(network, url) {
  return this.fb.group({
    network: [network],
    url: [url]
  });
}

x的值每1000毫秒增加1 它会打印1,2,3所以

答案 14 :(得分:5)

如果你想创建一个全局静态变量:

var my_id = 123;

用以下代码替换变量:

Object.defineProperty(window, 'my_id', {
    get: function() {
            return 123;
        },
    configurable : false,
    enumerable : false
});

答案 15 :(得分:4)

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

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

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

var foo = { bar : 1 }

然后按以下方式访问变量:foo.bar

答案 16 :(得分:4)

还有另一种方法,在浏览此帖子后解决了我的要求。它取决于您想要通过“静态变量”实现的目标。

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

它避免了对顶级全局变量(即Window.myglobal)的范围,生命周期,语义,动态等的所有麻烦。不知道它的效率如何,但这对于适度数量的适量数据并不重要。

轻松访问“sessionStorage.mydata = anything”并以类似方式检索。看到 “JavaScript:The Definitive Guide,Sixth Edition”,David Flanagan,ISBN:978-0-596-80552-4,第20章,第20.1节。这可以通过简单的搜索或者在你的O'Reilly Safaribooks订阅中轻松下载为PDF(值得以黄金计算)。

答案 17 :(得分:4)

要在此处压缩所有类概念,请测试:

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

那么,另一种看待这些事情的最佳实践的方法是看看coffeescript如何翻译这些概念。

#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);

答案 18 :(得分:3)

除了其他内容之外,目前stage-2 proposal上的草稿(ECMA Proposals)在课程中引入了static 公共字段。 (private fields were considered

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

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

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

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

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

您可以在proposal-static-class-features中跟踪新提案。

目前,babel使用您可以使用的transform class properties插件支持此功能。此外,虽然仍在进行中,V8 is implementing it

答案 19 :(得分:1)

摘要:

ES6 / ES 2015中,引入了class关键字和伴随的static关键字。请记住,这是javavscript所体现的原型继承模型的语法糖。 static关键字的工作方式如下:

class Dog {

  static bark () {console.log('woof');}
  // classes are function objects under the hood
  // bark method is located on the Dog function object
  
  makeSound () { console.log('bark'); }
  // makeSound is located on the Dog.prototype object

}

在chrome devtools中,我们可以很好地将其可视化:

static variables javascript

现在我们已经创建了一个static函数,可以通过ClassName.method()来执行

答案 20 :(得分:1)

Function's / classes只允许单个构造函数用于其对象作用域。 Function Hoisting, declarations & expressions

  
      
  • 使用Function构造函数创建的函数不会为其创建上下文创建闭包;它们总是在全球范围内创建。

      var functionClass = function ( ) {
            var currentClass = Shape;
            _inherits(currentClass, superClass);
            function functionClass() { superClass.call(this); // Linking with SuperClass Constructor.
                // Instance Variables list.
                this.id = id;   return this;
            }
        }(SuperClass)
    
  •   

Closures - closure的副本是保存数据的函数。

  
      
  • 每个闭包的副本都是使用自己的自由值或引用创建的。只要在另一个函数中使用函数,就会使用闭包。
  •   
  • JavaScript中的闭包就像是通过innerFunctions维护其父函数的所有局部变量的副本。

      function closureFun( args ) {
            // Local variable that ends up within closure
            var num = args;
            num++;
            return function() { console.log(num); }
        }
        var closure1 = closureFun( 5 );
        var closure2 = closureFun( 777 );
        closure1(); // 5
        closure2(); // 777
        closure2(); // 778
        closure1(); // 6
    
  •   

ES5功能类:使用Object.defineProperty ( O, P, Attributes )

  

Object.defineProperty()方法直接在对象上定义新属性,或修改对象上的现有属性,并返回该对象。

使用``创建了一些方法,这样每个人都可以轻松理解函数类。

'use strict';
var Shape = function ( superClass ) {
    var currentClass = Shape;
    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Shape(id) { superClass.call(this); // Linking with SuperClass Constructor.
        // Instance Variables list.
        this.id = id;   return this;
    }
    var staticVariablesJOSN = { "parent_S_V" : 777 };
    staticVariable( currentClass, staticVariablesJOSN );

    // Setters, Getters, instanceMethods. [{}, {}];
    var instanceFunctions = [
        {
            key: 'uniqueID',
            get: function get() { return this.id; },
            set: function set(changeVal) { this.id = changeVal; }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Object);

var Rectangle = function ( superClass ) {
    var currentClass = Rectangle;

    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Rectangle(id, width, height) { superClass.call(this, id); // Linking with SuperClass Constructor.

        this.width = width;
        this.height = height;   return this;
    }

    var staticVariablesJOSN = { "_staticVar" : 77777 };
    staticVariable( currentClass, staticVariablesJOSN );

    var staticFunctions = [
        {
            key: 'println',
            value: function println() { console.log('Static Method'); }
        }
    ];
    staticMethods(currentClass, staticFunctions);

    var instanceFunctions = [
        {
            key: 'setStaticVar',
            value: function setStaticVar(staticVal) {
                currentClass.parent_S_V = staticVal;
                console.log('SET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
            }
        }, {
            key: 'getStaticVar',
            value: function getStaticVar() {
                console.log('GET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
                return currentClass.parent_S_V;
            }
        }, {
            key: 'area',
            get: function get() {
                console.log('Area : ', this.width * this.height);
                return this.width * this.height;
                }
        }, {
            key: 'globalValue',
            get: function get() {
                console.log('GET ID : ', currentClass._staticVar);
                return currentClass._staticVar;
            },
            set: function set(value) {
                currentClass._staticVar = value;
                console.log('SET ID : ', currentClass._staticVar);
            }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Shape);

// ===== ES5 Class Conversion Supported Functions =====
function defineProperties(target, props) {
    console.log(target, ' : ', props);
    for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
function staticMethods( currentClass, staticProps ) {
    defineProperties(currentClass, staticProps);
};
function instanceMethods( currentClass, protoProps ) {
    defineProperties(currentClass.prototype, protoProps);
};
function staticVariable( currentClass, staticVariales ) {
    // Get Key Set and get its corresponding value.
    // currentClass.key = value;
    for( var prop in staticVariales ) {
        console.log('Keys : Values');
        if( staticVariales.hasOwnProperty( prop ) ) {
            console.log(prop, ' : ', staticVariales[ prop ] );
            currentClass[ prop ] = staticVariales[ prop ];
        }
    }
};
function _inherits(subClass, superClass) {
    console.log( subClass, ' : extends : ', superClass );
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, 
            { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
    if (superClass)
        Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

下面的代码片段是测试每个实例都有自己的实例成员和普通静态成员的副本。

var objTest = new Rectangle('Yash_777', 8, 7);
console.dir(objTest);

var obj1 = new Rectangle('R_1', 50, 20);
Rectangle.println(); // Static Method
console.log( obj1 );    // Rectangle {id: "R_1", width: 50, height: 20}
obj1.area;              // Area :  1000
obj1.globalValue;       // GET ID :  77777
obj1.globalValue = 88;  // SET ID :  88
obj1.globalValue;       // GET ID :  88  

var obj2 = new Rectangle('R_2', 5, 70);
console.log( obj2 );    // Rectangle {id: "R_2", width: 5, height: 70}
obj2.area;              // Area :  350    
obj2.globalValue;       // GET ID :  88
obj2.globalValue = 999; // SET ID :  999
obj2.globalValue;       // GET ID :  999

console.log('Static Variable Actions.');
obj1.globalValue;        // GET ID :  999

console.log('Parent Class Static variables');
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  777
obj1.setStaticVar(7);   // SET Instance Method Parent Class Static Value :  7
obj1.getStaticVar();    // GET Instance Method Parent Class Static Value :  7
  

Static method调用直接在类上进行,并且在类的实例上不可调用。但是您可以从实例内部实现对静态成员的调用。

     

使用语法:

   this.constructor.staticfunctionName();
class MyClass {
    constructor() {}
    static staticMethod() {
        console.log('Static Method');
    }
}
MyClass.staticVar = 777;

var myInstance = new MyClass();
// calling from instance
myInstance.constructor.staticMethod();
console.log('From Inside Class : ',myInstance.constructor.staticVar);

// calling from class
MyClass.staticMethod();
console.log('Class : ', MyClass.staticVar);

ES6课程:ES2015课程是基于原型的OO模式的简单糖。拥有一个方便的声明形式使类模式更易于使用,并鼓励互操作性。类支持基于原型的继承,超级调用,实例和静态方法和构造函数。

Example:请参阅我以前的帖子。

答案 21 :(得分:1)

有四种方法可以在Javascript中模拟函数本地静态变量。

方法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

答案 22 :(得分:1)

在JavaScript中,没有术语或关键字静态,但我们可以将这些数据直接放入函数对象中(就像在任何其他对象中一样)。

function f() {
    f.count = ++f.count || 1 // f.count is undefined at first
    alert("Call No " + f.count)
}

f(); // Call No 1

f(); // Call No 2

答案 23 :(得分:0)

我经常使用静态函数变量,这是一个真正的耻辱JS没有内置的机制。我常常看到变量和函数在外部作用域中定义的代码,即使它们只是在一个函数中使用。这很丑陋,容易出错,只是在惹麻烦......

我想出了以下方法:

if (typeof Function.prototype.statics === 'undefined') {
  Function.prototype.statics = function(init) {
    if (!this._statics) this._statics = init ? init() : {};
    return this._statics;
  }
}

这为所有函数添加了一个'静态'方法(是的,只是放松一下),调用它时会向函数对象添加一个空对象(_statics)并返回它。如果提供了init函数,则_statics将设置为init()result。

然后你可以这样做:

function f() {
  const _s = f.statics(() => ({ v1=3, v2=somefunc() });

  if (_s.v1==3) { ++_s.v1; _s.v2(_s.v1); }
} 

将它与另一个正确答案的IIFE进行比较,这样做的缺点是在每次函数调用时添加一个赋值和一个赋值,并在函数中添加一个'_statics'成员,但是有一些优点:参数在顶部不在内部函数中,在内部函数代码中使用'static'是显式的'_s'。前缀,看起来和理解总体上更简单。

答案 24 :(得分:0)

您可以使用static关键字定义static functions in JavaScript

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

MyClass.myStaticFunction(); // 42

在撰写本文时,您仍然不能在类中定义静态属性(函数以外的其他属性)。静态属性仍然是Stage 3 proposal,这意味着它们还不是JavaScript的一部分。但是,没有什么能阻止您像分配给任何其他对象一样简单地分配给一个类:

class MyClass {}

MyClass.myStaticProperty = 42;

MyClass.myStaticProperty; // 42

最后一点:请谨慎使用具有继承性的静态对象-all inherited classes share the same copy of the object

答案 25 :(得分:0)

我通常使用this method的原因有两个:

如果我想存储函数的局部值,则使用诸如“ Local.x”,“ Local.y”,“ Local.TempData”之类的东西!!

如果我想存储函数的静态值,可以使用“ Static.o”,“ Static.Info”,“ Static.count”等内容!!

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

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

答案 26 :(得分:0)

我使用了原型并以这种方式工作:

class Cat extends Anima {
  constructor() {
    super(Cat.COLLECTION_NAME);
  }
}

Cat.COLLECTION_NAME = "cats";

或使用静态吸气剂:

class Cat extends Anima {
  constructor() {
    super(Cat.COLLECTION_NAME);
  }

  static get COLLECTION_NAME() {
    return "cats"
  }
}

答案 27 :(得分:0)

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

面向对象编程实际上有两种不同的风格,一种是“基于类”(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,则更改将级联到立即继承它的子对象。

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

首先确保将构造函数隐藏在Global命名空间中,方法是将其封装在另一个函数中,如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
});

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

在我看来,“静态属性”的基于类的概念与这个Javascript实现之间没有完美的类比。因此,我认为从长远来看,使用更加友好的Javascript代码模式可能会更好。例如中央数据存储区或缓存甚至是专用的辅助对象来保存所有必需的静态变量。

答案 28 :(得分:0)

我有通用方法:

  • 创建类似Options -Indexes Options +FollowSymLinks Options -MultiViews DefaultLanguage pt-BR ServerSignature Off DirectoryIndex index.php RewriteEngine On # Check that you're on port 443 and the hostname starts with www RewriteCond %{SERVER_PORT} ^443 RewriteCond %{HTTP_HOST} ^www\. # Redirect to domain without the www RewriteRule (.*) https://example.com/intranet/$1 [L,R,QSA] RewriteCond %{HTTPS} !=on RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [L,R] 的对象
  • 使用它来动态添加字段:stat_flags = {};;
  • 下一次询问对象中是否需要标记并执行逻辑

示例:

flags.popup_save_inited = true

答案 29 :(得分:0)

ES6 classes support static functions的行为与其他面向对象语言中的静态函数非常相似:

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

typeof MyClass.myFunction; // 'function'
MyClass.myFunction(); // 42

General static properties仍然是stage 3 proposal,这意味着您需要Babel's stage 3 preset才能使用它们。但是使用Babel,您可以执行以下操作:

class MyClass {
  static answer = 42;
}

MyClass.answer; // 42

答案 30 :(得分:0)

2021 年更新

在 2021 年,您只需使用 static 关键字

TC39 从 2021 年 4 月起将 STATIC 关键字移至 Stage-4 Language Feature。使 static JS 功能成为正式集花了很长时间在 JS 语言特性方面,等待是由于缺乏浏览器支持;主流浏览器现在都支持 static 关键字,以及公共静态字段和私有静态字段的开放季节。



以下是实现静态 JavaScript 类成员的新方法的通用示例
class ColorFinder {
  static #red = "#ff0000";
  static #green = "#00ff00";
  static #blue = "#0000ff";
  
  static colorName(name) {
    switch (name) {
      case "red": return ColorFinder.#red;
      case "blue": return ColorFinder.#blue;
      case "green": return ColorFinder.#green;
      default: throw new RangeError("unknown color");
    }
  }
  
  // Somehow use colorName
}

Example above was taken from the official TC39 Repository, Static-Variables (Semantics)

To read more about the implementation of this new JS language feature (CLICK HERE).
To read more about the feature itself, as well as seeing examples that demonstarte the syntax used for static fields (CLICK HERE).

答案 31 :(得分:0)

在JavaScript中,一切都是基本类型或对象。 函数是对象 - (键值对)。

创建函数时,可以创建两个对象。一个对象表示函数本身,另一个对象表示函数的原型。

功能基本上就是具有属性的对象:

function name, 
arguments length 
and the functional prototype.

那么在哪里设置静态属性: 两个位置,在函数对象内部或函数原型对象内部。

以下是使用new JavaScript关键字创建该端甚至实例化两个实例的代码段。

function C () { // function
  var privateProperty = "42";  
  this.publicProperty = "39";  
  
  this.privateMethod = function(){ 
   console.log(privateProperty);
  };
}

C.prototype.publicMethod = function () {    
  console.log(this.publicProperty);
};

C.prototype.staticPrototypeProperty = "4";
C.staticProperty = "3";


var i1 = new C(); // instance 1
var i2 = new C(); // instance 2

i1.privateMethod();
i1.publicMethod();

console.log(i1.__proto__.staticPrototypeProperty);
i1.__proto__.staticPrototypeProperty = "2";
console.log(i2.__proto__.staticPrototypeProperty);

console.log(i1.__proto__.constructor.staticProperty);
i1.__proto__.constructor.staticProperty = "9";
console.log(i2.__proto__.constructor.staticProperty);

主要思想是实例i1i2使用相同的静态属性。

答案 32 :(得分:0)

试试这个:

如果我们定义一个属性并覆盖其getter和setter以使用Function Object属性,那么理论上你可以在javascript中有一个静态变量

例如:

&#13;
&#13;
function Animal() {
    if (isNaN(this.totalAnimalCount)) {
        this.totalAnimalCount = 0;
    }
    this.totalAnimalCount++;
};
Object.defineProperty(Animal.prototype, 'totalAnimalCount', {
    get: function() {
        return Animal['totalAnimalCount'];
    },
   set: function(val) {
       Animal['totalAnimalCount'] = val;
   }
});
var cat = new Animal(); 
console.log(cat.totalAnimalCount); //Will produce 1
var dog = new Animal();
console.log(cat.totalAnimalCount); //Will produce 2 and so on.
&#13;
&#13;
&#13;

答案 33 :(得分:0)

对于私有静态变量,我发现了这种方式:

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

答案 34 :(得分:0)

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

我在我的网站上创建了一种超级全局。由于我有几个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;
}

这当然是全局性的而不是静态的,但是当它在每个页面加载时重新初始化时,它实现了相同的目的。

答案 35 :(得分:0)

如果你想使用原型,那么有一种方法

var p = function Person() {
    this.x = 10;
    this.y = 20;
}
p.prototype.counter = 0;
var person1 = new p();
person1.prototype = p.prototype;
console.log(person1.counter);
person1.prototype.counter++;
var person2 = new p();
person2.prototype = p.prototype;
console.log(person2.counter);
console.log(person1.counter);

执行此操作,您将能够从任何实例访问计数器变量,并且将立即反映属性的任何更改!!

答案 36 :(得分:0)

使用使用jQuery的MVC网站,我喜欢确保某些事件处理程序中的AJAX操作只能在前一个请求完成后执行。我使用&#34;静态&#34; 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);

答案 37 :(得分:0)

Javascript中没有静态变量这样的东西。这种语言是基于原型的面向对象的,所以没有类,而是来自对象“复制”自己的原型。

您可以使用全局变量或原型来模拟它们(向原型添加属性):

function circle(){
}
circle.prototype.pi=3.14159

答案 38 :(得分:0)

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

答案 39 :(得分:-1)

你可以这样想。进入<body></body>标签 <p id='staticVariable'></p> 并设置其visibility: hide

当然,您可以使用jquery管理上一个标记内的文本。实际上,这个标签成为你的静态变量。

答案 40 :(得分:-1)

&#39;级&#39;系统

var Rect = (function(){
    'use strict';
     return {
        instance: function(spec){
            'use strict';
            spec = spec || {};

            /* Private attributes and methods */
            var x = (spec.x === undefined) ? 0 : spec.x,
            y = (spec.x === undefined) ? 0 : spec.x,
            width = (spec.width === undefined) ? 1 : spec.width,
            height = (spec.height === undefined) ? 1 : spec.height;

            /* Public attributes and methods */
            var that = { isSolid: (spec.solid === undefined) ? false : spec.solid };

            that.getX = function(){ return x; };
            that.setX = function(value) { x = value; };

            that.getY = function(){ return y; };
            that.setY = function(value) { y = value; };

            that.getWidth = function(){ return width; };
            that.setWidth = function(value) { width = value; };

            that.getHeight = function(){ return height; };
            that.setHeight = function(value) { height = value; };

            return that;
        },

        copy: function(obj){
            return Rect.instance({ x: obj.getX(), y: obj.getY(), width: obj.getWidth, height: obj.getHeight(), solid: obj.isSolid });
        }
    }
})();

答案 41 :(得分:-2)

{
   var statvar = 0;
   function f_counter()
   {
      var nonstatvar = 0;
      nonstatvar ++;
      statvar ++;
      return statvar + " , " + nonstatvar;
   }
}
alert(f_counter());
alert(f_counter());
alert(f_counter());
alert(f_counter());

这只是我在某处学习静态变量的另一种方法。

答案 42 :(得分:-3)

当我看到这个时,我记得JavaScript Closures ..我是这样做的。

        function Increment() {
            var num = 0; // Here num is a private static variable
            return function () {
                return ++num;
            }
        }

        var inc = new Increment();
        console.log(inc());//Prints 1
        console.log(inc());//Prints 2
        console.log(inc());//Prints 3