мы можем определить метку или другой HTML-тег с помощью атрибута стиля «dispaly: none» и установить значение переменной для этого значения и операции с этим значением. Давай не будем усердно
Асгар
Самое простое решение, которое я нашел: вообще не определять статическую переменную в классе. Если вы хотите использовать статическую переменную, просто определите ее тут же, например someFunc = () => { MyClass.myStaticVariable = 1; }. Затем просто создайте статический метод для возврата статического члена, например static getStatic() { return MyClass.myStaticVariable; }. Тогда вы можете просто позвонить MyClass.getStatic()извне класса, чтобы получить статические данные!
Пиксель
Ответы:
863
Если вы исходите из объектно-ориентированного языка на основе классов, статически типизированного (например, Java, C ++ или C #), я предполагаю, что вы пытаетесь создать переменную или метод, связанный с «типом», но не с экземпляром.
Пример, использующий «классический» подход с функциями конструктора, может помочь вам уловить понятия базового OO JavaScript:
functionMyClass(){// constructor functionvar 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 instancesMyClass.staticProperty ="baz";var myInstance =newMyClass();
staticPropertyопределяется в объекте MyClass (который является функцией) и не имеет никакого отношения к созданным экземплярам. JavaScript обрабатывает функции как объекты первого класса , поэтому, будучи объектом, вы можете назначать свойства функции.
ОБНОВЛЕНИЕ: ES6 представил возможность объявлять классы через classключевое слово. Это синтаксический сахар по сравнению с существующим наследованием на основе прототипов.
staticКлючевые слова позволяют легко определить статические свойства и методы в классе.
Давайте посмотрим на приведенный выше пример, реализованный с классами ES6:
classMyClass{// class constructor, equivalent to// the function body of a constructorconstructor(){const privateVariable ='private value';// Private variable at the constructor scopethis.publicVariable ='public value';// Public propertythis.privilegedMethod =function(){// Public Method with access to the constructor scope variables
console.log(privateVariable);};}// Prototype methods:
publicMethod(){
console.log(this.publicVariable);}// Static properties shared by all instancesstatic staticProperty ='static value';static staticMethod(){
console.log(this.staticProperty);}}// We can add properties to the class prototypeMyClass.prototype.additionalMethod =function(){
console.log(this.publicVariable);};var myInstance =newMyClass();
myInstance.publicMethod();// "public value"
myInstance.additionalMethod();// "public value"
myInstance.privilegedMethod();// "private value"MyClass.staticMethod();// "static value"
Предположительно, privilegedMethodэто не эквивалентно закрытому методу в OO, потому что кажется, что его можно вызвать на экземпляре MyClass? Вы имеете в виду, что это привилегировано, потому что оно может получить доступ privateVariable?
Донал
3
Не может this.constructorбыть использован для доступа к статическим переменным из "методов экземпляра"? Если да, то стоит добавить его в ответ.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
1
Вы также можете упомянуть статические функции в вашем примере.
Дэвид Родригес
18
привет, я не уверен, что согласен с этой строкой // Статическая переменная, используемая всеми экземплярами 'MyClass.staticProperty = "baz";' что касается меня, это означает, что вы можете найти базу из myInstance.staticProperty, чего, конечно, вы не можете.
fullstacklife
5
Возможно, он должен читать MyClass.prototype.staticProperty = "baz";или быть еще более правильным по отношению к принципам ОО: статическое свойство на самом деле должно быть определено как анонимная функция, MyClass.prototype.staticProperty = function () {return staticVar;}чтобы все экземпляры обращались к одной переменной, которая также может быть изменена с помощью установщика.
Линдсеймаквен
536
Вы можете воспользоваться тем фактом, что функции JS также являются объектами - это означает, что они могут иметь свойства.
function countMyself(){// Check to see if the counter has been initializedif(typeof countMyself.counter =='undefined'){// It has not... perform the initialization
countMyself.counter =0;}// Do something stupid to indicate the value
alert(++countMyself.counter);}
Если вы вызовете эту функцию несколько раз, вы увидите, что счетчик увеличивается.
И это, вероятно, гораздо лучшее решение, чем загрязнение глобального пространства имен глобальной переменной.
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.returnfunction(){return id++;};// Return and increment})();// Invoke the outer function after defining it.
Который дает вам такой же результат - за исключением того, что на этот раз увеличенное значение возвращается, а не отображается.
в качестве ярлыка, вы можете просто сделать это, countMyself.counter = countMyself.counter || initial_value;если статическая переменная никогда не будет ложной (false, 0, нулевая или пустая строка)
Кип
3
Немного короче и понятнее: (function () {var id = 0; function uniqueID () {return id ++;};}) ();
Я бы сказал, что это самый идиоматический способ сделать это в JavaScript. Жаль, что он не получает слишком много голосов благодаря другим методам, которые, вероятно, более приемлемы для людей, которые приходят из других языков.
1
Я бы перефразировал, используя «замыкание», а не просто «IIFE».
зендка
39
Вы можете использовать arguments.callee для хранения «статических» переменных (это также полезно в анонимной функции):
Насколько я понимаю, у этого метода есть одно (только одно?) Преимущество перед способом Паскаля МАРТИНА: его можно использовать в анонимных функциях. Примером этого было бы здорово
Дан
27
arguments.calleeустарел.
Вопросы Quolonel
Я все время высмеиваю JS, но calleeмне показалось, что это хорошо. Интересно, почему взломать они решили осудить это ...: |
user2173353
35
Я видел пару похожих ответов, но я хотел бы отметить, что этот пост описывает это лучше всего, поэтому я хотел бы поделиться им с вами.
Вот некоторый код, взятый из него, который я модифицировал, чтобы получить полный пример, который, мы надеемся, принесет пользу сообществу, потому что его можно использовать как шаблон дизайна для классов.
Это также отвечает на ваш вопрос:
functionPodcast(){// private variablesvar _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 functionthis.toString =function(){return'Title: '+this.title;}};// static propertyPodcast.FILE_EXTENSION ='mp3';// static functionPodcast.download =function(podcast){
console.log('Downloading '+ podcast +' ...');};
Учитывая этот пример, вы можете получить доступ к статическим свойствам / функциям следующим образом:
Обратите внимание, что в podcast.immutableProp () у нас есть замыкание : ссылка на _somePrivateVariable хранится внутри функции.
Вы даже можете определить геттеры и сеттеры . Взгляните на этот фрагмент кода (где dпрототип объекта, для которого вы хотите объявить свойство, yэто закрытая переменная, не видимая за пределами конструктора):
// getters and settersvar d =Date.prototype;Object.defineProperty(d,"year",{get:function(){returnthis.getFullYear()},set:function(y){this.setFullYear(y)}});
Он определяет свойство с d.yearпомощью getи setфункций - если вы не укажете set, то свойство доступно только для чтения и не может быть изменено (имейте в виду, что вы не получите сообщение об ошибке, если попытаетесь установить его, но оно не имеет никакого эффекта). Каждое свойство имеет атрибуты writable, configurable(позволяют изменения после декларации) и enumerable(позволяют использовать его как интервьюер), которые по умолчанию false. Вы можете установить их с помощью defineProperty3-го параметра, например enumerable: true.
Что также верно, так это синтаксис:
// getters and setters - alternative syntaxvar obj ={ a:7,get b(){returnthis.a +1;},set c(x){this.a = x /2}};
который определяет чтение / запись свойство a, свойство только для чтения bи свойство только для записи c, с помощью которой свойствоa можно получить доступ.
Чтобы избежать непредвиденного поведения в случае, если вы забыли newключевое слово, я предлагаю добавить следующее в функцию Podcast:
// instantiation helperfunctionPodcast(){if(false===(thisinstanceofPodcast)){returnnewPodcast();}// [... same as above ...]};
Теперь оба следующих экземпляра будут работать как положено:
var podcast =newPodcast();// normal usage, still allowedvar podcast =Podcast();// you can omit the new keyword because of the helper
Оператор 'new' создает новый объект и копирует все свойства и методы, т.е.
var a=newPodcast();var b=newPodcast();
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. Теперь, что, если вы хотите добавить метод к Podcast, который применяется ко всем из них после aи bбыли созданы? В этом случае используйте .prototypeследующее:
console.log(a.titleAndLink());// "a [http://www.astronomycast.com]"
console.log(b.titleAndLink());// "An Astronomy Cast [http://www.astronomycast.com]"
Вы можете найти более подробную информацию о прототипах здесь . Если вы хотите сделать больше наследства, я предлагаю изучить это .
В серии статей я уже упоминал выше, настоятельно рекомендуется читать, они включают в себя также следующие вопросы:
функции
Объекты
Прототипы
Внедрение новых функций конструктора
Подъемно
Автоматическая вставка точки с запятой
Статические свойства и методы
Обратите внимание, что автоматическая вставка точки с запятой функция « в JavaScript (как упоминалось в 6.) очень часто вызывает странные проблемы в вашем коде. Следовательно, я бы скорее расценил это как ошибку, чем как особенность.
Если вы хотите прочитать больше, вот довольно интересная статья MSDN на эти темы, некоторые из них, описанные там, предоставляют еще больше деталей.
Также интересно прочитать ( в том числе и по темам, упомянутым выше) статьи из руководства по MDN JavaScript :
Если вы хотите узнать, как эмулировать outпараметры c # (например, в DateTime.TryParse(str, out result)) в JavaScript, вы можете найти образец кода здесь.
Те из вас, кто работает с IE (у которого нет консоли для JavaScript, если вы не открываете инструменты разработчика с помощью F12и открываете вкладку консоли), могут найти следующий фрагмент полезным. Это позволяет использовать console.log(msg);как в приведенных выше примерах. Просто вставьте его перед Podcastфункцией.
Для вашего удобства приведенный выше код в одном полном фрагменте кода:
Удобный способ использовать классы и скомпилировать их в JavaScript - это TypeScript. Вот игровая площадка, где вы можете найти несколько примеров, показывающих, как это работает. Даже если вы не используете TypeScript в данный момент, вы можете посмотреть, потому что вы можете сравнить TypeScript с результатом JavaScript в параллельном представлении. Большинство примеров просты, но есть также пример Raytracer, который вы можете попробовать немедленно. Особенно рекомендую ознакомиться с примерами «Использование классов», «Использование наследования» и «Использование обобщенных элементов», выбрав их в выпадающем списке - это хорошие шаблоны, которые можно мгновенно использовать в JavaScript. Typescript используется с Angular.
Чтобы добиться инкапсуляции локальных переменных, функций и т. Д. В JavaScript, я предлагаю использовать шаблон, подобный следующему (JQuery использует ту же технику):
<html><head></head><body><script>'use strict';// module pattern (self invoked function)const myModule =(function(context){// to allow replacement of the function, use 'var' otherwise keep 'const'// put variables and function with local module scope here:var print =function(str){if(str !==undefined) context.document.write(str);
context.document.write("<br/><br/>");return;}// ... more variables ...// main methodvar _main =function(title){if(title !==undefined) print(title);
print("<b>last modified: </b>"+ context.document.lastModified +"<br/>");// ... more code ...}// public methodsreturn{Main: _main
// ... more public methods, properties ...};})(this);// use module
myModule.Main("<b>Module demo</b>");</script></body></html>
В ECMAScript 6 вы можете создавать статические функции, используя staticключевое слово:
classFoo{static bar(){return'I am static.'}}//`bar` is a property of the classFoo.bar()// returns 'I am static.'//`bar` is not a property of instances of the classvar foo =newFoo()
foo.bar()//-> throws TypeError
Классы ES6 не вводят никакой новой семантики для статики. Вы можете сделать то же самое в ES5 следующим образом:
//constructorvarFoo=function(){}Foo.bar =function(){return'I am static.'}Foo.bar()// returns 'I am static.'var foo =newFoo()
foo.bar()// throws TypeError
Вы можете назначить свойство, Fooпотому что в JavaScript функции являются объектами.
Foo.bar;возвращает назначенную ей функцию, а не строку, возвращаемую функцией, как подразумевает ваш комментарий.
Можете ли вы добавить информацию о том, как установить (перезаписать) статическое значение в обоих этих примерах?
Уилт
1
@Wilt в обоих случаях «статическое» свойство - это просто свойство функции, поэтому вы устанавливаете его и перезаписываете так же, как и любое другое свойство в JavaScript. В обоих случаях вы можете установить barсвойство Fooдля 3как это:Foo.bar = 3;
Следующий пример и объяснение взяты из книги Николаса Закаса «Профессиональный 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 =newPerson('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());// Jamesvar person2 =newPerson('Danielle');
console.log(person1.getName());// Danielle
console.log(person2.getName());// Danielle
PersonКонструктор в данном примере , имеет доступ к имени частной переменной, как это делают getName()и setName()методы. Используя этот шаблон, переменная имени становится статической и будет использоваться среди всех экземпляров. Это означает, что вызов setName()одного экземпляра влияет на все остальные экземпляры. Вызов setName()или создание нового Personэкземпляра устанавливает переменную name в новое значение. Это заставляет все экземпляры возвращать одно и то же значение.
Это помещает объект Person в глобальное пространство имен. Не решение, которое я бы порекомендовал.
Гхола
Я не думаю, что это настоящая статическая переменная, потому что она создается по-разному с каждым новым объектом. Статический объект должен быть одинаковым для всех объектов, наследуемых от родительского прототипа?
Линдсеймаквен
1
@Ghola Целью здесь было объяснить, как создать статическую переменную. Правильное пространство имен и избегание глобальных имен - это отдельная тема, которая, возможно, усложнила ответ. Пользователь должен определить, как прикрепить конструктор без загрязнения. Если это достаточно хорошо для Николаса Закаса, это достаточно хорошо для меня.
конец
@lindsaymacvean Это статическая переменная, потому что одно значение является общим для всех экземпляров. Это нормально для значения, чтобы измениться. Если один экземпляр изменяет значение, все экземпляры будут затронуты. Маловероятно, что он будет использован точно так же, как в примере выше. Разрешение значения, устанавливаемого во время создания экземпляра, просто показывает, что это возможно. Более вероятный вариант использования будет иметь только getter и setter или, по крайней мере, проверять, чтобы убедиться, что он имеет значение, отличное от undefined.
конец
15
Если вы используете новый синтаксис класса, то теперь вы можете сделать следующее:
Это полезно при создании статических служебных классов!
помещении
1
Но теперь вопрос в том, как сохранить значение и разрешить его изменение с помощью установщика. Потребуется замыкание или свойство, MyClassопределенное за пределами конструкции класса.
О classвведенном ECMAScript 2015. Остальные ответы не совсем понятны.
Вот пример, показывающий, как создать статическую переменную staticVarс помощью ClassName. varsynthax:
classMyClass{constructor(val){this.instanceVar = val;MyClass.staticVar =10;}}var class1 =newMyClass(1);
console.log(class1.instanceVar);// 1
console.log(class1.constructor.staticVar);// 10// New instance of MyClass with another valuevar class2 =newMyClass(3);
console.log(class1.instanceVar);// 1
console.log(class2.instanceVar);// 3
Для доступа к статической переменной мы используем .constructorсвойство, которое возвращает ссылку на функцию конструктора объекта, которая создала класс. Мы можем вызвать это на двух созданных экземплярах:
В настоящее время babel поддерживает эту функцию с помощью плагина свойств класса transform, который вы можете использовать. Кроме того, хотя все еще в процессе, V8это реализует его .
Вы можете создать статическую переменную в JavaScript, как показано ниже. Вот countстатическая переменная.
varPerson=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 1Person.count =Person.count ?Person.count +1:1;}var p1 =newPerson('User p1');
console.log(p1.constructor.count);// prints 1var p2 =newPerson('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 PersonPerson.count =20;
console.log(p1.constructor.count);// prints 20
В JavaScript к статической переменной ближе всего подходит глобальная переменная - это просто переменная, объявленная вне области действия функции или литерала объекта:
var thisIsGlobal =1;function foo(){var thisIsNot =2;}
Другая вещь, которую вы могли бы сделать, это хранить глобальные переменные внутри литерала объекта, например:
var foo ={ bar :1}
А затем получить доступ к variabels как это: foo.bar.
этот помог мне загрузить несколько файлов ..... var foo = {counter: 1}; function moreFiles () {fileName = "File" + foo.counter; foo.counter = foo.counter + 1;
veer7
4
Чтобы сжать все понятия класса здесь, проверьте это:
varTest=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 classesvar test_var ="super private";//the only way to access the "super private" test_var is from herethis.privileged =function(){
console.log(test_var);}();Test.test_var ='protected';//protected variable: accessible only form inherited methods (prototype) AND child/inherited classesthis.init();};//end constructorTest.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);varJake=function(){}Jake.prototype =newTest();Jake.prototype.test =function(){
console.log('jake',Test.test_var);}var jake =newJake();
jake.test();//output: "protected"});//end domready
Ну, еще один способ взглянуть на лучшие практики в этих вещах, это просто посмотреть, как coffeescript переводит эти концепции.
#this is coffeescript
classTest#static@prop="static"#instance
constructor:(prop)->@prop= prop
console.log(@prop)
t =newTest('inst_prop');
console.log(Test.prop);//this is how the above is translated in plain js by the CS compilerTest=(function(){Test.prop ="static";functionTest(prop){this.prop = prop;
console.log(this.prop);}returnTest;})();
t =newTest('inst_prop');
console.log(Test.prop);
Есть другой подход, который решил мои требования после просмотра этой темы. Это зависит от того, чего именно вы хотите достичь с помощью «статической переменной».
Глобальное свойство sessionStorage или localStorage позволяет хранить данные в течение жизни сеанса или в течение неопределенного более длительного периода до явной очистки соответственно. Это позволяет обмениваться данными между всеми окнами, фреймами, панелями вкладок, всплывающими окнами и т. Д. Вашей страницы / приложения и является гораздо более мощным, чем простая «статическая / глобальная переменная» в одном сегменте кода.
Это позволяет избежать всех хлопот с областью действия, временем жизни, семантикой, динамикой и т. Д. Глобальных переменных верхнего уровня, например Window.myglobal. Не знаю, насколько это эффективно, но это не важно для скромных объемов данных, к которым обращаются с умеренной скоростью.
Легко доступен как «sessionStorage.mydata = что-нибудь» и извлекается аналогично. См. «JavaScript: Полное руководство, шестое издание», Дэвид Фланаган, ISBN: 978-0-596-80552-4, глава 20, раздел 20.1. Это легко загрузить в формате PDF с помощью простого поиска или в подписке O'Reilly Safaribooks (на вес золота).
Функции, созданные с помощью конструктора Function, не создают замыканий для своих контекстов создания; они всегда создаются в глобальном масштабе.
var functionClass =function(){var currentClass =Shape;
_inherits(currentClass, superClass);function functionClass(){ superClass.call(this);// Linking with SuperClass Constructor.// Instance Variables list.this.id = id;returnthis;}}(SuperClass)
Закрытия - копии закрытия являются функцией с сохраненными данными.
Копии каждого замыкания создаются функцией с их собственными свободными значениями или ссылками. Когда вы используете функцию внутри другой функции, используется замыкание.
Закрытие в JavaScript похоже на сохранение копии всех локальных переменных своей родительской функции с помощью innerFunctions.
function closureFun( args ){// Local variable that ends up within closurevar num = args;
num++;returnfunction(){ console.log(num);}}var closure1 = closureFun(5);var closure2 = closureFun(777);
closure1();// 5
closure2();// 777
closure2();// 778
closure1();// 6
Ниже приведен фрагмент кода для проверки каждого экземпляра, имеющего свою собственную копию членов экземпляра и общих статических членов.
var objTest =newRectangle('Yash_777',8,7);
console.dir(objTest);var obj1 =newRectangle('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 =newRectangle('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();
classMyClass{constructor(){}static staticMethod(){
console.log('Static Method');}}MyClass.staticVar =777;var myInstance =newMyClass();// calling from instance
myInstance.constructor.staticMethod();
console.log('From Inside Class : ',myInstance.constructor.staticVar);// calling from classMyClass.staticMethod();
console.log('Class : ',MyClass.staticVar);
Классы ES6. Классы ES2015 - это простой сахар по сравнению с основанным на прототипе шаблоном ОО. Наличие единой удобной декларативной формы облегчает использование шаблонов классов и способствует взаимодействию. Классы поддерживают наследование на основе прототипов, супер вызовы, экземпляры и статические методы и конструкторы.
На момент написания статьи вы все еще не можете определить статические свойства (кроме функций) в классе. Статические свойства все еще являются предложением Stage 3 , что означает, что они еще не являются частью JavaScript. Тем не менее, ничто не мешает вам просто присвоить класс так же, как и любому другому объекту:
Я часто использую статические переменные функции, и очень жаль, что в JS для этого нет встроенного механизма. Слишком часто я вижу код, в котором переменные и функции определены во внешней области, даже если они просто используются внутри одной функции. Это уродливо, подвержено ошибкам и просто напрашивается на неприятности ...
Это добавляет метод «статика» ко всем функциям (да, просто расслабьтесь об этом), при вызове он добавляет пустой объект (_statics) к объекту функции и возвращает его. Если функция инициализации предоставлена, _statics будет установлен в init () result.
Затем вы можете сделать:
function f(){const _s = f.statics(()=>({ v1=3, v2=somefunc()});if(_s.v1==3){++_s.v1; _s.v2(_s.v1);}}
Сравнивая это с IIFE, который является другим правильным ответом, он имеет недостаток, заключающийся в добавлении одного присваивания и одного if при каждом вызове функции и добавлении члена функции _statics к функции, однако есть несколько преимуществ: аргументы есть в верхняя часть не во внутренней функции, использование «статического» во внутреннем коде функции явно с помощью «_s». префикс, и это в целом проще смотреть и понимать.
В ES6/ ES 2015 classключевое слово было введено с сопровождающим staticключевым словом. Имейте в виду, что это синтаксический сахар по сравнению с прототипной моделью наследования, которую воплощает javavscript. staticКлючевое слово работает следующим образом для методов:
classDog{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 classDog.prototype.breed ='Pitbull';// So to define a static property we don't need the `static` keyword.const fluffy =newDog();const vicky =newDog();
console.log(fluffy.breed, vicky.breed);// changing the static variable changes it on all the objectsDog.prototype.breed ='Terrier';
console.log(fluffy.breed, vicky.breed);
Изменения на уровне окон похожи на статические в том смысле, что вы можете использовать прямую ссылку, и они доступны для всех частей вашего приложения
Гораздо лучшее описание таких переменных - «глобальное», а не статичное.
Патрик М
0
В Javascript нет такой вещи как статическая переменная. Этот язык ориентирован на объекты на основе прототипов, поэтому нет классов, но есть прототипы, из которых объекты «копируют» себя.
Вы можете смоделировать их с помощью глобальных переменных или прототипирования (добавив свойство к прототипу):
Этот метод работает, но вы загрязняетеFunction.prototype
Дан
@Dan: Насколько я понимаю, это будет только для круга, а не функции. По крайней мере, это то, что Chrome пытается сказать мне: function circle() {}| circle.prototype| circle.prototype.pi = 3.14| circle.prototype| Function.prototype| Function.__proto__(если ты это имел в виду)
Актау
0
Работая с веб-сайтами MVC, использующими jQuery, я хочу убедиться, что действия AJAX в определенных обработчиках событий могут выполняться только после завершения предыдущего запроса. Я использую «статическую» переменную объекта jqXHR для достижения этой цели.
Я обычно использую IIFE, как это для моего обработчика кликов:
var ajaxAction =(function(jqXHR){returnfunction(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);
someFunc = () => { MyClass.myStaticVariable = 1; }
. Затем просто создайте статический метод для возврата статического члена, напримерstatic getStatic() { return MyClass.myStaticVariable; }
. Тогда вы можете просто позвонитьMyClass.getStatic()
извне класса, чтобы получить статические данные!Ответы:
Если вы исходите из объектно-ориентированного языка на основе классов, статически типизированного (например, Java, C ++ или C #), я предполагаю, что вы пытаетесь создать переменную или метод, связанный с «типом», но не с экземпляром.
Пример, использующий «классический» подход с функциями конструктора, может помочь вам уловить понятия базового OO JavaScript:
staticProperty
определяется в объекте MyClass (который является функцией) и не имеет никакого отношения к созданным экземплярам. JavaScript обрабатывает функции как объекты первого класса , поэтому, будучи объектом, вы можете назначать свойства функции.ОБНОВЛЕНИЕ: ES6 представил возможность объявлять классы через
class
ключевое слово. Это синтаксический сахар по сравнению с существующим наследованием на основе прототипов.static
Ключевые слова позволяют легко определить статические свойства и методы в классе.Давайте посмотрим на приведенный выше пример, реализованный с классами ES6:
источник
privilegedMethod
это не эквивалентно закрытому методу в OO, потому что кажется, что его можно вызвать на экземпляре MyClass? Вы имеете в виду, что это привилегировано, потому что оно может получить доступprivateVariable
?this.constructor
быть использован для доступа к статическим переменным из "методов экземпляра"? Если да, то стоит добавить его в ответ.MyClass.prototype.staticProperty = "baz";
или быть еще более правильным по отношению к принципам ОО: статическое свойство на самом деле должно быть определено как анонимная функция,MyClass.prototype.staticProperty = function () {return staticVar;}
чтобы все экземпляры обращались к одной переменной, которая также может быть изменена с помощью установщика.Вы можете воспользоваться тем фактом, что функции JS также являются объектами - это означает, что они могут иметь свойства.
Например, процитируем пример, приведенный в (теперь исчезнувшей) статье Статические переменные в Javascript :
Если вы вызовете эту функцию несколько раз, вы увидите, что счетчик увеличивается.
И это, вероятно, гораздо лучшее решение, чем загрязнение глобального пространства имен глобальной переменной.
И вот еще одно возможное решение, основанное на замыкании: хитрость в использовании статических переменных в javascript :
Который дает вам такой же результат - за исключением того, что на этот раз увеличенное значение возвращается, а не отображается.
источник
countMyself.counter = countMyself.counter || initial_value;
если статическая переменная никогда не будет ложной (false, 0, нулевая или пустая строка)===
дляtypeof
проверок, иначе вы получите какое-то странное принуждение.Вы делаете это через IIFE (сразу вызывается выражение функции):
источник
Вы можете использовать arguments.callee для хранения «статических» переменных (это также полезно в анонимной функции):
источник
arguments.callee
устарел.callee
мне показалось, что это хорошо. Интересно, почему взломать они решили осудить это ...: |Я видел пару похожих ответов, но я хотел бы отметить, что этот пост описывает это лучше всего, поэтому я хотел бы поделиться им с вами.
Вот некоторый код, взятый из него, который я модифицировал, чтобы получить полный пример, который, мы надеемся, принесет пользу сообществу, потому что его можно использовать как шаблон дизайна для классов.
Это также отвечает на ваш вопрос:
Учитывая этот пример, вы можете получить доступ к статическим свойствам / функциям следующим образом:
И свойства / функции объекта просто как:
Обратите внимание, что в podcast.immutableProp () у нас есть замыкание : ссылка на _somePrivateVariable хранится внутри функции.
Вы даже можете определить геттеры и сеттеры . Взгляните на этот фрагмент кода (где
d
прототип объекта, для которого вы хотите объявить свойство,y
это закрытая переменная, не видимая за пределами конструктора):Он определяет свойство с
d.year
помощьюget
иset
функций - если вы не укажетеset
, то свойство доступно только для чтения и не может быть изменено (имейте в виду, что вы не получите сообщение об ошибке, если попытаетесь установить его, но оно не имеет никакого эффекта). Каждое свойство имеет атрибутыwritable
,configurable
(позволяют изменения после декларации) иenumerable
(позволяют использовать его как интервьюер), которые по умолчаниюfalse
. Вы можете установить их с помощьюdefineProperty
3-го параметра, напримерenumerable: true
.Что также верно, так это синтаксис:
который определяет чтение / запись свойство
a
, свойство только для чтенияb
и свойство только для записиc
, с помощью которой свойствоa
можно получить доступ.Применение:
Ноты:
Чтобы избежать непредвиденного поведения в случае, если вы забыли
new
ключевое слово, я предлагаю добавить следующее в функциюPodcast
:Теперь оба следующих экземпляра будут работать как положено:
Оператор 'new' создает новый объект и копирует все свойства и методы, т.е.
Также обратите внимание, что в некоторых ситуациях может быть полезно использовать
return
оператор в функции конструктораPodcast
чтобы вернуть пользовательский объект, защищающий функции, на которые класс полагается, но которые необходимо представить. Это объясняется далее в главе 2 (Объекты) серии статей.Вы можете сказать это
a
иb
наследовать отPodcast
. Теперь, что, если вы хотите добавить метод к Podcast, который применяется ко всем из них послеa
иb
были созданы? В этом случае используйте.prototype
следующее:Теперь позвоните
a
иb
снова:Вы можете найти более подробную информацию о прототипах здесь . Если вы хотите сделать больше наследства, я предлагаю изучить это .
В серии статей я уже упоминал выше, настоятельно рекомендуется читать, они включают в себя также следующие вопросы:
Обратите внимание, что автоматическая вставка точки с запятой функция « в JavaScript (как упоминалось в 6.) очень часто вызывает странные проблемы в вашем коде. Следовательно, я бы скорее расценил это как ошибку, чем как особенность.
Если вы хотите прочитать больше, вот довольно интересная статья MSDN на эти темы, некоторые из них, описанные там, предоставляют еще больше деталей.
Также интересно прочитать ( в том числе и по темам, упомянутым выше) статьи из руководства по MDN JavaScript :
Если вы хотите узнать, как эмулировать
out
параметры c # (например, вDateTime.TryParse(str, out result)
) в JavaScript, вы можете найти образец кода здесь.Те из вас, кто работает с IE (у которого нет консоли для JavaScript, если вы не открываете инструменты разработчика с помощью F12и открываете вкладку консоли), могут найти следующий фрагмент полезным. Это позволяет использовать
console.log(msg);
как в приведенных выше примерах. Просто вставьте его передPodcast
функцией.Для вашего удобства приведенный выше код в одном полном фрагменте кода:
Показать фрагмент кода
Ноты:
Некоторые полезные советы, советы и рекомендации по программированию на JavaScript в целом вы можете найти здесь (лучшие практики JavaScript) и там («var» против «let») . Также рекомендуется эта статья о неявных типах (принуждение) .
Удобный способ использовать классы и скомпилировать их в JavaScript - это TypeScript. Вот игровая площадка, где вы можете найти несколько примеров, показывающих, как это работает. Даже если вы не используете TypeScript в данный момент, вы можете посмотреть, потому что вы можете сравнить TypeScript с результатом JavaScript в параллельном представлении. Большинство примеров просты, но есть также пример Raytracer, который вы можете попробовать немедленно. Особенно рекомендую ознакомиться с примерами «Использование классов», «Использование наследования» и «Использование обобщенных элементов», выбрав их в выпадающем списке - это хорошие шаблоны, которые можно мгновенно использовать в JavaScript. Typescript используется с Angular.
Чтобы добиться инкапсуляции локальных переменных, функций и т. Д. В JavaScript, я предлагаю использовать шаблон, подобный следующему (JQuery использует ту же технику):
Конечно, вы можете - и должны - поместить код скрипта в отдельный
*.js
файл; это просто написано, чтобы пример был коротким.Самовызывающиеся функции (также известные как IIFE = выражение для немедленного вызова функции) описаны более подробно здесь .
источник
источник
Обновленный ответ:
В ECMAScript 6 вы можете создавать статические функции, используя
static
ключевое слово:Классы ES6 не вводят никакой новой семантики для статики. Вы можете сделать то же самое в ES5 следующим образом:
Вы можете назначить свойство,
Foo
потому что в JavaScript функции являются объектами.источник
Foo.bar;
возвращает назначенную ей функцию, а не строку, возвращаемую функцией, как подразумевает ваш комментарий.bar
свойствоFoo
для3
как это:Foo.bar = 3;
Следующий пример и объяснение взяты из книги Николаса Закаса «Профессиональный JavaScript для веб-разработчиков, 2-е издание». Это ответ, который я искал, поэтому я подумал, что было бы полезно добавить его сюда.
Person
Конструктор в данном примере , имеет доступ к имени частной переменной, как это делаютgetName()
иsetName()
методы. Используя этот шаблон, переменная имени становится статической и будет использоваться среди всех экземпляров. Это означает, что вызовsetName()
одного экземпляра влияет на все остальные экземпляры. ВызовsetName()
или создание новогоPerson
экземпляра устанавливает переменную name в новое значение. Это заставляет все экземпляры возвращать одно и то же значение.источник
Если вы используете новый синтаксис класса, то теперь вы можете сделать следующее:
Это эффективно создает статическую переменную в JavaScript.
источник
MyClass
определенное за пределами конструкции класса.Если вы хотите объявить статические переменные для создания констант в вашем приложении, то я считаю следующий способ наиболее упрощенным
источник
О
class
введенном ECMAScript 2015. Остальные ответы не совсем понятны.Вот пример, показывающий, как создать статическую переменную
staticVar
с помощьюClassName
.var
synthax:Для доступа к статической переменной мы используем
.constructor
свойство, которое возвращает ссылку на функцию конструктора объекта, которая создала класс. Мы можем вызвать это на двух созданных экземплярах:источник
Есть и другие похожие ответы, но ни один из них мне не понравился. Вот чем я закончил:
источник
В дополнение к остальным, в настоящее время есть проект (предложение этапа 2 ) по предложениям ECMA, который вводит
static
открытые поля в классах. ( частные поля были рассмотрены )Используя пример из предложения, предложенный
static
синтаксис будет выглядеть следующим образом:и быть эквивалентным следующему, что другие подчеркнули:
Вы можете получить к нему доступ через
CustomDate.epoch
.Вы можете отслеживать новое предложение в
proposal-static-class-features
.В настоящее время babel поддерживает эту функцию с помощью плагина свойств класса transform, который вы можете использовать. Кроме того, хотя все еще в процессе,
V8
это реализует его .источник
Вы можете создать статическую переменную в JavaScript, как показано ниже. Вот
count
статическая переменная.Вы можете присвоить значения статической переменной, используя либо
Person
функцию, либо любой из экземпляров:источник
Если вы хотите создать глобальную статическую переменную:
Замените переменную следующим:
источник
В JavaScript к статической переменной ближе всего подходит глобальная переменная - это просто переменная, объявленная вне области действия функции или литерала объекта:
Другая вещь, которую вы могли бы сделать, это хранить глобальные переменные внутри литерала объекта, например:
А затем получить доступ к variabels как это:
foo.bar
.источник
Чтобы сжать все понятия класса здесь, проверьте это:
Ну, еще один способ взглянуть на лучшие практики в этих вещах, это просто посмотреть, как coffeescript переводит эти концепции.
источник
В JavaScript переменные являются статическими по умолчанию. Пример :
Значение x увеличивается на 1 каждые 1000 миллисекунд.
Он выведет 1,2,3 и т. Д.
источник
Есть другой подход, который решил мои требования после просмотра этой темы. Это зависит от того, чего именно вы хотите достичь с помощью «статической переменной».
Глобальное свойство sessionStorage или localStorage позволяет хранить данные в течение жизни сеанса или в течение неопределенного более длительного периода до явной очистки соответственно. Это позволяет обмениваться данными между всеми окнами, фреймами, панелями вкладок, всплывающими окнами и т. Д. Вашей страницы / приложения и является гораздо более мощным, чем простая «статическая / глобальная переменная» в одном сегменте кода.
Это позволяет избежать всех хлопот с областью действия, временем жизни, семантикой, динамикой и т. Д. Глобальных переменных верхнего уровня, например Window.myglobal. Не знаю, насколько это эффективно, но это не важно для скромных объемов данных, к которым обращаются с умеренной скоростью.
Легко доступен как «sessionStorage.mydata = что-нибудь» и извлекается аналогично. См. «JavaScript: Полное руководство, шестое издание», Дэвид Фланаган, ISBN: 978-0-596-80552-4, глава 20, раздел 20.1. Это легко загрузить в формате PDF с помощью простого поиска или в подписке O'Reilly Safaribooks (на вес золота).
источник
Функции / классы допускают только один конструктор для своей области видимости.
Function Hoisting, declarations & expressions
Закрытия - копии закрытия являются функцией с сохраненными данными.
Классы функций ES5 : использует Object.defineProperty (O, P, Атрибуты)
Создал несколько методов с помощью `` , чтобы каждый раз мог легко понять классы функций.
Ниже приведен фрагмент кода для проверки каждого экземпляра, имеющего свою собственную копию членов экземпляра и общих статических членов.
Классы ES6. Классы ES2015 - это простой сахар по сравнению с основанным на прототипе шаблоном ОО. Наличие единой удобной декларативной формы облегчает использование шаблонов классов и способствует взаимодействию. Классы поддерживают наследование на основе прототипов, супер вызовы, экземпляры и статические методы и конструкторы.
Пример : см. Мой предыдущий пост.
источник
Есть 4 способа эмулировать функционально-локальные статические переменные в Javascript.
Способ 1. Использование свойств объекта функции (поддерживается в старых браузерах)
Способ 2: использование замыкания, вариант 1 (поддерживается в старых браузерах)
Способ 3: использование замыкания, вариант 2 (также поддерживается в старых браузерах)
Способ 4: использование замыкания, вариант 3 (требуется поддержка EcmaScript 2015)
источник
Вы можете определить статические функции в JavaScript, используя
static
ключевое слово:На момент написания статьи вы все еще не можете определить статические свойства (кроме функций) в классе. Статические свойства все еще являются предложением Stage 3 , что означает, что они еще не являются частью JavaScript. Тем не менее, ничто не мешает вам просто присвоить класс так же, как и любому другому объекту:
Последнее замечание: будьте осторожны с использованием статических объектов с наследованием - все унаследованные классы совместно используют одну и ту же копию объекта .
источник
В JavaScript нет термина или ключевого слова static, но мы можем поместить такие данные непосредственно в объект функции (как в любом другом объекте).
источник
Я часто использую статические переменные функции, и очень жаль, что в JS для этого нет встроенного механизма. Слишком часто я вижу код, в котором переменные и функции определены во внешней области, даже если они просто используются внутри одной функции. Это уродливо, подвержено ошибкам и просто напрашивается на неприятности ...
Я придумал следующий метод:
Это добавляет метод «статика» ко всем функциям (да, просто расслабьтесь об этом), при вызове он добавляет пустой объект (_statics) к объекту функции и возвращает его. Если функция инициализации предоставлена, _statics будет установлен в init () result.
Затем вы можете сделать:
Сравнивая это с IIFE, который является другим правильным ответом, он имеет недостаток, заключающийся в добавлении одного присваивания и одного if при каждом вызове функции и добавлении члена функции _statics к функции, однако есть несколько преимуществ: аргументы есть в верхняя часть не во внутренней функции, использование «статического» во внутреннем коде функции явно с помощью «_s». префикс, и это в целом проще смотреть и понимать.
источник
Резюме:
В
ES6
/ ES 2015class
ключевое слово было введено с сопровождающимstatic
ключевым словом. Имейте в виду, что это синтаксический сахар по сравнению с прототипной моделью наследования, которую воплощает javavscript.static
Ключевое слово работает следующим образом для методов:источник
Я использовал прототип и так он работал:
или используя статический геттер:
источник
Изменения на уровне окон похожи на статические в том смысле, что вы можете использовать прямую ссылку, и они доступны для всех частей вашего приложения
источник
В Javascript нет такой вещи как статическая переменная. Этот язык ориентирован на объекты на основе прототипов, поэтому нет классов, но есть прототипы, из которых объекты «копируют» себя.
Вы можете смоделировать их с помощью глобальных переменных или прототипирования (добавив свойство к прототипу):
источник
Function.prototype
function circle() {}
|circle.prototype
|circle.prototype.pi = 3.14
|circle.prototype
|Function.prototype
|Function.__proto__
(если ты это имел в виду)Работая с веб-сайтами MVC, использующими jQuery, я хочу убедиться, что действия AJAX в определенных обработчиках событий могут выполняться только после завершения предыдущего запроса. Я использую «статическую» переменную объекта jqXHR для достижения этой цели.
Учитывая следующую кнопку:
Я обычно использую IIFE, как это для моего обработчика кликов:
источник
Если вы хотите использовать прототип, то есть способ
Делая это, вы сможете получить доступ к переменной счетчика из любого экземпляра, и любое изменение в свойстве будет немедленно отражено!
источник