Zmienne statyczne w JavaScript

Jak mogę tworzyć zmienne statyczne w Javascript?

Author: Matt, 2009-10-08

30 answers

Jeśli pochodzisz z opartego na klasach, statycznie wpisanego języka obiektowego (Jak Java, C++ lub C#) zakładam, że próbujesz utworzyć zmienną lub metodę powiązaną z "typem", ale nie z instancją.

Przykład przy użyciu" klasycznego " podejścia, z funkcjami konstruktora może pomóc ci złapać pojęcia podstawowego 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 jest zdefiniowany w obiekcie MyClass (który jest funkcją) i nie ma nic wspólnego z jego utworzonymi instancjami, JavaScript traktuje funkcje jako obiekty pierwszej klasy , więc będąc obiektem, można przypisać właściwości do funkcji.

 801
Author: CMS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-11 18:01:06

Możesz skorzystać z faktu, że funkcje JS są również obiektami-co oznacza, że mogą mieć właściwości.

Na przykład, przytaczając przykład podany na (obecnie znikającym) artykule zmienne statyczne w 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);
}

Jeśli wywołasz tę funkcję kilka razy, zobaczysz, że licznik jest zwiększany.

I jest to prawdopodobnie dużo lepsze rozwiązanie niż polutowanie globalnej przestrzeni nazw zmienną globalną.


A oto kolejny możliwe rozwiązanie, oparte na zamknięciu: trik użycia zmiennych statycznych w 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.

Co daje taki sam wynik -- z tym wyjątkiem, że tym razem zwracana jest zwiększona wartość, zamiast wyświetlana.

 500
Author: Pascal MARTIN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-22 14:30:00

Robisz to przez IIFE (natychmiast wywołane wyrażenie funkcji):

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

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

incr(); // returns 1
incr(); // returns 2
 79
Author: khoomeister,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-30 10:02:35

Możesz używać argumentów.callee do przechowywania" statycznych " zmiennych (jest to przydatne również w funkcji anonimowej):

function () {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 1;
  arguments.callee.myStaticVar++;
  alert(arguments.callee.myStaticVar);
}
 39
Author: gpilotino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-06 11:19:30
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();
 27
Author: jim_zike_huang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-28 20:08:00

Widziałem kilka podobnych odpowiedzi, ale chciałbym wspomnieć, żeten post opisuje ją najlepiej, więc chciałbym się nią z wami podzielić.

Oto kod z niego zaczerpnięty, który zmodyfikowałem, aby uzyskać kompletny przykład, który miejmy nadzieję przyniesie korzyści społeczności, ponieważ może być używany jako szablon do projektowania klas.

To również odpowiada na twoje pytanie:

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

Biorąc pod uwagę ten przykład, możesz uzyskać dostęp do statycznego właściwości / funkcja następująco:

// access static properties/functions
Podcast.FILE_EXTENSION;                // 'mp3'
Podcast.download('Astronomy cast');    // 'Downloading Astronomy cast ...'

I właściwości obiektu / funkcje po prostu jako:

// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString());       // Title: The Simpsons
console.log(podcast.immutableProp());  // 123

Uwaga , że w podcast.immutableProp (), mamy zamknięcie: odniesienie do _somePrivateVariable jest przechowywane wewnątrz funkcji.

Możesz nawet zdefiniowaćgettery i settery . Spójrz na ten fragment kodu (gdzie d jest prototypem obiektu, dla którego chcesz zadeklarować właściwość, y jest prywatną zmienna niewidoczna poza konstruktorem):

// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
    get: function() {return this.getFullYear() },
    set: function(y) { this.setFullYear(y) }
});

Definiuje właściwość d.year za pomocą funkcji get i set - Jeśli nie podasz set, wtedy właściwość jest tylko do odczytu i nie może być modyfikowana(pamiętaj, że nie otrzymasz błędu, jeśli spróbujesz ją ustawić, ale nie ma to żadnego wpływu). Każda właściwość ma atrybuty writable, configurable (pozwala na zmianę po deklaracji) i enumerable (pozwala używać go jako enumeratora), które są domyślnie false. Można je ustawić za pomocą defineProperty W 3. parametr, np. enumerable: true.

Poprawna jest również ta składnia:

