Javascript'te statik değişkenler

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

553
08 окт. Rajat 08 ekim tarafından belirlendi . 2009-10-08 07:31 '09, 07:31, 2009-10-08 07:31
@ 36 cevaplar
  • 1
  • 2

Sınıf tabanlı nesne yönelimli bir dilden (örneğin, Java, C ++ veya C #) başlarsanız, bir örnekle değil, "tür" ile ilişkilendirilmiş bir değişken veya yöntem oluşturmaya çalıştığınızı farz ediyorum.

Yapıcı işlevleriyle "klasik" yaklaşımı kullanan bir örnek, temel OO JavaScript kavramlarını anlamanı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(); 

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

743
08 окт. Cevap CMS 08 ekim tarafından verilir . 2009-10-08 07:49 '09, 07:49 2009-10-08 07:49

JS işlevlerinin aynı zamanda nesneler olduğu gerçeğinden yararlanabilirsiniz, bu da özelliklere sahip olabilecekleri anlamına gelir.

Örneğin, artık ortadan kaybolan Javascript'teki Statik Değişkenler makalesinden bir örnek alıntı:

 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, sayaç artışını göreceksiniz.

border=0

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


Ve işte kapanmaya dayalı başka bir olası çözüm: Javascript'te statik değişken kullanmanın püf noktası :

 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 da size aynı sonucu verir - bu süre dışında değer eklenen değerle birlikte döndürülür ve görüntülenmez.

465
08 окт. Cevap Pascal MARTIN tarafından yapıldı 08 Ekim 2009-10-08 07:37 '09, 07:37, 2009-10-08 07:37

Bunu IIFE üzerinden yaparsınız (hemen işlev ifadesi olarak adlandırılır):

 var incr = (function () { var i = 1; return function () { return i++; } })(); incr(); // returns 1 incr(); // returns 2 
60
30 марта '13 в 13:02 2013-03-30 13:02 Cevap khoomeister tarafından 30 '13 Mart'ta 13:02 2013-03-30 13:02 tarihinde verilmiştir.

"Statik" değişkenleri saklamak için arguments.callee dosyasını kullanabilirsiniz (bu, adsız bir işlev için de yararlıdır):

 function () { arguments.callee.myStaticVar = arguments.callee.myStaticVar || 1; arguments.callee.myStaticVar++; alert(arguments.callee.myStaticVar); } 
36
06 нояб. cevap gpilotino Kasım 06 tarafından verilen 2009-11-06 14:19 '09, 14:19 2009-11-06 14:19
 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(); 
24
28 февр. Tarafından verilen cevap jim_zike_huang 28 Şub. 2012-02-28 23:08 '12 23:08 2012-02-28 23:08

Birkaç benzer cevap gördüm, ancak bu yazının en iyisini açıkladığını, sizinle paylaşmak istediğini belirtmek isterim.

İşte tam bir örnek almak için değiştirdiğim, topluluğa fayda sağlayacağını umduğumdan, aldığım kod, çünkü sınıflar için tasarım şablonu olarak kullanılabilir.

Ayrıca sorunuzu yanıtlıyor:

 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 örnekte, statik özelliklere / işlevlere aşağıdaki gibi erişebilirsiniz:

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

Ve bir nesnenin özellikleri / işlevleri basittir:

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

Podcast.immutableProp () işlevinde bir kapatmamızın olduğunu unutmayın : _somePrivateVariable bağlantısının işlev içinde saklandığını unutmayın.

Alıcıları ve ayarlayıcıları bile tanımlayabilirsiniz. Bu kod pasajına bir göz atın (burada d , bir özelliği bildirmek istediğiniz nesnenin prototipidir, y , yapıcının 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) } }); 

d.year özelliğini, get ve set işlevleriyle tanımlar - d.year belirtmezseniz, özellik yalnızca okunur ve değiştirilemez (ayarlamaya çalışırsanız bir hata almazsınız, ancak etkisi olmaz). Her özellik, varsayılan olarak false olan writable , configurable (bildirimden sonra değişikliğe izin enumerable ) ve enumerable (numaralandırıcı olarak kullanılmasına izin ver) niteliklerine sahiptir. Bunları, örneğin üçüncü parametrede defineProperty ayarlayabilirsiniz. enumerable: true .

