Variables statiques en JavaScript

comment créer des variables statiques en Javascript?

619
demandé sur Matt 2009-10-08 08:31:25

30 réponses

si vous venez d'un langage objet statiquement typé basé sur une classe (comme Java, C++ ou C#) je suppose que vous essayez de créer une variable ou une méthode associée à un" type " mais pas à une instance.

un exemple utilisant une approche "classique", avec des fonctions de constructeur peut-être pourrait vous aider à attraper les concepts de base 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 est défini dans l'objet MyClass (qui est une fonction) et n'a rien à voir avec ses instances créées, JavaScript traite les fonctions comme objets de première classe , donc étant un objet, vous pouvez assigner des propriétés à une fonction.

801
répondu CMS 2018-03-11 18:01:06

vous pourriez profiter du fait que les fonctions JS sont aussi des objets -- ce qui signifie qu'ils peuvent avoir des propriétés.

par exemple, citant l'exemple donné sur l'article (maintenant disparu) variables statiques en 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);
}

Si vous appelez cette fonction plusieurs fois, vous verrez que le compteur est incrémenté.

et c'est probablement une bien meilleure solution que de polir le espace de noms global avec une variable globale.



Et voici une autre solution possible, basée sur une fermeture: astuce pour utiliser des variables statiques en 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.

qui vous obtient le même genre de résultat -- sauf, cette fois, la valeur incrémentée est retournée, au lieu de s'afficher.

500
répondu Pascal MARTIN 2014-08-22 14:30:00

vous le faites par L'intermédiaire D'une vie (expression de fonction immédiatement invoquée):

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

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

incr(); // returns 1
incr(); // returns 2
79
répondu khoomeister 2013-03-30 10:02:35

vous pouvez utiliser des arguments.le destinataire de l'appel à stocker "statique", les variables (ce qui est utile dans la fonction anonyme):

function () {
  arguments.callee.myStaticVar = arguments.callee.myStaticVar || 1;
  arguments.callee.myStaticVar++;
  alert(arguments.callee.myStaticVar);
}
39
répondu gpilotino 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
répondu jim_zike_huang 2012-02-28 20:08:00

j'ai vu quelques réponses similaires, mais j'aimerais mentionner que ce post le décrit le mieux, donc je voudrais le partager avec vous.

voici un code extrait de celui-ci, que j'ai modifié pour obtenir un exemple complet qui, espérons-le, profitera à la communauté car il peut être utilisé comme modèle de conception pour les classes.

il répond aussi à votre question:

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

étant donné cet exemple, vous pouvez accéder au propriétés/fonctions statiques comme suit:

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

Et le propriétés de l'objet/fonctions simplement comme:

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

Note que dans podcast.immuablprop (), nous avons un fermeture : la référence à _somePrivateVariable est conservée à l'intérieur de la fonction.

Vous pouvez même définir des getters et les setters . Regardez cet extrait de code (où d est le prototype de l'objet pour lequel vous souhaitez déclarer une propriété, y est une variable privée non visible à l'extérieur du constructeur):

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

il définit la propriété d.year via get et set fonctions - si vous ne spécifiez pas set , alors la propriété est en lecture seule et ne peuvent pas être modifiés (soyez conscient que vous n'obtiendrez pas une erreur si vous essayez de le définir, mais il n'a pas d'effet). Chaque propriété a les attributs writable , configurable (permettre de changer après la déclaration) et enumerable (permettre de l'utiliser comme recenseur), qui sont par défaut false . Vous pouvez les définir via defineProperty dans le troisième paramètre, par exemple enumerable: true .

ce qui est aussi valide est cette syntaxe:

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

qui définit une propriété lisible / inscriptible a , une propriété en lecture seule b et une propriété en écriture seule c , à travers laquelle la propriété a peut être consultée.

Utilisation:

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

Notes:

pour éviter un comportement inattendu dans le cas où vous avez oublié le mot-clé new , je vous suggère d'ajouter ce qui suit à la fonction Podcast :

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

maintenant les deux instanciations suivantes fonctionneront comme prévu:

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

l'instruction " new "crée un nouvel objet et copie toutes les propriétés et méthodes, i.e.

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"

Notez aussi, que dans certaines situations il peut être utile d'utiliser la déclaration return dans la fonction constructeur Podcast pour retourner un objet personnalisé la protection des fonctions de la classe dépend à l'interne, mais qui doivent être exposées. Ceci est expliqué plus en détail dans le chapitre 2 (objets) de la série d'articles.