// getters and setters - alternative syntax
var obj = { a: 7, 
            get b() {return this.a + 1;}, 
            set c(x) {this.a = x / 2}
        };

, która definiuje właściwość do odczytu / zapisu a, właściwość tylko do odczytu b i właściwość tylko do zapisu c, za pomocą której można uzyskać dostęp do właściwości a.

Użycie:

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

Uwagi:

Aby uniknąć nieoczekiwanego zachowania w przypadku, gdy zapomniałeś słowa kluczowego new, sugeruję, aby dodać następujące do funkcji Podcast:

// instantiation helper
function Podcast() {
    if(false === (this instanceof Podcast)) {
        return new Podcast();
    }
// [... same as above ...]
};

Teraz obie poniższe instancje będą działać zgodnie z oczekiwaniami:

var podcast = new Podcast(); // normal usage, still allowed
var podcast = Podcast();     // you can omit the new keyword because of the helper

Polecenie 'new' tworzy nowy obiekt i kopiuje wszystkie właściwości i metody, tzn.

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"

Zauważ również, , że w niektórych sytuacjach może być użyteczne użycie instrukcji return w funkcji konstruktora Podcast, aby zwrócić niestandardowy obiekt chroniący funkcje, na których Klasa wewnętrznie opiera się, ale które muszą zostać ujawnione. Wyjaśniono to dokładniej w rozdziale 2 (Obiekty) artykułu seria.

Można powiedzieć, że a i b dziedziczą od Podcast. A co, jeśli chcesz dodać metodę do podcastu, która ma zastosowanie do wszystkich z nich po instancjacji a i b? W tym przypadku użyj .prototype w następujący sposób:

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

Teraz zadzwoń a i b Jeszcze raz:

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

Więcej szczegółów na temat prototypów znajdziesz tutaj . Jeśli chcesz zrobić więcej dziedziczenia, proponuję zajrzeć do to .


Artykuł Seria wspomniałem powyżej są wysoce zalecane do czytania, obejmują one również następujące tematy:

  1. funkcje
  2. Obiekty
  3. prototypy
  4. wymuszanie nowych funkcji konstruktora
  5. podnoszenie
  6. Automatyczne Wstawianie Średnika
  7. właściwości statyczne i metody

Uwaga , że automatyczne wstawianie średnika "cecha" JavaScript (jako wymieniony w 6.) jest bardzo często odpowiedzialny za powodowanie dziwnych problemów w kodzie. Dlatego raczej traktowałbym to jako błąd niż jako funkcję.

Jeśli chcesz przeczytać więcej, tutaj jest dość ciekawy artykuł MSDN na te tematy, niektóre z nich tam opisane dostarczają jeszcze więcej szczegółów.

Co jest interesujące do czytania jak również (również obejmujące tematy wymienione powyżej) są te artykuły z MDN JavaScript Przewodnik :

Jeśli chcesz wiedzieć jak emulować parametry c# out (jak w DateTime.TryParse(str, out result)) w JavaScript, możesz znaleźć przykładowy kod tutaj.


Ci z Was, którzy pracują z IE (który nie ma konsoli dla JavaScript, chyba że otworzysz narzędzia programistyczne za pomocą F12 i otworzyć tab konsoli) może okazać się przydatny poniższy fragment. Pozwala na użycie console.log(msg); w sposób użyty w powyższych przykładach. Wystarczy wstawić go przed funkcją Podcast.

Dla Twojej wygody, oto powyższy kod w jednym pełnym pojedynczym fragmencie kodu:]}

let console = { log: function(msg) {  
  let canvas = document.getElementById("log"), br = canvas.innerHTML==="" ? "" : "<br/>";
  canvas.innerHTML += (br + (msg || "").toString());
}};

console.log('For details, see the explaining text');

function Podcast() {

  // with this, you can instantiate without new (see description in text)
  if (false === (this instanceof Podcast)) {
    return new Podcast();
  }

  // private variables
  var _somePrivateVariable = 123;

  // object properties
  this.title = 'Astronomy Cast';
  this.description = 'A fact-based journey through the galaxy.';
  this.link = 'http://www.astronomycast.com';

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


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

// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
  get: function() {
    return this.getFullYear()
  },
  set: function(y) {
    this.setFullYear(y)
  }
});

