JavaScript'teki statik değişkenler


716

Javascript'te nasıl statik değişkenler oluşturabilirim?


"dispaly: none" stil özniteliğiyle etiket veya diğer html etiketlerini tanımlayabilir ve bu değer ve bu değer üzerinde işlem için değişken değer ayarlayabiliriz. Çok zorlamayız.
asghar

Bulduğum en basit çözüm: sınıfta hiç statik bir değişken tanımlamayın. Statik bir değişken kullanmak istediğinizde, orada tanımlayın ve sonra örn someFunc = () => { MyClass.myStaticVariable = 1; }. Ardından, statik üyeyi döndürmek için statik bir yöntem oluşturun, örn static getStatic() { return MyClass.myStaticVariable; }. O zaman sadece MyClass.getStatic()statik verileri elde etmek için sınıfın dışından arayabilirsiniz !
Pixel

Yanıtlar:


863

Sınıf tabanlı, statik olarak yazılmış nesne yönelimli bir dilden (Java, C ++ veya C # gibi) geliyorsanız, bir örnekle değil, bir "tür" ile ilişkili bir değişken veya yöntem oluşturmaya çalıştığınızı varsayıyorum.

Yapıcı işlevlerle "klasik" bir yaklaşım kullanan bir örnek, temel OO JavaScript kavramlarını yakalamanıza yardımcı olabilir:

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

staticPropertyMyClass nesnesinde (bir işlevdir) tanımlanır ve oluşturulan örnekleriyle hiçbir ilgisi yoktur, JavaScript işlevleri birinci sınıf nesneler olarak görür , böylece bir nesne olarak, bir işleve özellikler atayabilirsiniz.

GÜNCELLEME: ES6 , anahtar kelime aracılığıyla sınıf bildirme özelliğini tanıttı class. Mevcut prototip tabanlı kalıtım üzerinde sözdizimi şekeri.

staticAnahtar kelime kolayca bir sınıfta statik özelliklerine veya yöntemlerine tanımlamanızı sağlar.

ES6 sınıflarıyla uygulanan yukarıdaki örneğe bakalım:

class MyClass {
  // class constructor, equivalent to
  // the function body of a constructor
  constructor() {
    const privateVariable = 'private value'; // Private variable at the constructor scope
    this.publicVariable = 'public value'; // Public property

    this.privilegedMethod = function() {
      // Public Method with access to the constructor scope variables
      console.log(privateVariable);
    };
  }

  // Prototype methods:
  publicMethod() {
    console.log(this.publicVariable);
  }

  // Static properties shared by all instances
  static staticProperty = 'static value';

  static staticMethod() {
    console.log(this.staticProperty);
  }
}

// We can add properties to the class prototype
MyClass.prototype.additionalMethod = function() {
  console.log(this.publicVariable);
};

var myInstance = new MyClass();
myInstance.publicMethod();       // "public value"
myInstance.additionalMethod(); // "public value"
myInstance.privilegedMethod(); // "private value"
MyClass.staticMethod();             // "static value"


5
Muhtemelen privilegedMethodMyClass örneğinde çağrılabilir gibi görünüyor çünkü OO özel bir yöntemle eşdeğer değil mi? Yani erişebildiği için ayrıcalıklı mı demek istiyorsun privateVariable?
Dónal

3
Can not this.constructor"örneği yöntemleri" statik değişkenleri erişmek için kullanılabilir? Cevabınız evet ise, cevaba eklemeye değer.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

1
Örneğinizde statik işlevlerden de bahsedebilirsiniz .
David Rodrigues

18
merhaba, bu çizgiyi kabul ettiğimden emin değilim // Statik değişken tüm 'MyClass.staticProperty = "baz"; olarak bana infers Eğer 'myInstance.staticProperty' dan baz bulabilmesi o hangi elbette bunu yapamazsınız.
fullstacklife

5
Belki de MyClass.prototype.staticProperty = "baz";statik özelliğin anonim bir işlev olarak tanımlanması MyClass.prototype.staticProperty = function () {return staticVar;}ve böylece tüm örneklerin bir ayarlayıcıyla da değiştirilebilen tek bir değişkene erişmesi için OO ilkelerini okuması veya daha doğru olması gerekir .
lindsaymacvean

536

JS işlevlerinin aynı zamanda nesne olduğu gerçeğinden de yararlanabilirsiniz - bu özelliklerin özellikleri olabilir.

Örneğin, Javascript'teki Statik değişkenler (şimdi yok oldu) makalesinde verilen örneği alıntılamak :

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

Bu işlevi birkaç kez çağırırsanız, sayacın artırıldığını görürsünüz.

Ve bu muhtemelen küresel isim alanını küresel bir değişkenle kirletmekten çok daha iyi bir çözümdür.


Ve burada bir kapanışa dayalı başka bir olası çözüm var: Javascript'te statik değişkenleri kullanma hilesi :

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.

Bu size aynı sonucu verir - bu sefer hariç, artan değer görüntülenmek yerine döndürülür.


50
kısayol olarak, countMyself.counter = countMyself.counter || initial_value;statik değişken asla falsey olmayacaksa (false, 0, null veya boş dize) yapabilirsiniz
Kip

3
Biraz daha kısa ve net: (function () {var id = 0; function uniqueID () {return id ++;};}) ();
Tom Robinson

3
Kapanma sayacı Firefox'taki sınıftan çok daha hızlı. jsperf.com/static-counter-in-class-vs-in-closure
Sony Santos

Kontroller ===için kullanın , typeofbazı tuhaf baskılar alacaksınız.
dewd

@SonySantos Testiniz Firefox 40 için tersi gösteriyor
bartolo-otrit

96

Bunu bir IIFE (hemen çağrılan işlev ifadesi) aracılığıyla yaparsınız:

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

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

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

21
Bunu JavaScript'te yapmanın en deyimsel yolu olduğunu söyleyebilirim. Çok kötü, muhtemelen diğer dillerden gelen insanlar için daha lezzetli olan diğer yöntemler sayesinde çok fazla upvotes almıyor.

1
Sadece 'IIFE' yerine 'kapatma' kullanarak yeniden ifade ederdim.
zendka

39

arguments.callee komutunu kullanarak "statik" değişkenleri saklayabilirsiniz (anonim işlevde de yararlıdır):

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

3
Anlayabildiğim kadarıyla, bu yöntemin pascal MARTIN'in yoluna göre bir (sadece bir?) Avantajı var: anonim işlevlerde kullanabilirsiniz. Bunun bir örneği harika olurdu
Dan

27
arguments.calleekullanımdan kaldırıldı.
Quolonel Soruları

Ben her zaman JS çok saçma, ama calleesahip olmak güzel bir şey gibi görünüyordu. Acaba neden bu itiraz karar verdi ...: |
user2173353

35

Birkaç benzer cevap gördüm, ancak bu yazının en iyi açıkladığını belirtmek isterim, bu yüzden sizinle paylaşmak istiyorum.

İşte onlardan alınan bazı kodlar, umarım topluluğa fayda sağlayan tam bir örnek almak için değiştirdim çünkü sınıflar için bir tasarım şablonu olarak kullanılabilir.

Ayrıca sorunuza cevap verir:

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

Bu örnek verildiğinde, statik özelliklere / işleve aşağıdaki gibi erişebilirsiniz :

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

Ve nesne özellikleri / işlevleri basitçe şöyle:

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

Not podcast.immutableProp () 'deki, bir sahiptir kapatma : _somePrivateVariable referans işlevi içinde tutulur.

Alıcıları ve ayarlayıcıları bile tanımlayabilirsiniz . Bu kod snippet'ine bir göz atın ( dbir özelliği bildirmek istediğiniz nesnenin prototipi burada , yyapıcı dışında görünmeyen özel bir değişkendir):

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

Bu özellik tanımlar d.yeararacılığı getile setbelirttiğiniz yoksa - fonksiyonlar set, daha sonra özelliği salt okunur ve değiştirilemez (bunu ayarlamaya çalışırsanız bir hata almazsınız farkında, ancak hiçbir etkisi yoktur). Her özellik özelliklere sahiptir writable, configurable(ilanından sonra değişikliğe izin) ve enumerablevarsayılan başınadır, (sýralayýcý olarak kullanmak için izin) false. Bunları defineProperty3. parametrede ayarlayabilirsiniz , örn enumerable: true.

Geçerli olan bu sözdizimidir:

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

okunabilir / yazılabilir bir özelliği a, salt okunur bir özelliği bve cbu özelliğe aerişilebilen salt okunur bir özelliği tanımlar .

Kullanımı:

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

Notlar:

newAnahtar kelimeyi unutmanız durumunda beklenmedik davranışlardan kaçınmak için, işleve aşağıdakileri eklemenizi öneririz Podcast:

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

Şimdi aşağıdaki örneklerin her ikisi de beklendiği gibi çalışacaktır:

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

'New' ifadesi yeni bir nesne oluşturur ve tüm özellikleri ve yöntemleri kopyalar;

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"

Ayrıca, bazı durumlarda sınıfın dahili olarak dayandığı ancak ortaya çıkarılması gereken özel bir nesne koruma işlevlerini döndürmek returniçin yapıcı işlevindeki ifadeyi kullanmanın yararlı olabileceğini unutmayın Podcast. Bu, makale serisinin 2. bölümünde (Nesneler) daha ayrıntılı olarak açıklanmaktadır.

Bunu söyleyebilir ave bmiras alabilirsiniz Podcast. Şimdi, Podcast'e sonradan hepsi için geçerli olan ave bsomutlaştırılmış bir yöntem eklemek isterseniz ne olacak ? Bu durumda, .prototypeaşağıdaki gibi kullanın :

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

Şimdi diyoruz ave byine:

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

Prototipler hakkında daha fazla bilgiyi burada bulabilirsiniz . Daha devralma yapmak istiyorsanız, ben içine bakarak öneririz bu .


Yazı dizisi Yukarıda sözünü ettiğim edilir şiddetle tavsiye okumak için, onlar da aşağıdaki konuları içerir:

  1. Fonksiyonlar
  2. Nesneler
  3. prototipleri
  4. Yapıcı İşlevlerinde Yeniyi Zorlamak
  5. kaldırma
  6. Otomatik Noktalı virgül ekleme
  7. Statik Özellikler ve Yöntemler

Not olduğunu otomatik noktalı virgül ekleme (aynı 6'da belirtilen) JavaScript "özelliği" çok sık garip şifreli sorunlarına neden sorumludur. Bu nedenle, onu bir özellik olarak bir hata olarak görmeyi tercih ederim.

Daha fazla okumak isterseniz, işte bu konularla ilgili oldukça ilginç bir MSDN makalesi var, bazıları burada daha fazla ayrıntı sunuyor.

Okumak ilginç olan şey (yukarıda belirtilen konuları da kapsayan) MDN JavaScript Kılavuzu'ndaki makalelerdir :

JavaScript'te c # outparametrelerini (içinde olduğu gibi DateTime.TryParse(str, out result)) nasıl taklit edeceğinizi öğrenmek istiyorsanız, örnek kodu burada bulabilirsiniz .


IE ile çalışanlarınız (geliştirici araçlarını F12konsol sekmesini kullanarak açıp açmadığınız sürece JavaScript için konsolu olmayanlar ) aşağıdaki snippet'i yararlı bulabilir. console.log(msg);Yukarıdaki örneklerde kullanıldığı gibi kullanmanıza izin verir . Sadece Podcastfonksiyondan önce takın .

Size kolaylık sağlamak için, yukarıdaki kodu tek bir tam kod snippet'inde bulabilirsiniz:


Notlar:

  • Genel olarak JavaScript programlama hakkında bazı iyi ipuçlarını, ipuçlarını ve önerileri burada bulabilirsiniz (JavaScript en iyi uygulamaları) ve orada ('var' karşı 'let') . Örtülü daktilolar (baskı) ile ilgili bu makale de önerilmektedir .

  • Sınıfları kullanmanın ve JavaScript'e derlemenin kullanışlı bir yolu TypeScript'tir. İşte size nasıl çalıştığını gösteren bazı örnekler bulabileceğiniz bir oyun alanı . Şu anda TypeScript kullanmasanız bile, bir bakabilirsiniz çünkü TypeScript'i yan yana görünümde JavaScript sonucuyla karşılaştırabilirsiniz. Çoğu örnek basittir, ancak anında deneyebileceğiniz bir Raytracer örneği de vardır. Özellikle "Sınıfları Kullanma", "Devralmayı Kullanma" ve "Generics'i Kullanma" örneklerine birleşik giriş kutusunda seçerek bakmanızı öneririm - bunlar anında JavaScript'te kullanabileceğiniz güzel şablonlardır. Dizgi, Açısal ile kullanılır .

  • JavaScript'te yerel değişkenlerin, işlevlerin vb. Kapsüllenmesini sağlamak için aşağıdaki gibi bir desen kullanmanızı öneririm (JQuery aynı tekniği kullanır):

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

Tabii ki, kod kodunu ayrı bir *.jsdosyaya koyabilir ve koymalısınız ; bu sadece örneği kısa tutmak için satır içi olarak yazılmıştır.

Kendiliğinden çalışan işlevler (IIFE = Hemen Çağırılan İşlev İfadesi olarak da bilinir) burada daha ayrıntılı olarak açıklanmaktadır .


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

28

Güncel cevap:

In ECMAScript 6 , kullandığınız statik işlevleri oluşturabilir staticanahtar kelime:

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 sınıfları statik için yeni bir anlambilim getirmez. ES5'te aynı şeyi şu şekilde yapabilirsiniz:

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

FooJavaScript işlevlerinde nesneler olduğu için bir özelliğe atayabilirsiniz .


Foo.bar;yorumunuzda belirtildiği gibi işlev tarafından döndürülen dize değil, kendisine atanan işlevi döndürür.

Her iki örnekte de statik bir değerin nasıl ayarlanacağı (üzerine yazılacağı) hakkında bilgi ekleyebilir misiniz?
Wilt

1
@Her iki durumda da, "statik" özellik yalnızca işlevdeki bir özelliktir, bu nedenle onu ayarlar ve JavaScript'teki diğer herhangi bir özellikte olduğu gibi üzerine yazarsınız. Her iki durumda da, ayarlayabilirsiniz barözelliği Fooiçin 3: böyleFoo.bar = 3;
Max Heiber


16

Aşağıdaki örnek ve açıklama Nicholas Zakas tarafından hazırlanan Web Geliştiricileri için Profesyonel JavaScript kitabından alınmıştır. Bu aradığım cevap, bu yüzden buraya eklemenin yararlı olacağını düşündüm.

(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

PersonBu örnekteki yapıcı yapın özel değişken adını erişebilir getName()ve setName()yöntemler. Bu kalıbı kullanarak name değişkeni statik hale gelir ve tüm örnekler arasında kullanılır. Bu setName(), bir örneği çağırmanın diğer tüm örnekleri etkilediği anlamına gelir . setName()Yeni bir Personörneği çağırmak veya oluşturmak , name değişkenini yeni bir değere ayarlar. Bu, tüm örneklerin aynı değeri döndürmesine neden olur.


yapıcı + prototip (hibrit) görünüyor
Ganesh Kumar

2
Bu, Person nesnesini genel ad alanına yerleştirir. Değil bir çözüm tavsiye ederim.
Ghola

Bunun gerçek bir statik değişken olduğunu düşünmüyorum çünkü her yeni nesne ile farklı şekilde başlatılıyor. Statik bir nesne, ana prototipten miras alınan tüm nesneler arasında tutarlı olmalıdır?
lindsaymacvean

1
@Ghola Buradaki amaç, statik bir değişkenin nasıl oluşturulacağını açıklamaktı. Doğru adlandırma ve küresellerden kaçınma cevabın karmaşıklığına katkıda bulunmuş olabilecek ayrı bir konudur. Kirletici olmadan kurucunun nasıl takılacağını belirlemek kullanıcıya bağlıdır. Nicholas Zakas için yeterince iyi olursa, benim için yeterince iyi.
Nate

@lindsaymacvean Bu, statik bir değişkendir çünkü tek değer tüm örneklerde paylaşılır. Değerin değiştirilmesi için sorun yok. Bir örnek değeri değiştirirse, tüm örnekler etkilenir. Yukarıdaki örnekle tamamen aynı olması muhtemel değildir. Gerçekleştirme sırasında değerin ayarlanmasına izin vermek, yalnızca mümkün olduğunu göstermek içindir. Daha olası bir kullanım durumu sadece alıcı ve ayarlayıcıya sahip olmak veya en azından tanımlanmamıştan başka bir şeye ayarlandığından emin olmak olacaktır.
Nate

15

Yeni sınıf sözdizimini kullanıyorsanız, şimdi aşağıdakileri yapabilirsiniz:

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

    console.log(MyClass.myStaticVariable);

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

Bu etkili bir şekilde JavaScript'te statik bir değişken oluşturur.


Bu, statik yardımcı sınıflar oluştururken faydalıdır!
17'de

1
Ama şimdi soru, bir değeri nasıl koruduğunuz ve bir ayarlayıcıyla değerde değişikliklere nasıl izin verdiğinizdir. Bir kapatma veya MyClasssınıf yapısının dışında tanımlanan bir özellik gerekli olacaktır .
trincot


8

Uygulamanızda sabitler oluşturmak için statik değişkenler bildirmek istiyorsanız, en basit yaklaşım olarak aşağıdakileri buldum

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

Hakkında classECMAScript 2015 tarafından tanıtılan diğer cevaplar tamamen temizlemek değildir.

İşte bir statik VAR nasıl oluşturulacağını gösteren bir örnektir staticVarile ClassName. varsynthax:

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

Statik değişkene erişmek .constructoriçin sınıfı oluşturan nesne yapıcı işlevine bir başvuru döndüren özelliği kullanırız . Bunu, oluşturulan iki örnekte çağırabiliriz:

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

Başka benzer cevaplar da var, ama hiçbiri bana pek çekici gelmedi. İşte sonuçta:

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

7

Diğerlerine ek olarak, şu anda ECMA Teklifleri ile ilgili olarak sınıflarda kamusal alanları tanıtan bir taslak ( 2. aşama ) önerisi bulunmaktadır . ( özel alanlar dikkate alınmıştır )static

Teklifin örneğini kullanarak, önerilen staticsözdizimi şöyle görünecektir:

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

ve diğerlerinin vurguladığı aşağıdakilere eşdeğer olun:

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

Daha sonra bu adrese erişebilirsiniz CustomDate.epoch.

İçindeki yeni teklifi takip edebilirsiniz proposal-static-class-features.


Şu anda, babel bu özelliği kullanabileceğiniz transform sınıfı özellikleri eklentisiyle desteklemektedir . Ayrıca, hala devam etmekle birlikte V8, uygulamaktadır .


6

JavaScript'te aşağıdaki gibi statik bir değişken oluşturabilirsiniz. İşte countstatik değişken.

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

PersonFonksiyonu veya örneklerden birini kullanarak statik değişkene değerler atayabilirsiniz :

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

Bu, statik değişken bildirmek ve JavaScript'e erişmek için iyi bir yaklaşımdır.
ArunDhwaj IIITH

5

Global bir statik değişken oluşturmak istiyorsanız:

var my_id = 123;

Değişkeni aşağıdaki ile değiştirin:

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

4

JavaScript'te statik bir değişkene en yakın şey global bir değişkendir - bu, yalnızca bir işlev veya nesne değişmezinin kapsamı dışında bildirilen bir değişkendir:

var thisIsGlobal = 1;

function foo() {
    var thisIsNot = 2;
}

Yapabileceğiniz diğer şey, global değişkenleri şöyle bir nesne hazır bilgisinde saklamak olacaktır:

var foo = { bar : 1 }

Ve sonra böyle variabels erişmek: foo.bar.


Bu bana birden fazla dosya yüklemek için yardımcı oldu ..... var foo = {counter: 1}; function moreFiles () {fileName = "Dosya" + foo.counter; foo.sayıcı = foo.sayıcı + 1;
veer7

4

Tüm sınıf kavramlarını burada yoğunlaştırmak için şunu test edin:

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

Bu şeylerde en iyi uygulamalara bakmanın bir başka yolu da, kahvenin bu kavramları nasıl çevirdiğini görmektir.

#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

JavaScript'te değişkenler varsayılan olarak statiktir . Örnek :

var x = 0;

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

setInterval(draw, 1000);

X değeri her 1000 milisaniyede bir artar.
1,2,3


2
Bu farklı bir durum. Örneğiniz kapsamlarla ilgilidir.
Challet

4

Bu konuya göz attıktan sonra gereksinimlerimi çözen başka bir yaklaşım var. "Statik değişken" ile tam olarak ne elde etmek istediğinize bağlıdır.

Global property sessionStorage veya localStorage, verilerin oturumun ömrü boyunca veya açıkça temizlenene kadar süresiz olarak daha uzun bir süre depolanmasına izin verir. Bu, verilerin sayfanızın / uygulamanızın tüm pencereleri, çerçeveleri, sekme panelleri, pop-up'ları vb. Arasında paylaşılmasını sağlar ve bir kod segmentindeki basit bir "statik / genel değişken" ten çok daha güçlüdür.

Window.myglobal gibi üst düzey küresel değişkenlerin kapsamı, ömrü, anlambilimi, dinamikleri vb. İle tüm zorluklardan kaçınır. Ne kadar verimli olduğunu bilmiyorum, ancak bu mütevazı oranlarda erişilen az miktarda veri için önemli değil.

"SessionStorage.mydata = bir şey" olarak kolayca erişilir ve benzer şekilde alınır. Bkz. "JavaScript: Kesin Kılavuz, Altıncı Baskı", David Flanagan, ISBN: 978-0-596-80552-4, Bölüm 20, bölüm 20.1. Bu, basit bir arama ile veya O'Reilly Safaribooks aboneliğinizde (ağırlığındaki altın değerinde) PDF olarak kolayca indirilebilir.


2

İşlev / sınıflar, nesne kapsamı için yalnızca tek bir kurucuya izin verir. Function Hoisting, declarations & expressions

  • İşlev yapıcısı ile oluşturulan işlevler, oluşturma bağlamlarına bir kapatma oluşturmaz; her zaman küresel kapsamda yaratılırlar.

      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)

Kapaklar - kapak kopyaları korunan verilerle çalışır.

  • Her kapağın kopyaları, kendi serbest değerleri veya referansları olan bir işleve oluşturulur. Başka bir işlevin içindeki işlevi her kullandığınızda, bir kapatma kullanılır.
  • JavaScript'teki bir kapatma, üst işlevinin tüm yerel değişkenlerinin innerFunctions tarafından bir kopyasını tutmak gibidir.

      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 İşlev Sınıfları : Object.defineProperty (O, P, Attributes) kullanır

Object.defineProperty () yöntemi, bir nesne üzerinde doğrudan yeni özelliğini tanımlayan ya da değiştiren, mevcut bir özelliği, bir nesne üzerinde ve nesnesi geri gönderir.

`` Kullanarak bazı yöntemler oluşturduk , böylece her seferinde fonksiyon sınıflarını kolayca anlayabilsin.

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

Aşağıdaki kod snippet'i, her örneğin kendi örnek üyeleri ve ortak statik üyelerin kendi kopyalarına sahiptir.

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

Statik yöntem çağrıları doğrudan sınıfta yapılır ve sınıf örneklerinde çağrılamaz. Ancak statik üyelerin çağrılarını bir örneğin içinden gerçekleştirebilirsiniz.

Sözdizimini kullanma:

   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 Sınıfları: ES2015 sınıfları, prototip tabanlı OO modeline göre basit bir şekerdir. Tek bir uygun bildirim formuna sahip olmak, sınıf modellerinin kullanımını kolaylaştırır ve birlikte çalışabilirliği teşvik eder. Sınıflar, prototip tabanlı kalıtım, süper çağrılar, örnek ve statik yöntemler ve yapıcıları destekler.

Örnek : önceki yazıma bakın.


2

Javascript'te işlev-yerel statik değişkenleri taklit etmenin 4 yolu vardır.

Yöntem 1: İşlev nesnesi özelliklerini kullanma (eski tarayıcılarda desteklenir)

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

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

Yöntem 2: Kapatma, değişken 1 (eski tarayıcılarda desteklenir) kullanma

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

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

Yöntem 3: Kapatma, varyant 2 (eski tarayıcılarda da desteklenir) kullanma

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

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

Yöntem 4: Kapatma, değişken 3 kullanma (EcmaScript 2015 için destek gerektirir)

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

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

2

Anahtar kelimeyi kullanarak JavaScript'te statik işlevleri tanımlayabilirsiniz static:

class MyClass {
  static myStaticFunction() {
    return 42;
  }
}

MyClass.myStaticFunction(); // 42

Bu yazıdan itibaren sınıf içinde statik özellikler (işlevler dışında) tanımlayamazsınız. Statik özellikler hala bir Aşama 3 önerisidir , yani henüz JavaScript'in bir parçası değildir. Ancak, başka bir nesneye yapacağınız gibi bir sınıfa atamanızı engelleyen hiçbir şey yoktur:

class MyClass {}

MyClass.myStaticProperty = 42;

MyClass.myStaticProperty; // 42

Son not: Kalıtımla statik nesneleri kullanma konusunda dikkatli olun - devralınan tüm sınıflar nesnenin aynı kopyasını paylaşır .


1

JavaScript'te, herhangi bir terim veya anahtar kelime statik yoktur, ancak bu tür verileri doğrudan işlev nesnesine (diğer herhangi bir nesnede olduğu gibi) koyabiliriz.

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

Statik fonksiyon değişkenlerini çok kullanıyorum ve JS'nin bunun için yerleşik bir mekanizmaya sahip olmadığı gerçek bir utanç. Çok sık, sadece bir fonksiyon içinde kullanılsalar bile, değişkenlerin ve fonksiyonların bir dış kapsamda tanımlandığı kodu görüyorum. Bu çirkin, hata eğilimli ve sadece sorun istiyor ...

Aşağıdaki yöntemi buldum:

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

Bu, tüm işlevlere bir 'statik' yöntemi ekler (evet, sadece rahatlayın), çağrıldığında işlev nesnesine boş bir nesne (_statics) ekler ve döndürür. Bir init işlevi sağlanırsa _statics init () sonucuna ayarlanır.

Daha sonra şunları yapabilirsiniz:

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

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

Bunu diğer doğru cevap olan bir IIFE ile karşılaştırmak, her işlev çağrısında bir ödev ve bir tane eklemek ve işleve bir '_statics' üyesi eklemek dezavantajına sahiptir, ancak birkaç avantaj vardır: üstteki iç işlevde değil, iç işlev kodunda 'statik' kullanılması '_s' ile açıktır. öneki, bakmak ve anlamak genel olarak daha kolaydır.


1

Özet:

In ES6/ ES 2015 classkelime bir eşlik ile tanıtıldı staticanahtar kelime. Bunun javavscript içerdiği prototip kalıtım modeli üzerinde sözdizimsel şeker olduğunu unutmayın. staticAnahtar kelime yöntemleri için aşağıdaki şekilde çalışır:

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

}

// to create static variables just create a property on the prototype of the class
Dog.prototype.breed = 'Pitbull';
// So to define a static property we don't need the `static` keyword.

const fluffy = new Dog();
const vicky = new Dog();
console.log(fluffy.breed, vicky.breed);

// changing the static variable changes it on all the objects
Dog.prototype.breed = 'Terrier';
console.log(fluffy.breed, vicky.breed);


2
Statik bir fonksiyon değil, statik bir değişken istiyordu.
Konrad Höffner

1

Prototipi kullandım ve bu şekilde çalıştı:

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

Cat.COLLECTION_NAME = "cats";

veya statik bir alıcı kullanarak:

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

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

0

Pencere seviyesi değişkenleri, doğrudan referans kullanabilmeniz açısından sorta benzeri statiktir ve bunlar uygulamanızın tüm bölümleri tarafından kullanılabilir


3
Bu tür değişkenlerin çok daha iyi bir açıklaması statik olmaktan ziyade 'global'dir.
Patrick M

0

Javascript'te statik değişken diye bir şey yoktur. Bu dil prototip tabanlı nesne yönelimlidir, bu nedenle sınıf yoktur, ancak nesnelerin kendilerini kopyaladıkları prototipler vardır.

Bunları global değişkenlerle veya prototipleme ile simüle edebilirsiniz (prototipe özellik ekleme):

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

Bu yöntem işe yarıyor, ancakFunction.prototype
Dan

@ Dan: Benim anlayışım, bu sadece İşlev için değil, daire için olurdu. En azından Chrome bana bunu anlatmaya çalışıyor: function circle() {}| circle.prototype| circle.prototype.pi = 3.14| circle.prototype| Function.prototype| Function.__proto__(demek istediğin buysa)
Aktau

0

JQuery kullanan MVC web siteleri ile çalışırken, belirli olay işleyicilerindeki AJAX eylemlerinin yalnızca önceki istek tamamlandıktan sonra yürütülebildiğinden emin olmak istiyorum. Bunu elde etmek için bir "statik" jqXHR nesne değişkeni kullanın.

Aşağıdaki düğme göz önüne alındığında:

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

Tıklama işleyicim için genellikle böyle bir IIFE kullanırım:

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

Prototip kullanmak istiyorsanız, bir yol var

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

Bunu yaptığınızda herhangi bir örnekten sayaç değişkenine erişebileceksiniz ve mülkteki herhangi bir değişiklik hemen yansıtılacaktır !!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.