vous pouvez dire que a et b héritent de Podcast . Maintenant, si vous souhaitez ajouter une méthode de Podcast qui s'applique à tous après a et b ont été instanciée? Dans ce cas, utilisez le .prototype comme suit:

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

Maintenant appelez a et b encore une fois:

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

vous pouvez trouver plus de détails sur les prototypes ici . Si vous voulez faire plus d'héritage, je suggère de regarder dans ce .


Le article de la série je l'ai mentionné ci-dessus sont hautement recommandé à lire, ils comprennent également les rubriques suivantes:

  1. fonctions
  2. objets
  3. Prototypes
  4. l'Application d'un Nouveau Constructeur sur les Fonctions
  5. hissage
  6. Insertion Automatique De Point-Virgule
  7. propriétés statiques et méthodes

Note que le point-virgule automatique l'insertion "fonctionnalité" de JavaScript (comme mentionné dans 6.) est très souvent responsable de causer des problèmes étranges dans votre code. Donc, je préfère le considérer comme un bug que comme une caractéristique.

si vous voulez en savoir plus, ici est un tout à fait intéressant article MSDN sur ces sujets, certains d'entre eux décrits il fournir encore plus de détails.

Ce qui est il est intéressant de lire ainsi (couvrant également les sujets mentionnés ci-dessus) sont les articles du MDN JavaScript Guide :

Si vous voulez savoir comment émuler c# out paramètres (comme dans DateTime.TryParse(str, out result) ) en JavaScript, vous pouvez trouver exemple de code ici.


ceux d'entre vous qui sont travaillant avec IE (qui n'a pas de console pour JavaScript à moins que vous n'ouvrez les outils de développement en utilisant F12 et ouvrez l'onglet console) pourrait trouver l'extrait suivant utile. Il vous permet d'utiliser console.log(msg); comme utilisé dans les exemples ci-dessus. Il suffit de l'insérer avant la fonction Podcast .

pour votre commodité, voici le code ci-dessus en un seul morceau de code complet:

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>

Notes:

  • quelques bons conseils, conseils et recommandations sur la programmation JavaScript en général, vous pouvez trouver ici (JavaScript meilleures pratiques) et il ('var' contre 'laisser') . Aussi recommandé est cet article au sujet des typographies implicites (coercition) .

  • une façon pratique d'utiliser les classes et de les compiler en JavaScript est le code dactylographique. Voici une aire de jeux où vous pouvez trouver quelques exemples vous montrant comment cela fonctionne. Même si vous n'utilisez pas de code pour le moment, vous pouvez jeter un coup d'oeil car vous pouvez comparer le code avec le résultat JavaScript sur une vue côte à côte. La plupart des exemples sont simples, mais il y a aussi un exemple Raytracer que vous pouvez essayer instantanément. Je recommande particulièrement de regarder dans les exemples "utiliser des Classes"," utiliser L'héritage " et "utiliser des génériques" en les sélectionnant dans le combobox - ce sont de beaux modèles que vous pouvez utiliser instantanément dans JavaScript.

  • pour réaliser encapsulation de variables locales, fonctions etc en JavaScript, je suggère d'utiliser un modèle comme le suivant (JQuery utilise la même technique):

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

bien sûr, vous pouvez - et devriez - mettre le code du script dans un *séparé.fichier js; c'est juste écrit en ligne pour garder l'exemple de court.

27
répondu Matt 2018-07-02 07:46:11

mise à jour de la réponse:

dans ECMAScript 6 , vous pouvez créer des fonctions statiques en utilisant le static mot clé:

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

ES6 n'introduisent pas de nouvelle sémantique pour la statique. Vous pouvez faire la même chose dans ES5 comme ceci:

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

vous pouvez affecter à une propriété de Foo parce que dans les fonctions JavaScript sont des objets.

21
répondu Max Heiber 2018-04-05 00:06:18

, L'exemple et l'explication du livre Professionnel JavaScript pour Développeurs Web 2e Édition par Nicholas Zakas. C'est la réponse que je cherchais, alors j'ai pensé qu'il serait utile d'ajouter ici.

