it-swarm.com.de

Statische Variablen in JavaScript

Wie kann ich statische Variablen in Javascript erstellen?

640
Rajat

Wenn Sie aus einer klassenbasierten, statisch typisierten, objektorientierten Sprache (wie Java, C++ oder C #) stammen, gehe ich davon aus, dass Sie versuchen, eine Variable oder Methode zu erstellen, die einem "Typ" zugeordnet ist, jedoch nicht einer Instanz .

Ein Beispiel, das einen "klassischen" Ansatz mit Konstruktorfunktionen verwendet, könnte Ihnen dabei helfen, die Grundbegriffe von OO JavaScript einzufangen:

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 ist im MyClass-Objekt (das ist eine Funktion) definiert und hat nichts mit den erstellten Instanzen zu tun. JavaScript behandelt Funktionen als Objekte der ersten Klasse . Da Sie also ein Objekt sind, können Sie einer Funktion Eigenschaften zuweisen.

810
CMS

Sie können die Tatsache ausnutzen, dass JS-Funktionen auch Objekte sind, dh sie können Eigenschaften haben.

Beispiel: Zitieren Sie das Beispiel für den (jetzt verschwundenen) Artikel Statische Variablen in 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);
}

Wenn Sie diese Funktion mehrmals aufrufen, wird der Zähler inkrementiert.

Dies ist wahrscheinlich eine viel bessere Lösung, als den globalen Namespace mit einer globalen Variablen zu überlisten.


Und hier ist eine andere mögliche Lösung, die auf einer Schließung basiert: Trick zur Verwendung statischer Variablen in 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.

Dadurch erhalten Sie dasselbe Ergebnis - außer, dass der inkrementierte Wert diesmal zurückgegeben wird, anstatt angezeigt zu werden.

513
Pascal MARTIN

Sie tun dies über eine IIFE (sofort aufgerufener Funktionsausdruck):

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

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

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

sie können arguments.callee verwenden, um "statische" Variablen zu speichern (dies ist auch in anonymen Funktionen hilfreich):

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

Ich habe ein paar ähnliche Antworten gesehen, aber ich möchte erwähnen, dass dieser Beitrag es am besten beschreibt, also möchte ich es mit Ihnen teilen.

Hier ist ein Code daraus, den ich modifiziert habe, um ein vollständiges Beispiel zu erhalten, das der Community hoffentlich Vorteile bringt, da es als Entwurfsvorlage für Klassen verwendet werden kann.

Es beantwortet auch Ihre Frage:

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

In diesem Beispiel können Sie wie folgt auf static properties/function zugreifen:

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

Und das Objekt Eigenschaften/Funktionen einfach als:

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

Hinweis dass wir in podcast.immutableProp () ein Closure : den Verweis auf _somePrivateVariable haben innerhalb der Funktion gehalten.

Sie können sogar Getter und Setter definieren. Schauen Sie sich diesen Codeausschnitt an (wobei d der Prototyp des Objekts ist, für das Sie eine Eigenschaft deklarieren möchten, y eine private Variable ist, die außerhalb des Konstruktors nicht sichtbar ist):

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

Sie definiert die Eigenschaft d.year über die Funktionen get und set. Wenn Sie set nicht angeben, ist die Eigenschaft schreibgeschützt und kann nicht geändert werden bewirken). Jede Eigenschaft hat die Attribute writable, configurable (darf nach der Deklaration geändert werden) und enumerable (darf als Enumerator verwendet werden), die standardmäßig false sind. Sie können sie über defineProperty im 3. Parameter einstellen, z. enumerable: true.

Was auch gültig ist, ist diese Syntax:

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

dies definiert eine lesbare/beschreibbare Eigenschaft a, eine schreibgeschützte Eigenschaft b und eine schreibgeschützte Eigenschaft c, über die auf die Eigenschaft a zugegriffen werden kann.

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

Hinweise:

Um unerwartetes Verhalten zu vermeiden, falls Sie das Schlüsselwort new vergessen haben, sollten Sie der Funktion Podcast Folgendes hinzufügen:

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

Jetzt funktionieren beide der folgenden Instanzen wie erwartet:

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