// getters and setters - alternative syntax
var obj = {
  a: 7,
  get b() {
    return this.a + 1;
  },
  set c(x) {
    this.a = x / 2
  }
};

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

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"

Podcast.prototype.titleAndLink = function() {
    return this.title + " [" + this.link + "]";
};
    
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
<div id="log"></div>

Uwagi:

  • Kilka dobrych wskazówek, wskazówek i zaleceń dotyczących programowania JavaScript w ogóle można znaleźć tutaj (JavaScript best praktyki) oraz tam ("var" versus "niech'). Zalecany jest również ten artykuł o typach ukrytych (przymus).

  • Wygodnym sposobem korzystania z klas i kompilowania ich do języka JavaScript jest TypeScript. oto plac zabaw gdzie można znaleźć kilka przykładów pokazujących, jak to działa. Nawet jeśli w tej chwili nie używasz maszynopisu, możesz spojrzeć, ponieważ możesz porównać maszynopis z wynik JavaScript w widoku obok siebie. Większość przykładów jest prosta, ale istnieje również przykład Raytracera, który możesz wypróbować natychmiast. Polecam szczególnie zajrzeć do przykładów "używanie klas", "używanie dziedziczenia" i "używanie generycznych", wybierając je w comboboxie - są to ładne szablony, które można natychmiast użyć w JavaScript.

  • Aby osiągnąć enkapsulację lokalnych zmiennych, funkcji itp. w JavaScript, proponuję użyć wzorca takiego jak następujące (JQuery używa tej samej techniki):

<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 method
      var _main = function(title) {

        if (title !== undefined) print(title);
        print("<b>last modified:&nbsp;</b>" + context.document.lastModified + "<br/>");        
        // ... more code ...
      }

      // public methods
      return {
        Main: _main
        // ... more public methods, properties ...
      };

    })(this);

    // use module
    myModule.Main("<b>Module demo</b>");
</script></body>
</html>

Oczywiście możesz - i powinieneś-umieścić kod skryptu w osobnym *.plik js; jest to po prostu napisane w wierszu, aby przykład był krótki.

 27
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-02 07:46:11

Ostatnia odpowiedź:

W ECMAScript 6 można tworzyć funkcje statyczne za pomocą słowa kluczowego 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

Klasy ES6 nie wprowadzają żadnej nowej semantyki dla statyki. Możesz zrobić to samo w ES5 Tak:

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

Można przypisać do Właściwości Foo ponieważ w JavaScript funkcje są obiektami.

 21
Author: Max Heiber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-05 00:06:18

Poniższy przykład i Wyjaśnienie pochodzą z książki Professional JavaScript for Web Developers 2nd Edition autorstwa Nicholasa Zakasa. To jest odpowiedź Szukałem więc pomyślałem, że byłoby pomocne, aby dodać go tutaj.

