简体   繁体   中英

Javascript local static variable

Not sure I completely understand answers to similar questions that I found here, so trying to be absolutely sure:

I would like to have a local variable in a function, initialized only once (similar to static variables in strongly-typed languages such as C, C++, etc).

Of course, I could declare it globally, but it seems better practice to have it within the scope of that function, since it is not used anywhere else.

Now, here is what I do:

function func(data) {
    func.PARAMS = [
        {"name": "from", "size": 160, "indexed": true},
        {"name": "input", "size": 256, "indexed": false},
        {"name": "output", "size": 256, "indexed": false},
    ];
    ...
}

And my question is, will func.PARAMS indeed be initialized only once, or will it be initialized every time the function is called?

According to some of the answers that I found ( this one for example), I need to precede the initialization with something like:

if (typeof func.PARAMS == 'undefined')

This "supplemental" would be irrelevant in strongly-typed languages of course, so I just want to be sure that it is absolutely necessary in order to ensure "static behavior" (ie, one-time initialization).

In addition to using properties of the function object, as you do in your example, there are 3 other ways to emulate function-local static variables in Javascript.

All of them rely on a closure, but using different syntax.

Method 1 (supported in old browsers):

var someFunc1 = (function(){
    var staticVar = 0 ;
    return function(){
        alert(++staticVar) ;
    }
})() ;

someFunc1() ; //prints 1
someFunc1() ; //prints 2
someFunc1() ; //prints 3

Method 2 (also supported in old browsers):

var someFunc2 ;
with({staticVar:0})
    var someFunc2 = function(){
        alert(++staticVar) ;
    } ;

someFunc2() ; //prints 1
someFunc2() ; //prints 2
someFunc2() ; //prints 3

Method 3 (requires support for EcmaScript 2015):

{
    let staticVar = 0 ;
    function someFunc3(){
        alert(++staticVar) ;
    }
}

someFunc3() ; //prints 1
someFunc3() ; //prints 2
someFunc3() ; //prints 3

Method 3 for strict mode :

'use strict'
{
    let staticVar = 0 ;
    var someFunc3 = function(){
        alert(++staticVar) ;
    } ;
}

someFunc3() ; //prints 1
someFunc3() ; //prints 2
someFunc3() ; //prints 3

It would be assigned every time the function is called. There are no static variables in JavaScript. You need to declare them outside of the function. You can do that in a local scope, though:

var func;
{
    const PARAMS = [
        {"name": "from", "size": 160, "indexed": true},
        {"name": "input", "size": 256, "indexed": false},
        {"name": "output", "size": 256, "indexed": false},
    ];
    func = function(data) {
        …
    }
}

While Javascript doesn't natively have the concept of static variables, it is easy to simulate them. One pattern with objects is to use a closure (via a self-invoking function).

const MyClass = ( function() {

    // Static variables are in the scope of the self-invoking function

    const _myStaticVariable = 'this is a static variable';
      let _instances = 0; // this is also a class variable

    // The constructor function is returned to MyClass, but still has the static variables in scope

    return function() {

        _instances++;

        this.sayStaticVariable = function(){
            console.log(_myStaticVariable);
        }

        this.howMany = function(){
            console.log(_instances);
        }
    }

})();

myInstance = new MyClass();

myInstance.sayStaticVariable();
// this is a static variable

myInstance.howMany();
// 1

In this case, _myStaticVariable and _instances will only be initialised once, but will still be in scope of (and accessible to) the constructor function returned to MyClass.

As you seem to be asking about static variables in the context of functions rather than objects, you could probably adapt this pattern using functional composition

JavaScript may look similar to C++ but in fact, it's very different. Initially, it's made for simple tasks in the browser. To mimic C++ like functionalities in JS programmers create complex structures. For example, in ES6 there are classes now but actually, they are just a syntactical sugar for constructor functions that rely on prototypal inheritance. In ES6 there now static methods you may want to check.

I guess in your case it will be better to use TypeScript that is more C# like and is a superset of JavaScript.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM