Переменные класса в Javascript

У меня возникли проблемы с попыткой заставить переменные класса работать в javascript.

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

  • Существуют ли какие-либо стандарты для веб-браузеров мобильных устройств с точки зрения спящего потока?
  • Как я могу запросить увеличение размера локального хранилища HTML5 на iPad, как это делает веб-приложение FT?
  • Самый простой способ проанализировать дату в Javascript
  • Эквивалент каталога Python в Javascript
  • Скажите ботам отдельно от посетителей-людей за статистику?
  • Поиск последнего слова в JavaScript
  • Вот почему этот код немного смущает меня.

    Каков правильный способ реализации переменных класса?

    function classA() {}; classA.prototype.shared = 0; a = new classA; //print both values to make sure that they are the same classA.prototype.shared; a.shared; //increment class variable classA.prototype.shared++; //Verify that they are each 1 (Works) classA.prototype.shared; a.shared; //now increment the other reference a.shared++; //Verify that they are each 2 (Doesn't Work) classA.prototype.shared; a.shared; 

    UPDATE: Кажется, что все подтверждают тот факт, что, увеличивая переменную экземпляра, мы не влияем на прототип. Это прекрасно, это то, что я документировал в моем примере, но разве это не похоже на ошибку в дизайне языка? Почему это поведение желательно? Мне кажется странным, что, когда var экземпляра undefined, мы следуем скрытой ссылке на прототип, где получаем значение var, но мы копируем его в объект экземпляра.

    Я также понимаю, что это не java / c ++ / ruby ​​/ python, это другой язык. Мне просто интересно, почему это поведение может быть хорошим.

    8 Solutions collect form web for “Переменные класса в Javascript”

     I assumed that since prototypes will be shared between objects then so will their variables. 

    Они есть, но это:

     a.shared++ 

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

     (a.shared= a.shared+1)-1 

    (-1 для возврата значения предварительного инкремента, а не того, что вы фактически используете значение retrun, но все же.)

    Таким образом, на самом деле это делается для a.shared. Когда вы назначаете члену экземпляра, вы всегда пишете его собственным членам, не касаясь каких-либо членов какого-либо из его прототипов. Это то же самое, что сказать:

     classA.prototype.shared= 1; a.shared= 2; 

    Таким образом, ваш новый a.shared скрывает прототип.shared, не изменяя его. Другие экземпляры класса A будут продолжать показывать значение прототипа 1. Если вы удалили a.shared, вы снова сможете увидеть переменную прототипа, которая была скрыта за ней.

    Статические (классные) переменные могут быть выполнены следующим образом :

     function classA(){ //initialize } classA.prototype.method1 = function(){ //accessible from anywhere classA.static_var = 1; //accessible only from THIS object this.instance_var = 2; } classA.static_var = 1; //This is the same variable that is accessed in method1() 

    Ваш результат кажется странным из-за того, как javascript обрабатывает прототипы . Вызов любого метода / возврат переменной экземплярированного объекта сначала проверяет экземпляр, затем – прототип . т.е.

     var a = new classA(); classA.prototype.stat = 1; // checks a.stat which is undefined, then checks classA.prototype.stat which has a value alert(a.stat); // (a.stat = undefined, a.prototype.stat = 1) // after this a.stat will not check the prototype because it is defined in the object. a.stat = 5; // (a.stat = 5, a.prototype.stat = 1) // this is essentially a.stat = a.stat + 1; a.stat++; // (a.stat = 6, a.prototype.stat = 1) 

    Если вы хотите иметь переменную класса, что-то вроде статической переменной в Java, тогда вы можете объявить переменную в родительском классе, но тогда вы не должны обращаться к ней как к переменной дочерних объектов. В этой статье есть хороший пример класса Circle с переменной Circle.PI = 3.14 то время как все экземпляры Circle обращаются к нему как Circle.PI (вместо c.PI ).

    Поэтому мой ответ заключается в том, что если вы хотите иметь переменную класса, shared в classA тогда вы должны объявить переменную, разделяемую в classA , а позже вы должны использовать classA.shared вместо a.shared . Изменение a.shared никогда не приведет к изменению classA.shared .

    Вы просто помещаете элемент прямо в «класс», который в JavaScript является функцией, которая создает объекты:

     function ClassA(x) { this.x = x; } ClassA.shared = ""; ClassA.prototype.foo = function() { return ClassA.shared + this.x; } var inst1 = new ClassA("world"); var inst2 = new ClassA("mars"); ClassA.shared = "Hello "; console.log(inst1.foo()); console.log(inst2.foo()); ClassA.shared = "Good bye "; console.log(inst1.foo()); console.log(inst2.foo()); 

    Приращение shared свойства через экземпляр делает его свойством этого экземпляра, поэтому вы видите это поведение.

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

     >>> function ConstructorA() {}; >>> ConstructorA.prototype.shared = 0; >>> var a = new ConstructorA(); >>> ConstructorA.prototype.shared++; >>> a.shared 1 >>> a.hasOwnProperty("shared") false >>> a.shared++; >>> a.hasOwnProperty("shared") true 

    Вот почему правильное решение – использовать ConstructorA.shared , как это было предложено во многих ответах до сих пор, и всегда получать к нему доступ через функцию конструктора, а не экземпляр.

    Это может помочь считать, что в JavaScript нет такой вещи, как класс. «Экземпляры», созданные с помощью new оператора, являются объектами, которые были созданы определенной конструкторской функцией и имеют определенную цепочку прототипов. Вот почему a.shared не сможет получить доступ к ConstructorA.shared – доступ к свойствам включает в себя просмотр объекта, о котором идет речь, для именованного свойства, и в противном случае он прогуливает свою цепочку прототипов в поисках свойства, но созданная функция-конструктор Объект не является частью цепи прототипов.

    Если вы создаете экземпляр этого класса ( a = new classA ), то изменение этого экземпляра a не изменит сам базовый класс. Экземпляры класса classA наследуют все от classA.prototype , но это не применяется в обратном направлении, изменение a не изменяет classA .
    Если у вас есть два экземпляра типа a1 = new classA и a2 = new classA вы можете вносить изменения как в a1 и a2 не выполняя другие. classA.prototype другой стороны, смена classA.prototype будет видна в обоих из них.
    Переменная, shared экземпляром a будет иметь значение по умолчанию, пока не будет присвоено новое значение. Значением по умолчанию является значение classA.prototype.shared .

    Это потому, что прототипы не являются определениями классов. Прототипные переменные не являются статическими переменными. Подумайте о прототипе слова. Это не модель, используемая для создания объекта – это пример объекта, который нужно дублировать.

    То, что вы определяете, не является переменной класса, это значение по умолчанию для переменной экземпляра.

    Переменные класса должны быть определены непосредственно в классе, что означает непосредственно в функции constrctor.

     function ClassA() { ClassA.countInstances = (ClassA.countInstances || 0) + 1; } var a1 = new ClassA(); alert(ClassA.countInstances); var a2 = new ClassA(); alert(ClassA.countInstances); 

    Когда вы объявляете переменную в прототипе, эта переменная будет наследоваться всеми экземплярами как переменные экземпляра (точно так же, как методы) и будет чрезмерно увеличиваться, если вы измените ее в экземпляре (точно так же, как методы).

    JavaScript делает сайт умным, красочным и простым использованием.