Die Anweisung 'new' erstellt ein neues Objekt und kopiert alle Eigenschaften und Methoden, d. H.

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"

Beachten Sie auch, dass es in manchen Situationen nützlich sein kann, die Anweisung return in der Konstruktorfunktion Podcast zu verwenden, um benutzerdefinierte Objektschutzfunktionen zurückzugeben, auf die sich die Klasse intern stützt, die es aber müssen ausgesetzt. Dies wird in Kapitel 2 (Objekte) der Artikelserie näher erläutert.

Sie können sagen, dass a und b von Podcast erben. Was ist nun, wenn Sie dem Podcast eine Methode hinzufügen möchten, die auf alle angewendet wird, nachdem a und b instanziiert wurden? Verwenden Sie in diesem Fall den .prototype wie folgt:

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

Rufen Sie nun a und b erneut auf:

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

Weitere Details zu Prototypen finden Sie hier . Wenn Sie mehr Vererbung machen möchten, schlage ich vor, this .


Die Artikelserie die ich oben erwähnt habe sind sehr zu empfehlen zu lesen, sie beinhalten auch die folgenden Themen:

  1. Funktionen
  2. Objekte
  3. Prototypen
  4. Neue Konstruktorfunktionen erzwingen
  5. Heben
  6. Automatisches Einfügen von Semikolons
  7. Statische Eigenschaften und Methoden

Hinweis dass das automatische Semikoloneinfügung "Feature" von JavaScript ist (wie in 6. erwähnt) Sehr oft verantwortlich für seltsame Probleme in Ihrem Code. Daher würde ich es eher als Fehler als als Merkmal betrachten.

Wenn Sie mehr darüber lesen möchten, ist hier ein recht interessanter MSDN-Artikel zu diesen Themen. Einige der dort beschriebenen Themen enthalten noch weitere Informationen.

Was interessant zu lesen ist (auch zu den oben genannten Themen), sind die Artikel aus dem MDN JavaScript Guide :

Wenn Sie wissen möchten, wie man c # out -Parameter (wie in DateTime.TryParse(str, out result)) in JavaScript emuliert, finden Sie Beispielcode hier. =


Diejenigen von Ihnen, die arbeiten mit IE (die keine Konsole für JavaScript haben, es sei denn, Sie öffnen die Entwicklertools mit )F12 und öffne die Konsolenregisterkarte), könnte das folgende Snippet nützlich sein. Hiermit können Sie console.log(msg); wie in den obigen Beispielen verwenden. Fügen Sie es einfach vor der Funktion Podcast ein.

Der Einfachheit halber finden Sie hier den obigen Code in einem vollständigen Code-Snippet:

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>

Hinweise:

  • Einige gute Tipps, Hinweise und Empfehlungen zur JavaScript-Programmierung im Allgemeinen finden Sie hier hier (Best Practices für JavaScript) und there ('var' versus 'let'). Empfohlen wird auch dieser Artikel über implizite Typumwandlungen (Zwang).

  • Eine bequeme Möglichkeit, Klassen zu verwenden und in JavaScript zu kompilieren, ist TypeScript. Hier ist ein Spielplatz where Sie können einige Beispiele finden, die Ihnen zeigen, wie es funktioniert. Auch wenn Sie TypeScript momentan nicht verwenden, können Sie einen Blick darauf werfen, da Sie TypeScript in einer Side-by-Side-Ansicht mit dem JavaScript-Ergebnis vergleichen können. Die meisten Beispiele sind einfach, aber es gibt auch ein Raytracer-Beispiel, das Sie sofort ausprobieren können. Ich empfehle, besonders die Beispiele "Using Classes", "Using Inheritance" und "Using Generics" zu betrachten, indem Sie sie in der Combobox auswählen - dies sind nette Vorlagen, die Sie sofort in JavaScript verwenden können. TypeScript wird mit Angular. verwendet

  • Um Kapselung von lokalen Variablen, Funktionen usw. in JavaScript zu erreichen, empfehle ich die Verwendung eines Musters wie folgt (JQuery verwendet dieselbe Technik):

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