(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

dans cet exemple, le constructeur Person a accès au nom de la variable privée, tout comme les méthodes getName() et setName() . En utilisant ce modèle, la variable de nom devient statique et sera utilisée parmi tous instance. Cela signifie qu'appeler setName() sur une instance affecte toutes les autres instances. L'appel à setName() ou la création d'une nouvelle instance Person définit la variable name à une nouvelle valeur. Cela fait que toutes les instances retournent la même valeur.

16
répondu Nate 2011-12-13 08:29:57

si vous voulez déclarer des variables statiques pour créer des constantes dans votre application, alors j'ai trouvé la suite comme approche la plus simpliste

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
répondu Hemant 2013-04-02 22:05:45

à Propos de la class mis en place par ECMAScript 2015. Les autres réponses ne sont pas totalement claires.

voici un exemple montrant comment créer un var statique staticVar avec le ClassName . var syntaxe:

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

pour accéder à la variable statique, nous utilisons la propriété .constructor qui renvoie une référence à la fonction du constructeur d'objets qui a créé la classe. Nous peut l'appeler sur les deux instances créées:

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
répondu COil 2017-03-24 10:02:17

il y a d'autres réponses similaires, mais aucune ne m'a plu. Voici ce que j'ai:

var nextCounter = (function () {
  var counter = 0;
  return function() {
    var temp = counter;
    counter += 1;
    return temp;
  };
})();
6
répondu funroll 2015-02-08 03:34:27

vous pouvez créer une variable statique en JavaScript comme ceci ci-dessous. Ici count est la variable statique.

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

vous pouvez attribuer des valeurs à la variable statique en utilisant soit la fonction Person , soit l'une des instances:

// 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
répondu Sнаđошƒаӽ 2016-09-23 04:44:32

si vous voulez faire une variable statique globale:

var my_id = 123;

remplacer la variable par la suivante:

Object.defineProperty(window, 'my_id', {
    get: function() {
            return 123;
        },
    configurable : false,
    enumerable : false
});
5
répondu JoolzCheat 2012-03-16 03:56:46

dans les variables JavaScript sont statique par défaut. exemple :

var x = 0;

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

setInterval(draw, 1000);

la valeur de x est incrémentée de 1 toutes les 1000 millisecondes
151990920" Il permet d'imprimer 1,2,3 etc

5
répondu Kerim 2018-09-19 15:16:49

la chose la plus proche dans JavaScript à une variable statique est une variable globale - c'est simplement une variable déclarée en dehors de la portée d'une fonction ou d'un objet littéral:

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

L'autre chose que vous pourriez faire serait de stocker des variables globales à l'intérieur d'un objet littéral comme ceci:

var foo = { bar : 1 }

et ensuite accéder aux variabels comme ceci: foo.bar .

4
répondu Andrew Hare 2009-10-08 04:33:29

il y a une autre approche, qui a résolu mes exigences après avoir parcouru ce fil. Cela dépend exactement ce que vous voulez atteindre avec une "variable statique".

la propriété globale sessionStorage ou localStorage permet de stocker des données pour la durée de la session, ou pour une période indéfinie plus longue jusqu'à ce qu'elles soient explicitement effacées, respectivement. Cela permet aux données d'être partagées entre toutes les fenêtres, les cadres, les panneaux d'onglets, les popups etc de votre page / application et est beaucoup plus puissant qu'une simple" variable statique/globale " dans un segment de code.

il évite tous les tracas avec la portée, la durée de vie, la sémantique, la dynamique etc des variables globales de haut niveau, c'est-à-dire fenêtre.myglobal. Je ne sais pas si c'est efficace, mais ce n'est pas important pour des quantités modestes de données, accessibles à des taux modestes.

facilement accessible en tant que "sessionStorage.mydata = rien" et récupéré de la même façon. Voir "JavaScript: The Definitive Guide, Sixth Edition", David Flanagan, ISBN: 978-0-596-80552-4, Chapitre 20, section 20.1. Vous pouvez facilement le télécharger sous forme de PDF par simple recherche, ou dans votre abonnement à O'Reilly Safaribooks (qui vaut son pesant d'or).

Cheers, Greg E

4
répondu Greg E 2013-04-07 10:03:30

pour condenser tous les concepts de classe ici, tester ceci:

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

Eh bien, une autre façon de jeter un coup d'oeil aux meilleures pratiques dans ces choses, est de voir comment coffeescript traduit ces concepts.

#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
répondu Stratboy 2013-11-24 15:15:45