Doğru olan da sözdizimi:

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

bu özellik, read / write özelliğini a , readonly b özelliğini ve bu özelliğe erişebileceğiniz salt okunur b özelliğini tanımlar.

Uygulama:

 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 

Açıklamalar:

Beklenmeyen davranışlardan kaçınmak için, new anahtar kelimeyi unutursanız, Podcast işlevine şunu eklemenizi öneririz:

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

Yeni işleç yeni bir nesne oluşturur ve tüm özellikleri ve yöntemleri kopyalar, yani.

 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 kendi içinde güvenilen, ancak etkilenmesi gereken işlevleri koruyan özel nesneleri döndürmek için Podcast yapıcı işlevindeki return kullanmanın yararlı olabileceğini unutmayın . Bu, makale serisinin 2. Bölümünde (Nesneler) daha ayrıntılı olarak açıklanmaktadır.

a ve b Podcast devralındığını söyleyebilirsiniz. Şimdi, a ve b sonra hepsine uygulanan bir Podcast'e bir yöntem eklemek isterseniz, örneklenilsin mi? Bu durumda, aşağıdaki gibi .prototype kullanın:

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

Şimdi tekrar a ve b arayın:

 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 buradan okuyun. Daha fazla kalıtım yapmak istiyorsanız, bunu çalışmanızı öneririm.


Yukarıda bahsettiğim bir dizi makale , okunması önerilir , ayrıca aşağıdaki konuları da içerirler

  • fonksiyonlar
  • nesneleri
  • prototipler
  • Yeni yapıcı işlevlerin yürütülmesi
  • kaldırma
  • Otomatik noktalı virgül
  • Statik özellikler ve yöntemler