(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

Konstruktor Person w tym przykładzie ma dostęp do nazwy prywatnej zmiennej, podobnie jak metody getName() i setName(). Używając tego wzorca, zmienna name staje się statyczna i będzie używana wśród wszystkich instancji. Oznacza to, że wywołanie setName() na jednej instancji wpływa na wszystkie inne przypadki. Wywołanie setName() lub utworzenie nowej instancji Person ustawia zmienną name na nową wartość. Powoduje to, że wszystkie instancje zwracają tę samą wartość.

 16
Author: Nate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-13 08:29:57

Jeśli używasz nowej składni klasy, możesz teraz wykonać następujące czynności:

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

    console.log(MyClass.myStaticVariable);

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

To skutecznie tworzy zmienną statyczną w JavaScript.

 10
Author: Automatico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-22 16:11:06

Jeśli chcesz zadeklarować zmienne statyczne do tworzenia stałych w aplikacji, znalazłem następujące podejście jako najbardziej uproszczone

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;
 8
Author: Hemant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-02 22:05:45

O class wprowadzony przez ECMAScript 2015. Pozostałe odpowiedzi nie są do końca jasne.

Oto przykład pokazujący jak utworzyć statyczny var staticVar z ClassName.var syntaks:

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

Aby uzyskać dostęp do zmiennej statycznej używamy .constructor właściwość zwracająca odniesienie do funkcji konstruktora obiektu, która utworzyła klasę. Możemy wywołać go na dwóch utworzonych instancjach:

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
 7
Author: COil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-24 10:02:17

Są inne podobne odpowiedzi, ale żadna nie przypadła mi do gustu. Oto z czym skończyłem:

var nextCounter = (function () {
  var counter = 0;
  return function() {
    var temp = counter;
    counter += 1;
    return temp;
  };
})();
 6
Author: funroll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-08 03:34:27

Możesz utworzyć zmienną statyczną w JavaScript, jak poniżej. Tutaj count jest zmienną statyczną.

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

Możesz przypisać wartości do zmiennej statycznej za pomocą funkcji Person lub dowolnego z wystąpień:

// 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
 6
Author: Sнаđошƒаӽ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-23 04:44:32

Jeśli chcesz stworzyć globalną zmienną statyczną:

var my_id = 123;

Zastąp zmienną poniższą:

Object.defineProperty(window, 'my_id', {
    get: function() {
            return 123;
        },
    configurable : false,
    enumerable : false
});
 5
Author: JoolzCheat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-16 03:56:46

W JavaScript zmienne są domyślnie statyczne . przykład :

var x = 0;

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

setInterval(draw, 1000);

Wartość x jest zwiększana o 1 Co 1000 milisekund
Wydrukuje 1,2,3 tak dalej

 5
Author: Kerim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-19 15:16:49

Najbliższą rzeczą w JavaScript do zmiennej statycznej jest zmienna globalna - jest to po prostu zmienna zadeklarowana poza zakresem funkcji lub obiektu literalnie:

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

Inną rzeczą, którą możesz zrobić, byłoby przechowywanie globalnych zmiennych wewnątrz literału obiektu, takiego jak:

var foo = { bar : 1 }

A następnie uzyskaj dostęp do zmiennych w następujący sposób: foo.bar.

 4
Author: Andrew Hare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-08 04:33:29

Jest inne podejście, które rozwiązało moje wymagania Po przeglądaniu tego wątku. To zależy dokładnie od tego, co chcesz osiągnąć za pomocą "zmiennej statycznej".

Właściwość global sessionStorage lub localStorage pozwala na przechowywanie danych przez cały okres trwania sesji lub przez nieokreślony dłuższy okres, aż do wyraźnego wyczyszczenia, odpowiednio. Pozwala to na udostępnianie danych między wszystkimi oknami, ramkami, panelami kart, wyskakującymi okienkami itp. "zmienna statyczna / globalna" w jednym segmencie kodu.

Unika wszelkich kłopotów z zakresem, żywotnością, semantyką, dynamiką itp. globalnych zmiennych najwyższego poziomu, czyli okna.myglobal. Nie wiem, jak wydajny jest, ale to nie jest ważne dla skromnych ilości danych, dostęp do skromnych stawek.

Łatwo dostępne jako " sessionStorage.mydata = cokolwiek " i podobnie. Zobacz też "JavaScript: the Definitive Guide, Sixth Edition", David Flanagan, ISBN: 978-0-596-80552-4, Rozdział 20, sekcja 20.1. Można go łatwo pobrać w formacie PDF za pomocą prostego wyszukiwania lub w subskrypcji O ' Reilly Safaribooks (wart swojej wagi w złocie).

Pozdrawiam, Greg E

 4
Author: Greg E,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-07 10:03:30

Aby skondensować wszystkie koncepcje klas, przetestuj to:

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
Cóż, innym sposobem, aby przyjrzeć się najlepszym praktykom w tych sprawach, jest po prostu zobaczyć, jak coffeescript tłumaczy te pojęcia.
#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);
 4
Author: Stratboy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-24 15:15:45

Oprócz reszty, obecnie istnieje projekt (propozycja etapu 2 ) na propozycje ECMA , który wprowadza static public pola w klasach. (prywatne pola były brane pod uwagę )

Używając przykładu z propozycji, proponowana składnia static będzie wyglądała następująco:

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

I być równoznaczne z tym, co inni podkreślili:

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

Możesz uzyskać do niego dostęp poprzez CustomDate.epoch.

Możesz śledzić nowe wniosek w proposal-static-class-features.


Obecnie babel obsługuje tę funkcję za pomocą wtyczki transform class properties , której możesz użyć. Dodatkowo, choć wciąż w toku, V8 realizuje ją .

 3
Author: Jim Fasarakis Hilliard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-07 22:27:26

W JavaScript nie ma statycznego terminu ani słowa kluczowego, ale możemy umieścić takie dane bezpośrednio w obiekcie function (jak w każdym innym obiekcie).

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
 1
Author: Satyapriya Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-31 18:05:07

Function ' s / classes pozwala tylko jednemu konstruktorowi dla jego zakresu obiektów. Function Hoisting, declarations & expressions

  • Funkcje utworzone za pomocą konstruktora funkcji nie tworzą zamknięć w kontekstach ich tworzenia; zawsze są tworzone w zasięgu globalnym.

      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)
    