Natürlich können und sollten Sie den Skriptcode in eine separate *.js-Datei einfügen. Dies ist nur inline geschrieben, um das Beispiel kurz zu halten.

28
Matt
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
jim_zike_huang

Aktualisierte Antwort:

In ECMAScript 6 können Sie statische Funktionen mit dem Schlüsselwort static erstellen:

class Foo {

  static bar() {return 'I am static.'}

}

//`bar` is a property of the class
Foo.bar() // returns 'I am static.'

//`bar` is not a property of instances of the class
var foo = new Foo()
foo.bar() //-> throws TypeError

ES6-Klassen führen keine neue Semantik für Statik ein. Sie können dasselbe in ES5 wie folgt tun:

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

Sie können eine Eigenschaft von Foo zuweisen, da Funktionen in JavaScript Objekte sind.

22
Max Heiber

Das folgende Beispiel und die Erklärung stammen aus dem Buch Professional JavaScript für Web Developers 2nd Edition von Nicholas Zakas. Dies ist die Antwort, nach der ich gesucht habe, also dachte ich, es wäre hilfreich, sie hier hinzuzufügen.

(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

Der Konstruktor Person in diesem Beispiel hat Zugriff auf den Namen der privaten Variablen, ebenso wie die Methoden getName() und setName(). Mit diesem Muster wird die Namensvariable statisch und wird zwischen allen Instanzen verwendet. Das bedeutet, dass der Aufruf von setName() in einer Instanz alle anderen Instanzen betrifft. Durch Aufruf von setName() oder Erstellen einer neuen Person-Instanz wird die Namensvariable auf einen neuen Wert gesetzt. Dies führt dazu, dass alle Instanzen denselben Wert zurückgeben.

16
Nate

Wenn Sie die neue class-Syntax verwenden, können Sie jetzt Folgendes tun:

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

    console.log(MyClass.myStaticVariable);

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

Dadurch wird effektiv eine statische Variable in JavaScript erstellt.

10
Automatico

Wenn Sie statische Variablen für die Erstellung von Konstanten in Ihrer Anwendung deklarieren möchten, habe ich Folgendes als sehr vereinfachend empfunden

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
Hemant

Über das class , das von ECMAScript 2015 eingeführt wurde. Die anderen Antworten sind nicht völlig klar.

Hier ein Beispiel, das zeigt, wie eine statische var staticVar mit dem ClassName.var-Syntax erstellt wird:

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

Um auf die statische Variable zuzugreifen, verwenden wir die Eigenschaft .constructor , die einen Verweis auf die Objektkonstruktorfunktion zurückgibt, mit der die Klasse erstellt wurde .. _. Wir können sie in den beiden erstellten Instanzen aufrufen:

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
COil

Es gibt andere ähnliche Antworten, aber keine von ihnen hat mich angesprochen. Hier ist was ich endete mit:

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

Sie können eine statische Variable in JavaScript wie folgt erstellen. Hier ist count die statische Variable.

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

Sie können der statischen Variable Werte zuweisen, indem Sie entweder die Funktion Person oder eine der Instanzen verwenden:

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

Wenn Sie eine globale statische Variable erstellen möchten:

var my_id = 123;

Ersetzen Sie die Variable durch das Folgende:

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

In JavaScript sind die Variablen standardmäßig static . Beispiel:

var x = 0;

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

setInterval(draw, 1000);

Der Wert von x wird alle 1000 Millisekunden um 1 erhöht
Es wird 1,2,3 so weiter drucken

5
Kerim

Um alle Klassenkonzepte hier zusammenzufassen, testen Sie dies:

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

Eine weitere Möglichkeit, Best Practices in diesen Dingen zu betrachten, besteht darin, zu sehen, wie Coffeescript diese Konzepte übersetzt.

#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
Luca Reghellin

Es gibt einen anderen Ansatz, der meine Anforderungen nach Durchsuchen dieses Threads gelöst hat. Es hängt davon ab, was genau Sie mit einer "statischen Variable" erreichen möchten.

Die globale Eigenschaft sessionStorage oder localStorage ermöglicht das Speichern von Daten für die Dauer der Sitzung oder für einen unbestimmten längeren Zeitraum, bis sie explizit gelöscht wird. Dies ermöglicht die gemeinsame Nutzung von Daten zwischen allen Fenstern, Rahmen, Registerkarten, Popups usw. Ihrer Seite/App und ist wesentlich leistungsfähiger als eine einfache "statische/globale Variable" in einem Codesegment.

Es vermeidet alle Probleme mit dem Umfang, der Lebensdauer, der Semantik, der Dynamik usw. der globalen Variablen der obersten Ebene, z. B. Window.myglobal. Ich weiß nicht, wie effizient es ist, aber das ist nicht wichtig für bescheidene Datenmengen, auf die mit bescheidenen Raten zugegriffen wird.

Einfacher Zugriff als "sessionStorage.mydata = irgendwas" und ähnlich abgerufen. Siehe "JavaScript: The Definitive Guide, Sechste Ausgabe", David Flanagan, ISBN: 978-0-596-80552-4, Kapitel 20, Abschnitt 20.1. Dieses kann einfach als PDF durch einfache Suche oder in Ihrem O'Reilly Safaribooks-Abonnement heruntergeladen werden (Gold wert).

4
Greg E

Eine statische Variable ist in JavaScript am nächsten eine globale Variable. Dies ist einfach eine Variable, die außerhalb des Gültigkeitsbereichs einer Funktion oder eines Objektliteral deklariert wurde:

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

Die andere Möglichkeit wäre, globale Variablen wie folgt in einem Objektliteral zu speichern:

var foo = { bar : 1 }

Und greifen Sie dann wie folgt auf die Variablen zu: foo.bar.

4
Andrew Hare

Darüber hinaus gibt es derzeit einen Entwurf ( Phase-2-Vorschlag ) zu ECMA-Vorschlägen , der staticpublic -Felder in Klassen einführt. ( private Felder wurden berücksichtigt )

Anhand des Beispiels aus dem Vorschlag sieht die vorgeschlagene static-Syntax folgendermaßen aus: 

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

und gleichwertig zu den folgenden sein, die andere hervorgehoben haben: 

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

Sie können dann über CustomDate.Epoch darauf zugreifen.

Sie können den neuen Vorschlag in proposal-static-class-features verfolgen. 


Derzeit unterstützt babel diese Funktion mit den Eigenschaften der Klasse transform class plugin, die Sie verwenden können. Obwohl noch in Arbeit, implementiert V8 es

Es gibt vier Möglichkeiten, funktionslokale statische Variablen in Javascript zu emulieren.

Methode 1: Eigenschaften von Funktionsobjekten verwenden (in alten Browsern unterstützt)

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

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

Methode 2: Verwenden einer Schließung, Variante 1 (in alten Browsern unterstützt)

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

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

Methode 3: Verwenden eines Abschlusses, Variante 2 (wird auch in alten Browsern unterstützt)

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

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

Methode 4: Verwenden eines Abschlusses, Variante 3 (erfordert Unterstützung für EcmaScript 2015)

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

someFunc4() ; //prints 1
someFunc4() ; //prints 2
someFunc4() ; //prints 3
1
GetFree

Funktion/classes erlaubt nur einen einzigen Konstruktor für seinen Objektumfang . Function Hoisting, declarations & expressions

  • Mit dem Funktionskonstruktor erstellte Funktionen erstellen keine Schließungen für ihre Erstellungskontexte. Sie werden immer im globalen Bereich erstellt.

      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 - Closure-Kopien funktionieren mit erhaltenen Daten.

  • Die Kopien jedes Abschlusses werden für eine Funktion mit ihren eigenen freien Werten oder Referenzen erstellt. Wenn Sie die Funktion innerhalb einer anderen Funktion verwenden, wird ein Abschluss verwendet.
  • Eine Schließung in JavaScript ist so, als würde eine Kopie aller lokalen Variablen der übergeordneten Funktion von innerFunctions beibehalten.

      function closureFun( args ) {
            // Local variable that ends up within closure
            var num = args;
            num++;
            return function() { console.log(num); }
        }
        var closure1 = closureFun( 5 );
        var closure2 = closureFun( 777 );
        closure1(); // 5
        closure2(); // 777
        closure2(); // 778
        closure1(); // 6
    

ES5-Funktionsklassen: use Object.defineProperty (O, P, Attribute)

Die Object.defineProperty () - Methode definiert eine neue Eigenschaft direkt für ein Objekt oder ändert eine vorhandene Eigenschaft für ein Objekt und gibt das Objekt zurück.

Erstellt einige Methoden mit `` , damit jeder die Funktionsklassen leicht verstehen kann.

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

Das folgende Codefragment dient zum Testen. Jede Instanz verfügt über eine eigene Kopie von Instanzmitgliedern und allgemeinen statischen Mitgliedern.

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

Statische Methodenaufrufe - Aufrufe werden direkt in der Klasse ausgeführt und sind für Instanzen der Klasse nicht aufrufbar. Sie können jedoch die Aufrufe für statische Member innerhalb einer Instanz erreichen.

Syntax verwenden:

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

ES6-Klassen: ES2015-Klassen sind ein einfacher Zucker über dem auf Prototypen basierenden OO -Muster. Die Verwendung eines einzigen deklarativen Formulars erleichtert die Verwendung von Klassenmustern und fördert die Interoperabilität. Klassen unterstützen prototypbasierte Vererbung, Super-Aufrufe, Instanz- und statische Methoden und Konstruktoren.

Beispiel : verweise auf meinen vorherigen Beitrag.

1
Yash

In JavaScript gibt es keine statischen Begriffe oder Schlüsselwörter, aber wir können solche Daten direkt in Funktionsobjekte einfügen (wie in jedem anderen Objekt).

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

Wenn Sie Prototyp verwenden möchten, gibt es einen Weg

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

Auf diese Weise können Sie von jeder Instanz aus auf die Zählervariable zugreifen und jede Änderung der Eigenschaft wird sofort angezeigt.

0
charlie

Probier diese:

Wenn wir eine Eigenschaft definieren und ihre Getter und Setter überschreiben, um die Function Object-Eigenschaft zu verwenden, können Sie theoretisch eine statische Variable in Javascript verwenden

zum Beispiel:

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
user2959417

Ich verwende häufig statische Funktionsvariablen und es ist wirklich schade, dass JS dafür keinen eingebauten Mechanismus hat. Zu oft sehe ich Code, bei dem Variablen und Funktionen in einem äußeren Bereich definiert sind, obwohl sie nur innerhalb einer Funktion verwendet werden. Das ist hässlich, fehleranfällig und verlangt nur Ärger ...

Ich habe mir folgende Methode ausgedacht:

if (typeof Function.prototype.statics === 'undefined') {
  Function.prototype.statics = function(init) {
    if (!this._statics) this._statics = init ? init() : {};
    return this._statics;
  }
}

Dies fügt allen Funktionen eine 'Statik'-Methode hinzu (ja, entspannen Sie sich einfach darüber). Wenn sie aufgerufen wird, fügt sie dem Funktionsobjekt ein leeres Objekt (_statics) hinzu und gibt es zurück. Wenn eine Init-Funktion bereitgestellt wird, wird _statics auf init () gesetzt.

Sie können dann tun:

function f() {
  const _s = f.statics(() => ({ v1=3, v2=somefunc() });

  if (_s.v1==3) { ++_s.v1; _s.v2(_s.v1); }
} 

Vergleicht man dies mit einem IIFE, der die andere richtige Antwort ist, hat dies den Nachteil, dass bei jedem Funktionsaufruf eine Zuweisung hinzugefügt wird und wenn ein '_statics'-Member zu der Funktion hinzugefügt wird. Es gibt jedoch einige Vorteile: Die Oberseite, die nicht in der internen Funktion enthalten ist und eine 'statische' im internen Funktionscode verwendet, ist explizit mit einem '_s'. Präfix, und es ist insgesamt einfacher zu sehen und zu verstehen.

0
kofifus

Bei den anderen Antworten sehe ich also, dass sie die grundlegenden architektonischen Anforderungen eines statischen Attributs in der objektorientierten Programmierung nicht berücksichtigen. 

Objektorientierte Programmierung hat zwei verschiedene Stile, von denen einer "klassenbasiert" ist (C++, C #, Java usw.), der andere "prototypisch" (Javascript). In klassenbasierten Sprachen soll ein 'statisches Attribut' der Klasse und nicht den instanziierten Objekten zugeordnet werden. Dieses Konzept funktioniert in prototypischen Sprachen wie Javascript viel intuitiver, da Sie das Attribut einfach als Wert des übergeordneten Prototyps zuweisen.

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

Und greifen Sie von jedem der Objekte aus zu, die von diesem Konstruktor aus instanziiert werden, wie so ...

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

Wenn Sie jetzt den MyObject.prototype.staticAttribute ändern, wird die Änderung auf die untergeordneten Objekte übertragen, die diese sofort erben. 

Es gibt jedoch ein paar "Gotchas", die die "statische" Natur dieses Attributs erheblich beeinträchtigen oder die Sicherheitsanfälligkeit beeinträchtigen könnten ... 

Stellen Sie zunächst sicher, dass Sie den Konstruktor vor dem globalen Namespace ausblenden, indem Sie ihn in eine andere Funktion wie die jQuery-Methode ready einschließen

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

Zweitens und zum Schluss kann das Attribut auch dann bearbeitet werden, wenn ein anderer Teil Ihres eigenen Skripts verwendet wird. In diesem Fall kann es vorkommen, dass ein Fehler in Ihrem Code über das Attribut eines der untergeordneten Objekte schreibt und entfernt wird Wenn Sie das übergeordnete Attribut ändern, wird es nicht mehr in Kaskade gesetzt und das statische Attribut für das untergeordnete Objekt geändert. Siehe diese jsfiddle. In verschiedenen Szenarien könnten wir entweder Object.freeze(obj), um alle Änderungen am untergeordneten Objekt zu stoppen, oder wir können im Konstruktor eine Setter- und Getter-Methode einrichten und auf eine Schließung zugreifen, wobei beide eine Komplexität aufweisen.

Es scheint mir, dass es kein perfektes Analogon zwischen der klassenbasierten Idee eines 'statischen Attributs' und dieser Javascript-Implementierung gibt. Ich denke, es könnte auf lange Sicht besser sein, ein anderes Codemuster zu verwenden, das Javascript-freundlicher ist. Ein zentraler Datastore oder Cache oder sogar ein dediziertes Hilfsobjekt, das alle erforderlichen statischen Variablen enthält. 

0
lindsaymacvean

Zusammenfassung:

In ES6/ES 2015 wurde das Schlüsselwort class mit einem begleitenden Schlüsselwort static eingeführt. Denken Sie daran, dass dies syntaktischer Zucker über dem prototypischen Vererbungsmodell ist, das javavscript verkörpert. Das static-Schlüsselwort funktioniert folgendermaßen:

class Dog {

  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

}

In Chrome Devtools können wir das gut visualisieren:

 static variables javascript

Nun haben wir eine static-Funktion erstellt, die wir über ClassName.method() ausführen können. 

0

Bei der Arbeit mit MVC-Websites, die jQuery verwenden, möchte ich sicherstellen, dass AJAX - Aktionen in bestimmten Event-Handlern nur ausgeführt werden können, wenn die vorherige Anforderung abgeschlossen ist. Ich verwende dazu eine "statische" jqXHR-Objektvariable.

Gegeben die folgende Schaltfläche:

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

Im Allgemeinen verwende ich ein IIFE für meinen Click-Handler:

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
Todd L

Ich habe den Prototyp benutzt und so hat es funktioniert:

class Cat extends Anima {
  constructor() {
    super(Cat.COLLECTION_NAME);
  }
}

Cat.COLLECTION_NAME = "cats";

oder mit einem statischen Getter:

class Cat extends Anima {
  constructor() {
    super(Cat.COLLECTION_NAME);
  }

  static get COLLECTION_NAME() {
    return "cats"
  }
}
0
EliuX

Für private statische Variablen habe ich diesen Weg gefunden:

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
Martin Wantke

Fensterebenen sind wie Statiken in dem Sinn, dass Sie direkte Referenz verwenden können und diese für alle Teile Ihrer App verfügbar sind

0
Bostone

In JavaScript ist alles entweder ein primitiver Typ oder ein Objekt .. _. Funktionen sind Objekte - (Schlüsselwertpaare). 

Wenn Sie eine Funktion erstellen, erstellen Sie zwei Objekte. Ein Objekt, das die Funktion selbst darstellt, und das andere, das den Prototyp der Funktion darstellt. 

Funktion ist im Grunde ein Objekt mit den Eigenschaften:

function name, 
arguments length 
and the functional prototype.

Wo also die statische Eigenschaft gesetzt werden soll: Zwei Stellen, entweder innerhalb des Funktionsobjekts oder innerhalb des Funktionsprototypobjekts. 

Hier ist ein Ausschnitt, der erstellt, dass das Ende sogar zwei Instanzen mit dem new-JavaScript-Schlüsselwort instanziiert.

function C () { // function
  var privateProperty = "42";  
  this.publicProperty = "39";  
  
  this.privateMethod = function(){ 
   console.log(privateProperty);
  };
}

C.prototype.publicMethod = function () {    
  console.log(this.publicProperty);
};

C.prototype.staticPrototypeProperty = "4";
C.staticProperty = "3";


var i1 = new C(); // instance 1
var i2 = new C(); // instance 2

i1.privateMethod();
i1.publicMethod();

console.log(i1.__proto__.staticPrototypeProperty);
i1.__proto__.staticPrototypeProperty = "2";
console.log(i2.__proto__.staticPrototypeProperty);

console.log(i1.__proto__.constructor.staticProperty);
i1.__proto__.constructor.staticProperty = "9";
console.log(i2.__proto__.constructor.staticProperty);

Die Hauptidee ist, dass die Instanzen i1 und i2 dieselben statischen Eigenschaften verwenden.

0
prosti

In Javascript gibt es keine statischen Variablen. Diese Sprache ist objektorientiert auf Prototypen ausgerichtet, daher gibt es keine Klassen, sondern Prototypen, von denen sich Objekte selbst "kopieren".

Sie können sie mit globalen Variablen oder mit Prototypen simulieren (dem Prototyp eine Eigenschaft hinzufügen):

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

Ich habe diese Idee in keiner der Antworten gesehen und sie einfach der Liste hinzugefügt. Wenn es sich um ein Duplikat handelt, lass es mich einfach wissen und ich werde es löschen und das andere bestätigen.

Ich habe auf meiner Website eine Art Super Global erstellt. Da ich mehrere js-Dateien habe, die auf jede Seite geladen werden, und Dutzende anderer js-Dateien, die nur auf einigen Seiten geladen werden, füge ich die gesamte "globale" Funktion in einer einzigen globalen Variablen zusammen.

Am Anfang meiner ersten eingeschlossenen "globalen" Dateien steht die Deklaration

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

Dann kümmere ich mich um mehrere globale Helferfunktionen

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

Wenn ich dann eine statische Variable brauche, speichere ich sie einfach außerhalb des Gültigkeitsbereichs, z. B. außerhalb des Dokuments, oder außerhalb der Verhaltensanhänge. (Ich verwende jquery, aber es sollte in Javascript funktionieren.)

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

Dies ist natürlich eine globale, keine statische, aber da es bei jedem Laden der Seite neu initialisiert wird, erfüllt es denselben Zweck.

0
danielson317

Normalerweise verwende ich diese Methode aus zwei Hauptgründen:

wenn ich lokale Werte speichern möchte, verwende ich so etwas wie "Local.x", "Local.y", "Local.TempData" usw.!

Wenn ich statische Werte für Funktionen speichern möchte, verwende ich etwas wie "Static.o", "Static.Info", "Static.count" usw.!

[Update2]: Gleiche Methode, aber IIFE-Ansatz!

[Update1]: "Static" und "Local" Objekte für Funktionen werden automatisch durch Vorbearbeitungsskripten erstellt!

0
User