Otomatik noktalı virgül JavaScript "işlevi" nin (6'da belirtildiği gibi) kodunuzda garip sorunlara neden olmaktan çok sorumlu olduğunu unutmayın. Bu nedenle, bunu işlev olarak değil hata olarak değerlendirmeyi tercih ederim.

Daha fazla bilgi edinmek istiyorsanız, işte bazıları burada açıklanan bu konularla ilgili oldukça ilginç bir MSDN makalesi.

Okumak ilginç (yukarıda belirtilen konuları da kapsayan) MDN JavaScript Rehberindeki makaleler:


IE ile çalışanlarınız (JavaScript için bir konsolu olmayan, F12'yi kullanarak geliştirici araçlarını açmazsanız ve konsol sekmesini açmazsanız) aşağıdaki pasajı yararlı bulabilirsiniz. Bu, console.log(msg); kullanmanıza izin verir console.log(msg); yukarıdaki örneklerde kullanıldığı gibi. Sadece Podcast özelliğinin önüne yapıştırın.

Size kolaylık sağlamak için, işte tam bir kod pasajında ​​yukarıdaki kod:


Not. . Sınıfları kullanmanın ve bunları JavaScript'te derlemenin kolay bir yolu TypeScript'tir. İşte bunun nasıl çalıştığını gösteren birkaç örnek bulabileceğiniz bir platform . Şu anda TypeScript kullanmasanız bile, bakabilirsiniz, çünkü TypeScript'i javascript ile yan yana karşılaştırabilirsiniz. Örneklerin çoğu basit, ancak anında deneyebileceğiniz bir Raytracer örneği de var. Özellikle, "Sınıf kullanma", "Kalıtım kullanma" ve "Ortak kullanım" örneklerini açılan kutuda seçerek incelemenizi öneririm. Bunlar, JavaScript'te hemen kullanabileceğiniz güzel şablonlardır.

21
10 сент. Cevap Matt Matt tarafından gönderildi 10 Eyl 2013-09-10 14:53 '13, 14:53 2013-09-10 14:53

Güncelleme cevabı:

ECMAScript 6'da static kullanarak statik işlevler oluşturabilirsiniz:

 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ı statikler için yeni bir anlam ifade etmez. ES5'te aynısını aşağıdaki gibi 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 

JavaScript işlevlerinde nesneler olduğu için Foo özelliğini atayabilirsiniz.

16
27 марта '15 в 4:09 2015-03-27 04:09 Cevap, 27.03.2015 tarihinde Max Heiber tarafından 4:09 2015-03-27 04:09 tarihinde verilmiştir.

Aşağıdaki örnek ve açıklama, Nicholas Zakas tarafından yayınlanan Web Geliştiricileri için Profesyonel JavaScript 2. kitapta verilmiştir. Aradığım cevap buydu, bu yüzden buraya eklemenin faydalı 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 

Bu örnekte, Person kurucusu özel bir değişkenin adına ve ayrıca getName() ve setName() yöntemlerine erişebilir. Bu şablonu kullanarak, isim değişkeni statik hale gelir ve tüm örnekler için kullanılır. Bu, bir örnekte setName() çağrılmasının diğer tüm örnekleri etkilediği anlamına gelir. setName() çağırmak veya yeni bir Person örneği oluşturmak, yeni değer için ad değişkenini ayarlar. Bu, tüm örneklerin aynı değeri döndürmesine neden olur.

13
13 дек. Cevap Nate'e 13 Aralık'ta verildi. 2011-12-13 11:26 '11 11:26 2011-12-13 11:26

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

5
22 февр. Cevap Automatico 22 Şubat'ta verildi . 2017-02-22 19:11 '17, 19:11 2017-02-22 19:11

Uygulamanızda sabitler oluşturmak için statik değişkenler bildirmek istiyorsanız, aşağıdakileri en basitleştirilmiş yaklaşım olarak 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; 
4
03 апр. Tarafından cevaplandı Hemant, Nis 03 2013-04-03 01:05 '13, 01:05 2013-04-03 01:05

Başka benzer cevaplar var, ama hiçbiri bana hitap etmedi. İşte ne bitirdim:

 var nextCounter = (function () { var counter = 0; return function() { var temp = counter; counter += 1; return temp; }; })(); 
4
08 февр. Cevap verilirse funroll 08 февр . 2015-02-08 06:34 '15 6: 34'te 2015-02-08 06:34

Javascript'te aşağıda gösterildiği gibi statik bir değişken oluşturabilirsiniz. Burada count statik bir değişkendir.

 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 

Person işlevini veya örneklerden herhangi birini kullanarak statik bir 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 
3
31 июля '16 в 9:16 2016-07-31 09:16 Cevap Snađoshƒaӽ 31 Temmuz 16, 09:16 tarihinde eklendi 2016-07-31 09:16

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

 var my_id = 123; 

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

 Object.defineProperty(window, 'my_id', { get: function() { return 123; }, configurable : false, enumerable : false }); 
3
16 марта '12 в 6:56 2012-03-16 06:56 Cevap JoolzCheat tarafından 16 '12 Mart'ta 06:56 2012-03-16 06:56 tarihinde verilmiştir.

ECMAScript 2015 tarafından sunulan class hakkında. Cevapların geri kalanı tamamen açık değildir.

ClassName kullanarak statik var staticVar nasıl oluşturulduğunu gösteren bir örnek. var synthax:

 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 bir değişkene erişmek için, nesneyi sınıfı oluşturan .constructor referans veren .constructor özelliğini kullanırız. Oluşturulan iki örnekte arayabiliriz:

 MyClass.staticVar = 11; console.log(class1.constructor.staticVar); // 11 console.log(class2.constructor.staticVar); // 11 <-- yes it static! :) MyClass.staticVar = 12; console.log(class1.constructor.staticVar); // 12 console.log(class2.constructor.staticVar); // 12 
3
24 марта '17 в 13:02 2017-03-24 13:02 Cevap 24 Mart 17'de COil tarafından 13:02 2017-03-24 13:02 tarihinde verilmiştir.

Statik bir değişken için JavaScript'teki en yakın şey, genel 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 başka bir şey, global değişkenleri bir değişmez nesnenin içine aşağıdaki gibi koymaktır:

 var foo = { bar : 1 } 

Ve sonra bu gibi değişkenlere erişin: foo.bar .

2
08 окт. Cevap Hare Ekim 08 için cevap 2009-10-08 07:33 '09, 07:33, 2009-10-08 07:33

Varsayılan javascript değişkenleri statiktir . örnek:

 var x = 0; işlev draw () { alarm (x);  // x + = 1; } setInterval (çizim, 1000);

Her 1000 milisaniyede bir x değeri 1 artırılır.
1,2,3 ve daha fazla yazdıracak.

2
08 апр. Cevap Kerim 08 Nisan tarafından verilmiştir . 2017-04-08 15:39 '17, 15:39, 2017-04-08 15:39

Tüm sınıf kavramlarını yoğunlaştırmak için şunu kontrol 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 

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

 #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); 
2
24 нояб. Cevap Stratboy tarafından 24 Kasım'da verildi. 2013-11-24 14:20 '13, 14:20, 2013-11-24 14:20

Bu konuyu inceledikten sonra gereksinimlerimi belirleyen farklı bir yaklaşım vardı. Bu "statik değişken" ile ne elde etmek istediğinize bağlıdır.

Global sessionStorage veya localStorage özelliği, verileri oturum boyunca ya da belirsiz olarak daha uzun bir süre boyunca sırasıyla açıkça temizlenene kadar saklamanıza olanak tanır. Bu, verilerin tüm pencereler, çerçeveler, sekmeler, açılır pencereler vb. Arasında paylaşılmasını sağlar. Sayfanızın / uygulamanızın ve tek bir kod segmentindeki basit bir "statik / global değişken" den çok daha güçlü.

Kapsam, ömür, anlam, dinamikleri vb. İle ilgili tüm problemlerden kaçınır. global üst seviye değişkenler, yani, Window.myglobal. Bunun ne kadar etkili olduğunu bilmiyorum, ancak erişimin mütevazı oranlarda yapıldığı ılımlı miktarda veri için önemli değil.

"SessionStorage.mydata = herhangi bir şey" olarak erişmek ve aynı şekilde almak kolaydır. Bkz. "JavaScript: Son Kılavuz, Altıncı Baskı", David Flanagan, ISBN: 978-0-596-80552-4, bölüm 20, bölüm 20.1. Basit arama yoluyla veya O'Reilly Safaribooks'a (altın cinsinden ağırlığına değer) abonelikle PDF formatında indirmek kolaydır.

Selamlar, Greg E

2
07 апр. Yanıtla Greg E 07 Nis 2013-04-07 12:58 '13, 12:58 2013-04-07 12:58

Bir prototip kullanmak istiyorsanız, o zaman bir yolu 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 yaparak, sayaç değişkenine herhangi bir durumda erişebilirsiniz ve özellikteki herhangi bir değişiklik derhal yansıtılır!

0
09 мая '14 в 9:25 2014-05-09 09:25 Cevap charlie tarafından 09 Mayıs 14: 9: 25'te bildirildi 2014-05-09 09:25

JavaScript’te statik bir terim veya anahtar kelime yoktur, ancak bu verileri doğrudan bir işlev nesnesine (diğer nesnelerde 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 
0
31 марта '16 в 20:44 2016-03-31 20:44 Cevap Satyapriya Mishra tarafından 31 Mart'ta 16 : 20'de verilecek 2016-03-31 20:44

Özel statik değişkenler için bu yöntemi buldum:

 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
25 окт. Cevap Martin Wantke 25 Ekim 2016-10-25 15:42 '16, 15:42 2016-10-25 15:42

Öyleyse, diğer cevaplarla gördüğüm şey, nesneye yönelik programlamada statik bir özniteliğin temel mimari gereksinimini dikkate almadıklarıdır.

Nesne yönelimli programlama aslında iki farklı stile sahiptir: biri “sınıf tabanlı” (C ++, C #, Java vb.), Diğeri “prototip” (Javascript). В языках на основе класса предполагается, что "статический атрибут" связан с классом, а не с экземплярами объектов. Эта концепция на самом деле работает намного интуитивно на прототипных языках, таких как Javascript, потому что вы просто назначаете атрибут как значение родительского прототипа, например.

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