Статические переменные в JavaScript

Как создать статические переменные в Javascript?

30 ответов


Если вы пришли из класса на основе статически типизированного объектно-ориентированного языка (например, 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 обрабатывает функции как первоклассные объекты, поэтому, будучи объектом, вы можете назначить свойства функции.


вы можете воспользоваться тем, что функции JS также являются объектами , что означает, что они могут иметь свойства.

например, цитируя пример, приведенный в (теперь исчезнувшей) статье статические переменные в 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);
}

Если вы вызовете эту функцию несколько раз, вы увидите, что счетчик увеличивается.

и это, вероятно, гораздо лучшее решение, чем загрязнение глобального пространства имен глобальным переменная.


И вот еще одно возможное решение, основанное на закрытии:трюк для использования статических переменных в 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.

что дает вам тот же результат-за исключением того, что на этот раз возвращается увеличенное значение, а не отображается.


вы делаете это через IIFE (немедленно вызываемое выражение функции):

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

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

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

вы можете использовать аргументы.вызываемый для хранения "статических" переменных (это полезно и в анонимной функции):

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

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

я видел пару подобных ответов, но я хотел бы упомянуть, что этот пост описывает его лучше, поэтому я хотел бы поделиться им с вами.

вот некоторый код, взятый из него, который я изменил, чтобы получить полный пример, который, надеюсь, принесет пользу сообществу, потому что его можно использовать в качестве шаблона дизайна для классов.

кроме ответ на ваш вопрос:

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 + ' ...');
};

учитывая этот пример, вы можете получить доступ the статические свойства/функции следующим образом:

// 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

Примечание это в подкасте.immutableProp(), у нас есть закрытие: ссылка на _somePrivateVariable хранится внутри функции.

вы даже можете определить геттеры и сеттеры. Взгляните на этот фрагмент кода (где 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.year via get и set функции-если вы не укажете set, тогда свойство доступно только для чтения и не может быть изменено (имейте в виду, что вы не получите ошибку, если попытаетесь установить его, но это не имеет никакого эффекта). Каждое свойство имеет атрибуты writable, configurable (разрешить изменение после объявления) и enumerable (позволяют использовать его в качестве перечислителя), которые по умолчанию false. Вы можете установить их через defineProperty в 3-м параметре, например 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

оператор 'new' создает новый объект и копирует все свойства и методы, т. е.

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 (объекты) серии статьи.

вы можете сказать, что a и b наследовать от Podcast. Теперь, что делать, если вы хотите добавить метод подкаста, который применяется ко всем из них после a и b были instanciated? В этом случае, используйте .prototype as следует:

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

звоните прямо сейчас a и b еще раз:

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

вы можете найти более подробную информацию о прототипах здесь. Если вы хотите сделать больше наследства, то этой.


на статьи я уже упоминал выше рекомендуется читать, они включают также следующие темы:

  1. функции
  2. объекты
  3. прототипы
  4. применение новых функций конструктора
  5. поднимать
  6. Автоматическая Запятой Вставки
  7. статические свойства и методы

Примечание что автоматическая запятой вставки "особенность" JavaScript (как указано в 6.) очень часто несет ответственность для возникновения странных проблем в коде. Следовательно, я бы предпочел рассматривать его как ошибку, а не как функцию.

если вы хотите прочитать больше,здесь очень интересно статья MSDN об этих темах, некоторые из них описаны там предоставить еще более подробную информацию.

что это интересно читать а также (также охватывающие темы, упомянутые выше) являются те статьи из MDN JavaScript Руководство:

если вы хотите знать, как эмулировать c# out параметры (как в DateTime.TryParse(str, out result)) в JavaScript, вы можете найти вот пример кода.


те из вас, кто работа с IE (который не имеет консоли для JavaScript, если вы открываете инструменты разработчика с помощью F12 и откройте вкладку консоли) может оказаться полезным следующий фрагмент. Это позволяет использовать console.log(msg); как использовано в примерах выше. Просто вставьте его перед


обновленный ответ:

на 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 функции являются объектами.


следующий пример и объяснение Из книги профессиональный JavaScript для веб-разработчиков 2-го издания Николаса Закаса. Это ответ, который я искал, поэтому я подумал, что было бы полезно добавить его здесь.

(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() on один экземпляр влияет на все остальные. Зову setName() или создание нового Person экземпляр устанавливает переменную name в новое значение. Это заставляет все экземпляры возвращать одно и то же значение.


Если вы используете новый синтаксис класс Теперь вы можете сделать следующее:

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

    console.log(MyClass.myStaticVariable);

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

это эффективно создает статическую переменную в JavaScript.


Если вы хотите объявить статические переменные для создания констант в своем приложении, я нашел следующий наиболее упрощенный подход

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;

о class введено ECMAScript 2015. Другие ответы не совсем ясны.

вот пример, показывающий, как создать статический var staticVar С ClassName.var 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

есть и другие подобные ответы, но ни один из них мне не понравился. Вот что у меня получилось:

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

вы можете создать статическую переменную в JavaScript, как показано ниже. Вот!--2--> является статической переменной.

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

Если вы хотите сделать глобальную статическую переменную:

var my_id = 123;

замените переменную на следующую:

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

в JavaScript переменные являются static по умолчанию. пример:

var x = 0;

function draw() {
    alert(x); //
    x+=1;
}

setInterval(draw, 1000);

значение x увеличивается на 1 каждые 1000 миллисекунд
Он будет печатать 1,2,3 и так далее


ближе всего в JavaScript к статической переменной является глобальная переменная - это просто переменная, объявленная вне области функции или объектного литерала:

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

другое, что вы могли бы сделать, это хранить глобальные переменные внутри объектного литерала, такого как:

var foo = { bar : 1 }

а затем получить доступ к variabels следующим образом:foo.bar.


есть еще один подход, который решил мои требования после просмотра этого потока. Это зависит от того, чего вы хотите достичь с помощью "статической переменной".

глобальное свойство sessionStorage или localStorage позволяет хранить данные в течение всего сеанса или в течение неопределенного более длительного периода, пока не будет явно очищено, соответственно. Это позволяет обмениваться данными между всеми окнами, фреймами, вкладками, всплывающими окнами и т. д. вашей страницы / приложения и намного мощнее, чем простая "статическая / глобальная переменная" в одном сегменте кода.

Это позволяет избежать всех хлопот с областью, временем жизни, семантикой, динамикой и т. д. глобальных переменных верхнего уровня, т. е. окна.myglobal. Не знаю, насколько это эффективно, но это не важно для скромных объемов данных, доступных по скромным ставкам.

легко доступны, как "sessionStorage.mydata = anything" и извлекается аналогично. Видеть "JavaScript: The Definitive Guide, Sixth Edition", David Flanagan, ISBN: 978-0-596-80552-4, Глава 20, статья 20.1. Это легко загрузить в формате PDF с помощью простого поиска, или в Вашей подписке O'Reilly Safaribooks (стоит своего веса в золоте).

Ура, Грег Е


чтобы сжать все понятия классов здесь, проверьте это:

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

в дополнение к остальным, в настоящее время есть проект (Этап-2 предложения) on предложения ECMA что вводит static общественные полей в классах. (частные поля считались)

используя пример из предложения, предлагаемом static синтаксис будет выглядеть так:

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

и быть эквивалентным следующим, которые другие выделили:

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

вы можете получить доступ это через CustomDate.epoch.

вы можете отслеживать новое предложение в proposal-static-class-features.


в настоящее время babel поддерживает эту функцию с помощью свойства преобразования класс плагин, который вы можете использовать. Кроме того, хотя все еще продолжается,V8 реализует.


в JavaScript нет термина или ключевого слова static, но мы можем поместить такие данные непосредственно в объект function (как и в любом другом объекте).

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

функция / classes допускает только один конструктор для области объекта. Function Hoisting, declarations & expressions

  • функции, созданные с помощью конструктора функций, не создают замыканий в контекстах создания; они всегда создаются в глобальной области.

      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)
    

закрытие - копии закрытия являются функцией с сохраненными данными.

  • копии каждого закрытия создаются для функции со своими собственными свободными значениями или ссылками, когда вы используете функцию внутри другой функции, используется закрытие.
  • закрытие в 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 классов функция использует


существует 4 способа эмуляции локальных статических переменных в 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

уровень окна vars-это своего рода статика в том смысле, что вы можете использовать прямую ссылку, и они доступны для всех частей вашего приложения


в Javascript нет такой вещи, как статическая переменная. Этот язык ориентирован на объект на основе прототипов, поэтому нет классов, но прототипы, из которых объекты "копируют" себя.

вы можете имитировать их с глобальными переменными или с прототипированием (добавлением свойства к прототипу):

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

работая с веб-сайтами MVC, использующими jQuery, я хотел бы убедиться, что действия 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);

