【问题标题】:Static variables in JavaScriptJavaScript 中的静态变量
【发布时间】:2010-12-04 20:55:26
【问题描述】:

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

【问题讨论】:

  • 我们可以定义label或者其他html标签,带有“dispaly:none”样式属性,并为这个值设置变量值并对这个值进行操作。我们不要太努力。
  • 我找到的最简单的解决方案:根本不要在类中定义静态变量。当您想使用静态变量时,只需在此处定义它,然后,例如someFunc = () => { MyClass.myStaticVariable = 1; }。然后只需创建一个静态方法来返回静态成员,例如static getStatic() { return MyClass.myStaticVariable; }。然后你就可以在课外调用MyClass.getStatic() 来获取静态数据!
  • 查看 2021 年更新以了解如何使用静态字段。截至 2021 年 4 月的静态班成员。发生了很大变化!

标签: javascript variables static closures


【解决方案1】:

试试这个:

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

例如:

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.

【讨论】:

    【解决方案2】:

    在 JavaScript 中,一切要么是原始类型,要么是对象。 函数是对象——(键值对)。

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

    从这个意义上说,函数基本上是一个具有属性的对象:

    function name, 
    arguments length 
    and the functional prototype.
    

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

    这是一个 sn-p,它使用 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 使用相同的静态属性。

    【讨论】:

    • __proto__.staticVariable 在我的 nodejs 应用程序中为我工作。
    【解决方案3】:

    我经常使用静态函数变量,真可惜 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() 结果。

    你可以这样做:

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

    将此与另一个正确答案的 IIFE 进行比较,这具有在每个函数调用中添加一个赋值和一个 if 并向函数添加一个“_statics”成员的缺点,但是有一些优点:参数是否在顶部不在内部函数中,在内部函数代码中使用“静态”是用“_s”明确表示的。前缀,而且总体上更容易查看和理解。

    【讨论】:

      【解决方案4】:

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

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

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

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

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

      【讨论】:

        【解决方案5】:

        总结:

        ES6/ES 2015 中引入了class 关键字,并伴随着static 关键字。请记住,这是 javascript 所体现的原型继承模型的语法糖。 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
        
        }
        
        // to create static variables just create a property on the prototype of the class
        Dog.prototype.breed = 'Pitbull';
        // So to define a static property we don't need the `static` keyword.
        
        const fluffy = new Dog();
        const vicky = new Dog();
        console.log(fluffy.breed, vicky.breed);
        
        // changing the static variable changes it on all the objects
        Dog.prototype.breed = 'Terrier';
        console.log(fluffy.breed, vicky.breed);

        【讨论】:

        • 他要的是静态变量,而不是静态函数。
        【解决方案6】:

        我有通用方法:

        • 创建对象,如:stat_flags = {};
        • 使用它来动态添加字段:flags.popup_save_inited = true;
        • 下次询问对象中是否有您需要的标志并执行您的逻辑

        例子:

        class ACTGeneratedPages {
            constructor(table_data, html_table_id) {
                this.flags = {};//static flags for any processes
        
                //any your code here
        
            }
        
            call_popup(post_id) {
        
                let _this = this;
                document.getElementById('act-popup-template').style.display = 'block';
        
                if (!this.flags.popup_save_inited) {//second time listener will not be attached
                    document.querySelector('.act-modal-save').addEventListener('click', function (e) {
                        //saving data code here
                        return false;
                    });
                }
        
                this.flags.popup_save_inited = true;//set flag here
            }
        
        }
        

        【讨论】:

          【解决方案7】:

          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
          

          【讨论】:

            【解决方案8】:

            我使用了原型并且它是这样工作的:

            class Cat {
              constructor() {
                console.log(Cat.COLLECTION_NAME);
              }
            }
            
            Cat.COLLECTION_NAME = "cats";
            

            或使用静态 getter:

            class Cat {
              constructor() {
                console.log(Cat.COLLECTION_NAME);
              }
            
              static get COLLECTION_NAME() {
                return "cats"
              }
            }
            

            【讨论】:

              【解决方案9】:

              您可以在声明静态变量后重新分配函数

              function IHaveBeenCalled() {
                console.log("YOU SHOULD ONLY SEE THIS ONCE");
                return "Hello World: "
              }
              function testableFunction(...args) {
                testableFunction=inner //reassign the function
                const prepend=IHaveBeenCalled()
                return inner(...args) //pass all arguments the 1st time
                function inner(num) {
                  console.log(prepend + num);
                }
              }
              testableFunction(2) // Hello World: 2
              testableFunction(5) // Hello World: 5
              

              这使用了速度较慢的...args,有没有办法第一次使用父函数的范围而不是传递所有参数?


              我的用例:

              function copyToClipboard(...args) {
                copyToClipboard = inner //reassign the function
                const child_process = require('child_process')
                return inner(...args) //pass all arguments the 1st time
                function inner(content_for_the_clipboard) {
                  child_process.spawn('clip').stdin.end(content_for_the_clipboard)
                }
              }
              

              如果你想在范围之外使用child_process,你可以将它分配给copyToClipboard的属性

              function copyToClipboard(...args) {
                copyToClipboard = inner //reassign the function
                copyToClipboard.child_process = require('child_process')
                return inner(...args) //pass all arguments the 1st time
                function inner(content_for_the_clipboard) {
                  copyToClipboard.child_process.spawn('clip').stdin.end(content_for_the_clipboard)
                }
              }
              

              【讨论】:

                【解决方案10】:

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

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

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

                【讨论】:

                • 这个方法有效,但是你污染了Function.prototype
                • @Dan:据我了解,这仅适用于圈子,而不适用于函数。至少这就是 Chrome 试图告诉我的:function circle() {} | circle.prototype | circle.prototype.pi = 3.14 | circle.prototype | Function.prototype | Function.__proto__(如果你是这个意思)
                【解决方案11】:

                '类'系统

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

                【讨论】:

                • 创建静态变量的部分呢?
                • 使用这种类型的系统,您只需像我一样将静态变量设为私有,使用 getter/setter 访问/修改变量并创建类的实例。在我的例子中,它是'var $R = Rect.instance({ x: 0, y: 0, width: 10, height: 10 });'。现在,我们可以使用 getter 和 setter 来访问变量,这将允许我们确保我们不能不安全地修改变量,例如如果有人试图将宽度设置为负值!
                【解决方案12】:

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

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

                【讨论】:

                  【解决方案13】:
                  {
                     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());
                  

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

                  【讨论】:

                  • 外对{}不做任何事情; JavaScript 不是块作用域,它是函数作用域。因此,您将 statvar 声明为全局变量。如果不是 {} 而是用自调用匿名函数 (function () {}()); 包装它,它会更接近你认为那里发生的情况。
                  • 目前尚不清楚您想在这里向我们展示什么 - 以及它与问题的关系。请尝试更具描述性,并改进您的答案。
                  【解决方案14】:

                  当我看到这个时,我记得 JavaScript 闭包。这是我的做法。

                          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
                  

                  【讨论】:

                    猜你喜欢
                    • 2012-06-05
                    • 2023-04-08
                    • 2018-08-02
                    • 2011-04-12
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-09-25
                    相关资源
                    最近更新 更多