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


当前回答

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

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

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

其他回答

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

关于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构造函数创建的函数不会创建其创建上下文的闭包;它们总是在全局范围内创建的。var functionClass=函数(){var currentClass=形状;_继承(currentClass,superClass);function functionClass(){superClass.call(this);//与superClass构造函数链接。//实例变量列表。this.id=id;返回此;}}(特级)

闭包-闭包的副本是保存数据的函数。

每个闭包的副本都被创建到一个具有自己的自由值或引用的函数。每当您在另一个函数中使用函数时,都会使用闭包。JavaScript中的闭包就像innerFunctions维护其父函数的所有局部变量的副本。函数closureFun(参数){//结束于闭包内的局部变量var num=参数;num++;return函数(){console.log(num);}}var closure1=closureFun(5);var closure2=closureFun(777);closure1();//5.closure2();//777closure2();//778closure1();//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

静态方法调用直接在类上进行,不能在类的实例上调用。但您可以从实例内部实现对静态成员的调用。使用语法: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模式更简单。拥有一个方便的声明性表单可以使类模式更易于使用,并鼓励互操作性。类支持基于原型的继承、超级调用、实例和静态方法以及构造函数。

示例:参考我以前的帖子。

2021更新

在2021,您可以简单地使用static关键字

截至2021 4月,TC39将STATIC关键字移至第4阶段语言功能。将静态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
}

以上示例取自TC39存储库,静态字段



要了解更多关于这个新的JS语言特性的实现(单击此处)。

阅读更多关于该特性本身的信息,以及演示静态字段语法的示例(单击此处)。

在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