Если вы хотите использовать прототип, то есть способ

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

при этом вы сможете получить доступ к переменной счетчика из любого экземпляра, и любое изменение в свойстве будет немедленно отражено!!


Итак, что я вижу с другими ответами, так это то, что они не касаются фундаментального архитектурного требования статического атрибута в объектно-ориентированном программировании.

объектно-ориентированное программирование на самом деле имеет два разных стиля: один - "основанный на классе" (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 изменение будет каскадировать вниз к дочерним объектам, которые немедленно наследуют его.

однако есть несколько "gotchas", которые могут значительно подорвать "статический" характер этого атрибута или просто оставить уязвимость безопасности...

сначала убедитесь, что конструктор скрыт из глобального пространства имен, заключив его в другую функцию, такую как метод 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
});

во-вторых и, наконец, даже если вы это сделаете, атрибут по-прежнему редактируется из любой другой части вашего собственного скрипта, поэтому может быть так, что ошибка в вашем коде записывает атрибут на одном из дочерних объектов и отсоединяет его из родительского прототипа, поэтому при изменении родительского атрибута он больше не будет каскадировать и изменять статический атрибут для дочернего объекта. см. этот jsfiddle. в разных сценариях мы могли бы либо Object.freeze(obj) чтобы остановить любые изменения дочернего объекта, или мы могли бы настроить метод setter и getter в конструкторе и получить доступ к закрытию, оба из них имеют связанные сложности.

мне кажется, что нет идеального аналога между классом на основе смысл статических атрибутов и реализации JavaScript. Поэтому я думаю, что в долгосрочной перспективе лучше использовать другой шаблон кода, который более удобен для Javascript. Например, центральное хранилище данных или кэш или даже выделенный вспомогательный объект для хранения всех необходимых статических переменных.


Я не видел эту идею ни в одном из ответов, поэтому просто добавил ее в список. Если это дубликат, просто дайте мне знать и я удалю его и upvote другой.

Я создал своего рода супер глобальный на своем веб-сайте. Поскольку у меня есть несколько JS-файлов, которые загружаются при каждой загрузке страницы, и десятки других JS-файлов, которые загружаются только на некоторых страницах, я помещаю всю "глобальную" функцию в одну глобальную переменную.

в верхней части моих первых включенных "глобальных" файлов декларация

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

тогда я delcare несколько глобальных вспомогательных функций

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

Это, конечно, глобальный не статический, но поскольку он повторно инициализируется на каждой загрузке страницы, он выполняет ту же цель.


для частных статических переменных я нашел следующий способ:

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

попробуй это:

Если мы определяем свойство и переопределяем его геттеры и сеттеры для использования свойства 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.