en plus du reste, il y a actuellement un projet ( proposition de l'étape 2 ) sur propositions de L'ECMA qui introduit static public champs dans les classes. ( champs privés ont été considérés comme )

en utilisant l'exemple de la proposition, la syntaxe proposée static ressemblera à ceci:

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

et être l'équivalent des valeurs suivantes: ce que d'autres ont souligné:

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

vous pouvez alors y accéder via CustomDate.epoch .

vous pouvez suivre la nouvelle proposition en proposal-static-class-features .


actuellement, babel supporte cette fonctionnalité avec le plugin transform class properties que vous pouvez utiliser. En outre, bien que toujours en cours, V8 est mise en œuvre it .

3
répondu Jim Fasarakis Hilliard 2018-02-07 22:27:26

dans JavaScript, il n'y a aucun terme ou mot-clé statique, mais nous pouvons mettre ces données directement dans l'objet de fonction (comme dans tout autre objet).

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
répondu Satyapriya Mishra 2016-03-31 18:05:07

Function's / classes ne permet qu'un seul constructeur pour la portée de son objet. Function Hoisting, declarations & expressions

  • les fonctions créées avec la fonction constructeur ne créent pas de fermetures à leurs contextes de création; elles sont toujours créées dans le cadre global.

      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)
    

fermetures - les copies de fermeture sont des fonctions avec des données conservées.

  • chaque copie de fermeture est créée pour une fonction avec ses propres valeurs libres ou références, chaque fois que vous utilisez une fonction à l'intérieur d'une autre fonction, une fermeture est utilisée.
  • une fermeture en JavaScript est comme maintenir une copie de toutes les variables locales de sa fonction mère par les fonctions internes.

      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 classes de fonctions : utilise objet.defineProperty ( O, P, Attributs )

L'Objet .defineProperty() méthode définit une nouvelle propriété directement sur un objet, ou modifie une propriété sur un objet, et renvoie l'objet.