Closures - kopie zamknięcia są funkcjami z zachowanymi danymi.

  • każda kopia zamknięcia jest tworzona do funkcji z własną dowolne wartości lub odniesienia, za każdym razem, gdy używasz funkcji wewnątrz innej funkcji, używane jest zamknięcie.
  • Zamknięcie w JavaScript jest jak zachowanie kopii wszystkich lokalnych zmiennych funkcji macierzystej przez 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
    

Klasy funkcji ES5 : używa obiektu .defineProperty (O, P, atrybuty)

Obiekt .metoda defineProperty () definiuje nową właściwość bezpośrednio na obiekcie, lub modyfikuje istniejącą właściwość obiektu i zwraca obiekt.

Stworzył kilka metod używając `, aby każdy raz mógł łatwo zrozumieć klasy funkcji.

'use strict';
var Shape = function ( superClass ) {
    var currentClass = Shape;
    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Shape(id) { superClass.call(this); // Linking with SuperClass Constructor.
        // Instance Variables list.
        this.id = id;   return this;
    }
    var staticVariablesJOSN = { "parent_S_V" : 777 };
    staticVariable( currentClass, staticVariablesJOSN );

    // Setters, Getters, instanceMethods. [{}, {}];
    var instanceFunctions = [
        {
            key: 'uniqueID',
            get: function get() { return this.id; },
            set: function set(changeVal) { this.id = changeVal; }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Object);

var Rectangle = function ( superClass ) {
    var currentClass = Rectangle;

    _inherits(currentClass, superClass); // Prototype Chain - Extends

    function Rectangle(id, width, height) { superClass.call(this, id); // Linking with SuperClass Constructor.

        this.width = width;
        this.height = height;   return this;
    }

    var staticVariablesJOSN = { "_staticVar" : 77777 };
    staticVariable( currentClass, staticVariablesJOSN );

    var staticFunctions = [
        {
            key: 'println',
            value: function println() { console.log('Static Method'); }
        }
    ];
    staticMethods(currentClass, staticFunctions);

    var instanceFunctions = [
        {
            key: 'setStaticVar',
            value: function setStaticVar(staticVal) {
                currentClass.parent_S_V = staticVal;
                console.log('SET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
            }
        }, {
            key: 'getStaticVar',
            value: function getStaticVar() {
                console.log('GET Instance Method Parent Class Static Value : ', currentClass.parent_S_V);
                return currentClass.parent_S_V;
            }
        }, {
            key: 'area',
            get: function get() {
                console.log('Area : ', this.width * this.height);
                return this.width * this.height;
                }
        }, {
            key: 'globalValue',
            get: function get() {
                console.log('GET ID : ', currentClass._staticVar);
                return currentClass._staticVar;
            },
            set: function set(value) {
                currentClass._staticVar = value;
                console.log('SET ID : ', currentClass._staticVar);
            }
        }
    ];
    instanceMethods( currentClass, instanceFunctions );

    return currentClass;
}(Shape);

// ===== ES5 Class Conversion Supported Functions =====
function defineProperties(target, props) {
    console.log(target, ' : ', props);
    for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        Object.defineProperty(target, descriptor.key, descriptor);
    }
}
function staticMethods( currentClass, staticProps ) {
    defineProperties(currentClass, staticProps);
};
function instanceMethods( currentClass, protoProps ) {
    defineProperties(currentClass.prototype, protoProps);
};
function staticVariable( currentClass, staticVariales ) {
    // Get Key Set and get its corresponding value.
    // currentClass.key = value;
    for( var prop in staticVariales ) {
        console.log('Keys : Values');
        if( staticVariales.hasOwnProperty( prop ) ) {
            console.log(prop, ' : ', staticVariales[ prop ] );
            currentClass[ prop ] = staticVariales[ prop ];
        }
    }
};
function _inherits(subClass, superClass) {
    console.log( subClass, ' : extends : ', superClass );
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, 
            { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });
    if (superClass)
        Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

Poniższy fragment kodu służy do sprawdzenia, czy każda instancja ma własną kopię członków instancji i zwykłych członków statycznych.

var objTest = new Rectangle('Yash_777', 8, 7);
console.dir(objTest);

var obj1 = new Rectangle('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 = new Rectangle('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

Statyczne wywołania metody są wykonywane bezpośrednio na klasie i nie są możliwe do wywołania na instancjach klasy. Ale można osiągnąć wywołanie statycznych członków z wnętrza instancji.

Użycie składni:

   this.constructor.staticfunctionName();
class MyClass {
    constructor() {}
    static staticMethod() {
        console.log('Static Method');
    }
}
MyClass.staticVar = 777;

var myInstance = new MyClass();
// calling from instance
myInstance.constructor.staticMethod();
console.log('From Inside Class : ',myInstance.constructor.staticVar);

// calling from class
MyClass.staticMethod();
console.log('Class : ', MyClass.staticVar);

Klasy ES6: klasy ES2015 są cukrem prostym nad wzorcem oo opartym na prototypie. Posiadanie jednej wygodnej formy deklaratywnej sprawia, że wzorce klas są łatwiejsze w użyciu i zachęca do interoperacyjności. Klasy obsługują dziedziczenie oparte na prototypach, super wywołania, instancje oraz statyczne metody i konstruktory.

Przykład : refer my previous post.

 1
Author: Yash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-09 13:07:36

Istnieją 4 sposoby emulowania funkcji-lokalnych zmiennych statycznych w Javascript.

Metoda 1: Używanie właściwości obiektu funkcji (obsługiwane w starych przeglądarkach)

function someFunc1(){
    if( !('staticVar' in someFunc1) )
        someFunc1.staticVar = 0 ;
    alert(++someFunc1.staticVar) ;
}

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

Metoda 2: użycie zamknięcia, wariant 1 (obsługiwane w starych przeglądarkach)

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

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

Metoda 3: użycie zamknięcia, wariant 2 (również wspierany w starych przeglądarkach)

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

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

Metoda 4: użycie zamknięcia, wariant 3 (wymaga wsparcia dla EcmaScript 2015)

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

someFunc4() ; //prints 1
someFunc4() ; //prints 2
someFunc4() ; //prints 3
 1
Author: GetFree,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-26 02:05:17

Zmienne poziomu okien są czymś w rodzaju statyki w tym sensie, że można użyć bezpośredniego odniesienia i są one dostępne dla wszystkich części aplikacji

 0
Author: Bostone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-08 04:34:16

W Javascript nie ma czegoś takiego jak zmienna statyczna. Ten język jest zorientowany na obiekty oparte na prototypach, więc nie ma klas, ale prototypy, z których obiekty "kopiują"się.

Można je symulować za pomocą zmiennych globalnych lub za pomocą prototypowania (dodawanie właściwości do prototypu):

function circle(){
}
circle.prototype.pi=3.14159
 0
Author: Gerardo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-08 04:38:06

Pracując z portalami MVC używającymi jQuery, chciałbym się upewnić, że działania AJAX w niektórych programach obsługi zdarzeń mogą być wykonywane tylko po zakończeniu poprzedniego żądania. W tym celu używam "statycznej" zmiennej obiektowej jqXHR.

Podano następujący przycisk:

<button type="button" onclick="ajaxAction(this, { url: '/SomeController/SomeAction' })">Action!</button>

Generalnie używam takiego programu do obsługi kliknięć:

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);
 0
Author: Todd L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-17 21:13:48

Jeśli chcesz użyć prototype to jest sposób

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

W ten sposób będziesz mógł uzyskać dostęp do zmiennej counter z dowolnej instancji i każda zmiana właściwości zostanie natychmiast odzwierciedlona!!

 0
Author: charlie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-09 06:25:42

WiÄ ™ c wiÄ ™ c z innymi odpowiedziami wiÄ ™ c wiÄ ™ c nie odpowiadajÄ ... one fundamentalnym wymaganiom architektonicznym statycznego atrybutu w programowaniu obiektowym.

Programowanie obiektowe ma w rzeczywistości dwa różne style, jeden jest "oparty na klasach" (C++, C#, Java itp.), drugi jest "prototypowy" (Javascript). W językach opartych na klasach' atrybut statyczny ' powinien być powiązany z klasą, A nie z instancyjnymi obiektami. Koncepcja ta faktycznie działa znacznie bardziej intuicyjnie w językach prototypowych, takich jak Javascript, ponieważ po prostu przypisać atrybut jako wartość prototypu macierzystego, jak tak.

function MyObject() {};
MyObject.prototype.staticAttribute = "some value";

I uzyskać do niego dostęp z każdego obiektu, który jest instancją tego konstruktora...

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

Teraz, jeśli zmienisz MyObject.prototype.staticAttribute zmiana będzie kaskadowa do obiektów potomnych, które natychmiast ją odziedziczą.

Istnieje jednak kilka 'gotchas', które mogłyby znacząco podważyć 'statyczną' naturę tego atrybutu, albo po prostu zostawić lukę w zabezpieczeniach...

Najpierw upewnij się, że ukrywasz konstruktor przed globalną przestrzenią nazw, zamykając go wewnątrz innej funkcji, takiej jak metoda 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
});

Po drugie i na koniec, nawet jeśli to zrobisz, atrybut jest nadal edytowalny z dowolnej innej części twojego skryptu, więc może się zdarzyć, że błąd w kodzie zapisze nad atrybutem na jednym z obiektów potomnych i odłączy go od prototypu rodzica, więc jeśli zmienisz rodzica atrybut nie będzie już kaskadowy i zmieni statyczny atrybut obiektu podrzędnego. # Patrz jsfiddle w różnych scenariuszach możemy albo Object.freeze(obj) zatrzymać wszelkie zmiany w obiekcie potomnym, albo możemy skonfigurować metodę setter i getter w konstruktorze i uzyskać dostęp do zamknięcia, oba te mają powiązane złożoności.

Wydaje mi się, że nie ma idealnego analogii między klasową ideą 'atrybutu statycznego' a tą implementacją Javascript. Więc Ja myślę, że może być lepiej na dłuższą metę, aby użyć innego wzorca kodu, który jest bardziej przyjazny dla Javascript. Taki jak centralny magazyn danych lub pamięć podręczna, a nawet dedykowany obiekt pomocniczy do przechowywania wszystkich niezbędnych zmiennych statycznych.

 0
Author: lindsaymacvean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-11 03:01:24

Nie widziałem tego pomysłu w żadnej z odpowiedzi, więc po prostu dodaję go do listy. Jeśli to duplikat, daj mi znać, a ja go usunę i zagłosuję na drugiego.

Stworzyłem coś w rodzaju super globalnego na mojej stronie internetowej. Ponieważ mam kilka plików js, które są ładowane na każdym załadowaniu strony i dziesiątki innych plików js, które są ładowane tylko na niektórych stronach i umieścić wszystkie" global " funkcji w jednej zmiennej globalnej.

Na górze moich pierwszych dołączonych plików "globalnych" jest deklaracja

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

Następnie delcare kilka globalnych funkcji pomocniczych

cgf.formBehaviors = function()
{
    // My form behaviors that get attached in every page load.
}

Następnie, jeśli potrzebuję zmiennej statycznej, przechowuję ją poza zakresem, np. poza dokumentem ready lub poza załącznikiem behavior. (Używam jquery, ale powinno działać w 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;
}

To oczywiście jest globalny, a nie statyczny, ale ponieważ jest ponownie uruchamiany przy każdym załadowaniu strony, osiąga ten sam cel.

 0
Author: danielson317,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-12 16:45:17

Dla prywatnych zmiennych statycznych znalazłem w ten sposób:

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
 0
Author: Martin Wantke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-25 12:42:02

Spróbuj tego:

Jeśli zdefiniujemy właściwość i nadpisamy jej gettery i settery, aby używały Właściwości obiektu Function, to teoretycznie możesz mieć statyczną zmienną w javascript

Na przykład:

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.
 0
Author: user2959417,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-09 18:57:32