Статические переменные в JavaScript: глобальный доступ и сохранение
Быстрый ответ
Для работы со статическими переменными в JavaScript часто используют замыкания или присваивают свойства функциям-конструкторам. Пример с применением замыкания:
function createCounter() {
let count = 0;
return () => count++;
}
const counter = createCounter();
console.log(counter()); // Вывод: 0
console.log(counter()); // Вывод: 1
В данном примере функция createCounter
"спрятала" переменную count
, что позволяет ей сохранять состояние между последовательными вызовами благодаря возвращаемой функции.
Применение классов ES6 для работы со статическими переменными
Классы ES6 предоставляют функциональность для создания статических переменных с помощью ключевого слова static
. Такие переменные привязываются к самому классу, а не к его экземплярам.
class MyClass {
static myStaticValue = 0;
static increment() {
this.myStaticValue++;
}
}
MyClass.increment();
console.log(MyClass.myStaticValue); // Вывод: 1
Следовательно, статическая переменная будет общей для всех экземпляров класса.
Защита статических переменных посредством замыканий
Замыкания дают возможность создавать приватные статические переменные, которые не доступны непосредственно извне, но можно изменять их через предоставленные методы.
let Library = (function () {
let bookCount = 0;
return class {
static incrementBooks() {
return ++bookCount;
}
}
})();
console.log(Library.incrementBooks()); // Вывод: 1
Такая конструкция помогает защитить bookCount
от прямого доступа извне – изменения возможны только с помощью метода incrementBooks
.
Общие методы с помощью prototype
С помощью prototype
можно определить методы, которые будут доступны всем экземплярам, что помогает оптимизировать использование памяти.
function Animal() {}
Animal.prototype.speak = function () {
return 'Это животное издает звук.';
};
let dog = new Animal();
console.log(dog.speak()); // Вывод: Это животное издает звук.
Все экземпляры Animal
используют одну и ту же функцию speak
, которая занимает место в памяти только в единственном экземпляре.
Управление доступом с использованием Object.defineProperty
Для точного контроля над доступом к переменным можно использовать Object.defineProperty
для создания геттеров и сеттеров.
class Example {
static #secretValue = 123;
static get secretValue() {
return Example.#secretValue;
}
static set secretValue(val) {
Example.#secretValue = val;
}
}
console.log(Example.secretValue); // Вывод: 123
Example.secretValue = 456;
console.log(Example.secretValue); // Вывод: 456
Визуализация
Давайте представим общественный парк в качестве места общего пользования:
Парк (🌳): [Посетитель1, Посетитель2, Посетитель3]
А теперь давайте представим статическую переменную в роли скамейки в этом парке:
function ParkBench() {
if (typeof ParkBench.counter == 'undefined') {
ParkBench.counter = 0;
}
ParkBench.counter++;
}
Каждый новый визит в парк увеличивает количество людей, отдохнувших на одной и той же скамейке:
Статическая скамья (🪑): [Посетитель1 (1), Посетитель2 (2), Посетитель3 (3)]
Таким образом, статическая переменная отслеживает посещаемость скамейки, даже если посетители посещают парк не одновременно.
На помощь приходят модули!
Модульный подход позволяет избежать загрязнения глобального пространства имен за счет использования самовызывающихся функций.
var MyApp = (function() {
var privateStaticVar = 0;
return {
increment: function() {
return ++privateStaticVar;
},
value: function() {
return privateStaticVar;
}
};
})();
console.log(MyApp.increment()); // Вывод: 1
console.log(MyApp.value()); // Вывод: 1
Внедрение TypeScript
TypeScript предлагает более привычный и традиционный синтаксис для работы со статическими переменными и модификаторами доступа.
class MyClass {
private static count = 0;
public static increment() {
this.count++;
}
}
MyClass.increment();
// console.log(MyClass.count); // Ошибка: 'count' – приватная переменная, доступная только в MyClass.
Работа со статическими переменными в анонимных функциях
В анонимной функции можно поддерживать статическую переменную с помощью arguments.callee
.
let anonymousCounter = (function() {
let count = 0;
return function() {
count++;
console.log(count, arguments.callee);
};
})();
anonymousCounter(); // Вывод: 1, [Function]
Полезные материалы
- static – JavaScript | MDN — руководство по статическим свойствам классов на MDN.
- Область видимости переменных, замыкание — подробное объяснение замыканий в JavaScript.
- Основы модульного паттерна JavaScript — статья, рассказывающая о создании модулей.
- Паттерны проектирования JavaScript: Singleton — о использовании синглтон-паттерна для управления состоянием.
- Классы в JavaScript — анализ различий между статическими и инстансными свойствами классов.
- Understanding ECMAScript 6 — детальный анализ классов ES6 и статических свойств.
- Статические переменные в JavaScript – Stack Overflow — обсуждение статических переменных в сообществе Stack Overflow.