a créé certaines méthodes en utilisant ` , de sorte que chaque fois peut comprendre les classes de fonction facilement.

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

ci-dessous code snippet est de tester que chaque instance a sa propre copie des membres d'instance et des membres statiques communs.

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

méthode statique les appels sont faits directement sur la classe et ne sont pas appelables sur les instances de la classe. Mais vous pouvez réaliser les appels de membres statiques à partir d'une instance.

utilisant la syntaxe:

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

Classes ES6: les classes ES2015 sont un simple sucre par rapport au modèle d'OO basé sur le prototype. Le fait d'avoir une seule forme déclarative pratique facilite l'utilisation des modèles de classe et favorise l'interopérabilité. Les Classes prennent en charge les héritages basés sur des prototypes, les super-appels, les instances et les méthodes statiques et les constructeurs.

exemple : voir mon post précédent.

1
répondu Yash 2017-12-09 13:07:36

il y a 4 façons d'émuler une fonction-les variables statiques locales en Javascript.

Méthode 1: Utilisation de la fonction propriétés de l'objet (pris en charge par d'anciens navigateurs)

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

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

Méthode 2: Utilisation d'une fermeture, variante 1 (compatible avec les anciens navigateurs)

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

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

Méthode 3: Utilisation d'une fermeture, variante 2 (également prise en charge dans les anciens navigateurs)

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

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

Méthode 4: à l'Aide d'une fermeture, la variante 3 (exige le soutien de la EcmaScript 2015)

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

someFunc4() ; //prints 1
someFunc4() ; //prints 2
someFunc4() ; //prints 3
1
répondu GetFree 2018-04-26 02:05:17

vars de niveau de fenêtre sont comme statics dans le sens où vous pouvez utiliser une référence directe et ceux-ci sont disponibles pour toutes les parties de votre application

0
répondu Bostone 2009-10-08 04:34:16

il n'existe pas de variable statique en Javascript. Ce langage est basé sur un prototype orienté objet, il n'y a donc pas de classes, mais des prototypes à partir desquels les objets se "copient" eux-mêmes.

vous pouvez les simuler avec des variables globales ou avec prototypage (ajout d'une propriété au prototype):

function circle(){
}
circle.prototype.pi=3.14159
0
répondu Gerardo 2009-10-08 04:38:06

en travaillant avec les sites MVC qui utilisent jQuery, j'aime m'assurer que les actions AJAX dans certains gestionnaires d'événements ne peuvent être exécutées qu'une fois la requête précédente terminée. J'utilise une variable d'objet" statique " jqXHR pour y parvenir.

avec le bouton Suivant:

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

j'utilise généralement une vie comme celle-ci pour mon gestionnaire de clic:

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
répondu Todd L 2014-03-17 21:13:48

si vous voulez utiliser prototype puis il ya un moyen

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

en faisant cela, vous pourrez accéder à la variable counter à partir de n'importe quelle instance et tout changement dans la propriété sera immédiatement reflété!!

0
répondu charlie 2014-05-09 06:25:42

donc ce que je vois avec les autres réponses est qu'elles ne traitent pas de l'exigence architecturale fondamentale d'un attribut statique dans la programmation orientée objet.

la programmation orientée Objet a en fait deux styles différents est 'classe' (C++, C#, Java, etc), l'autre est 'prototypes' (Javascript). Dans les langages basés sur les classes, un "attribut statique" est censé être associé à la classe et non aux objets instanciés. Ce concept fonctionne réellement beaucoup plus intuitivement dans un langage prototypique comme Javascript parce que vous assignez juste l'attribut comme une valeur du prototype parent comme ainsi.

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

Et y accéder à partir de tous les objets instanciés à partir de ce constructeur comme si...

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

maintenant si vous allez de l'avant et changez le MyObject.prototype.staticAttribute le changement se répercutera vers le bas aux objets enfant qui héritent immédiatement.

cependant il sont quelques ' gotchas 'qui pourraient miner de manière significative la nature' statique ' de cet attribut, ou tout simplement laisser la vulnérabilité de sécurité...

tout D'abord, assurez-vous de cacher le constructeur de L'espace de noms Global en l'enfermant dans une autre fonction comme la méthode 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
});

Deuxièmement et enfin, même si vous faites cela, l'attribut est toujours modifiable à partir de n'importe quelle autre partie de votre propre script, donc il pourrait être le cas qu'un bug dans votre code écrit sur l'attribut sur un des objets enfants et le détache de la mère prototype, donc si vous changez l'attribut parent, il ne sera plus cascade et de modifier l'attribut statique de l'objet enfant. voir ce jsfiddle. dans différents scénarios, nous pourrions soit Object.freeze(obj) pour arrêter tout changement à l'objet enfant, ou nous pourrions mettre en place une méthode setter et getter dans le constructeur et accéder à une fermeture, ces deux ont des complexités associées.

il me semble qu'il n'y a pas d'analogie parfaite entre l'idée d'un "attribut statique" basée sur la classe et cette implémentation Javascript. Donc, je pense qu'il pourrait être préférable à long terme d'utiliser un modèle de code différent qui est plus Javascript convivial. Comme un datastore central ou un cache ou même un objet helper dédié pour contenir toutes les variables statiques nécessaires.

0
répondu lindsaymacvean 2015-11-11 03:01:24

Je n'ai vu cette idée dans aucune des réponses donc je l'ai juste ajoutée à la liste. Si c'est un duplicata, dites-le-moi, je le supprimerai et je ferai monter l'autre.

j'ai créé une sorte de super global sur mon site. Depuis que j'ai plusieurs fichiers js qui sont chargés sur chaque chargement de page et des douzaines d'autres fichiers js qui ne sont chargés que sur certaines pages, j'ai mis toute la fonction "global" dans une seule variable globale.

au sommet de mon premier inclus "global" des fichiers est la déclaration

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

Puis-je delcare plusieurs fonctions d'assistance global

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

alors si j'ai besoin d'une variable statique, je la stocke simplement en dehors de la portée, par exemple en dehors du document prêt ou en dehors de la pièce jointe de comportement. (J'utilise jquery, mais il faut travailler dans le 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;
}

c'est bien sûr un global pas un statique mais comme il est réinitialisé sur chaque charge de page il accomplit le même but.

0
répondu danielson317 2016-02-12 16:45:17

pour les variables statiques privées, j'ai trouvé cette façon:

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
répondu Martin Wantke 2016-10-25 12:42:02

essayez celui-ci:

si nous définissons une propriété et que nous outrepassons ses getters et setters pour utiliser la propriété D'objet de fonction, alors en théorie vous pouvez avoir une variable statique en javascript

par exemple:

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
répondu user2959417 2016-11-09 18:57:32