Soru JavaScript'te enumları tanımlamak için tercih edilen sözdizimi nedir?
JavaScript'te enumları tanımlamak için tercih edilen sözdizimi nedir? Gibi bir şey:
my.namespace.ColorEnum = {
RED : 0,
GREEN : 1,
BLUE : 2
}
// later on
if(currentColor == my.namespace.ColorEnum.RED) {
// whatever
}
Yoksa daha çok tercih edilen bir deyim var mı?
1678
2017-11-13 19:09
Menşei
Cevaplar:
1.8.5'ten beri nesneyi mühürlemek ve dondurmak mümkündür, böylece yukarıdakileri tanımlayın:
var DaysEnum = Object.freeze({"monday":1, "tuesday":2, "wednesday":3, ...})
veya
var DaysEnum = {"monday":1, "tuesday":2, "wednesday":3, ...}
Object.freeze(DaysEnum)
ve voila! JS enums.
Bununla birlikte, bu, genellikle enumların ana hedefi olan bir değişkene istenmeyen bir değer atamanızı engellemez:
let day = DaysEnum.tuesday
day = 298832342 // goes through without any errors
Daha güçlü bir tipte güvenlik sağlamak için bir yol (enumlar ile veya başka şekilde) gibi bir araç kullanmaktır daktilo ile yazılmış yazı veya Akış.
Kaynak
Tırnaklar gerekli değil ama onları tutarlılık için sakladım.
541
2018-02-18 11:03
Bu bir cevap değil, ama bunun iyi çalıştığını söyleyebilirim, kişisel olarak
Bunu söylemiş olursak, değerlerin ne olduğu önemli değil (0, 1, 2 kullandınız), şimdiki değeri almak istediğinizde anlamlı bir ip kullanırdım.
583
2017-11-13 19:13
GÜNCELLEŞTİRME: Herkes için tüm oylar için teşekkürler, ama aşağıda cevabım Javascript içinde enum yazmak için en iyi yol olduğunu düşünmüyorum. Daha fazla ayrıntı için blog gönderime bakın: Javascript'teki Enumlar.
İsmi bildirmek zaten mümkün:
if (currentColor == my.namespace.ColorEnum.RED) {
// alert name of currentColor (RED: 0)
var col = my.namespace.ColorEnum;
for (var name in col) {
if (col[name] == col.RED)
alert(name);
}
}
Alternatif olarak, değerler nesnelerini yapabilirsiniz, böylece pastayı alabilir ve yiyebilirsiniz:
var SIZE = {
SMALL : {value: 0, name: "Small", code: "S"},
MEDIUM: {value: 1, name: "Medium", code: "M"},
LARGE : {value: 2, name: "Large", code: "L"}
};
var currentSize = SIZE.MEDIUM;
if (currentSize == SIZE.MEDIUM) {
// this alerts: "1: Medium"
alert(currentSize.value + ": " + currentSize.name);
}
Javascript'te, dinamik bir dil olduğu için, enum değerlerini daha sonra kümeye eklemek bile mümkündür:
// Add EXTRALARGE size
SIZE.EXTRALARGE = {value: 3, name: "Extra Large", code: "XL"};
Unutmayın, enumun alanları (bu örnekteki değer, isim ve kod) kimlik kontrolü için gerekli değildir ve sadece kolaylık için vardır. Ayrıca, boyut özelliğinin adının kodlanmış olması gerekmez, ancak dinamik olarak da ayarlanabilir. Dolayısıyla, yalnızca yeni enum değerinizin adını bildiğinizi varsayarak, sorunsuz olarak ekleyebilirsiniz:
// Add 'Extra Large' size, only knowing it's name
var name = "Extra Large";
SIZE[name] = {value: -1, name: name, code: "?"};
Elbette bu, bazı varsayımların artık yapılamayacağı anlamına gelir (bu değer, örneğin boyut için doğru sırayı gösterir).
Unutmayın, Javascript'te bir nesne tıpkı bir harita veya karmaşa gibidir. İsim-değer çiftleri kümesi. Onlardan geçebilir veya önceden onlar hakkında fazla bilgi sahibi olmadan bunları manipüle edebilirsiniz.
ÖRNEĞİN:
for (var sz in SIZE) {
// sz will be the names of the objects in SIZE, so
// 'SMALL', 'MEDIUM', 'LARGE', 'EXTRALARGE'
var size = SIZE[sz]; // Get the object mapped to the name in sz
for (var prop in size) {
// Get all the properties of the size object, iterates over
// 'value', 'name' and 'code'. You can inspect everything this way.
}
}
Ve btw, ad alanlarıyla ilgileniyorsanız, javascript için basit ama güçlü ad alanı ve bağımlılık yönetimi çözümüme bir göz atmak isteyebilirsiniz: Paketler JS
477
2018-03-04 22:31
Alt satır: Yapamazsın.
Taklit edebilirsin ama tip güvenliği olmaz. Tipik olarak bu, tamsayı değerlerine eşlenen dize değerleri basit bir sözlük oluşturarak yapılır. Örneğin:
var DaysEnum = {"monday":1, "tuesday":2, "wednesday":3, ...}
Document.Write("Enumerant: " + DaysEnum.tuesday);
Bu yaklaşımdaki problem? Sayınızı yanlışlıkla yeniden tanımlayabilir veya yanlışlıkla yinelenen sayım değerlerine sahip olabilirsiniz. Örneğin:
DaysEnum.monday = 4; // whoops, monday is now thursday, too
Düzenle
Artur Czajka'nın Object.freeze'den ne haber? Pazartesiden perşembeye gitmenizi engellemek için işe yaramaz mı? - Fry Quad
Kesinlikle, Object.freeze
şikayet ettiğim sorunu tamamen düzeltirdi. Herkesi hatırlattığımda herkese hatırlatmak isterim. Object.freeze
gerçekten yoktu.
Şimdi .... şimdi biraz açılıyor çok ilginç olanaklar.
2'yi düzenle
İşte enumlar oluşturmak için çok iyi bir kütüphane.
http://www.2ality.com/2011/10/enums.html
Her türlü geçerli enumat kullanımına uymuyor olsa da, çok uzun bir yol kat ediyor.
79
2017-08-21 20:56
Hepimizin istediği:
function Enum(constantsList) {
for (var i in constantsList) {
this[constantsList[i]] = i;
}
}
Şimdi enumlarınızı yaratabilirsiniz:
var YesNo = new Enum(['NO', 'YES']);
var Color = new Enum(['RED', 'GREEN', 'BLUE']);
Bunu yaparak, sabitler her zamanki şekilde (YesNo.YES, Color.GREEN) okunabilir ve sıralı bir int değeri alırlar (NO = 0, YES = 1; KIRMIZI = 0, YEŞİL = 1, MAVİ = 2).
Enum.prototype'ı kullanarak da yöntemler ekleyebilirsiniz:
Enum.prototype.values = function() {
return this.allValues;
/* for the above to work, you'd need to do
this.allValues = constantsList at the constructor */
};
Düzenle - küçük iyileştirme - şimdi varargs ile: (maalesef IE'de düzgün çalışmıyor: S ... daha önceki versiyona bağlı kalmalı)
function Enum() {
for (var i in arguments) {
this[arguments[i]] = i;
}
}
var YesNo = new Enum('NO', 'YES');
var Color = new Enum('RED', 'GREEN', 'BLUE');
46
2017-07-13 00:28
Çoğu modern tarayıcıda, bir sembol Bir numaralandırma oluşturmak için kullanılabilecek ilkel veri türü. Her sembol değerinin JavaScript tarafından benzersiz olması garantili olduğundan, enumun tip güvenliğini sağlayacaktır, örn. Symbol() != Symbol()
. Örneğin:
const COLOR = Object.freeze({RED: Symbol(), BLUE: Symbol()});
Hata ayıklamayı basitleştirmek için enum değerlerine bir açıklama ekleyebilirsiniz:
const COLOR = Object.freeze({RED: Symbol("RED"), BLUE: Symbol("BLUE")});
Plunker demosu
üzerinde GitHub numarayı başlatmak için gereken kodu basitleştiren bir sarıcı bulabilirsiniz:
const color = new Enum("RED", "BLUE")
color.RED.toString() // Symbol(RED)
color.getName(color.RED) // RED
color.size // 2
color.values() // Symbol(RED), Symbol(BLUE)
color.toString() // RED,BLUE
41
2018-05-05 16:32
Benimle oynadım, enumlarımı seviyorum. =)
kullanma Object.defineProperty
Sanırım biraz uygulanabilir bir çözüm buldum.
İşte bir jsfiddle: http://jsfiddle.net/ZV4A6/
Bu yöntemi kullanarak .. (teoride), o nesnenin diğer özelliklerini etkilemeden, herhangi bir nesne için enum değerlerini çağırıp tanımlayabilmelisiniz.
Object.defineProperty(Object.prototype,'Enum', {
value: function() {
for(i in arguments) {
Object.defineProperty(this,arguments[i], {
value:parseInt(i),
writable:false,
enumerable:true,
configurable:true
});
}
return this;
},
writable:false,
enumerable:false,
configurable:false
});
Özellik nedeniyle writable:false
bu meli güvenli yazın.
Yani özel bir nesne oluşturabilirsin, sonra ara Enum()
üstünde. Atanan değerler 0'da başlar ve öğe başına artış.
var EnumColors={};
EnumColors.Enum('RED','BLUE','GREEN','YELLOW');
EnumColors.RED; // == 0
EnumColors.BLUE; // == 1
EnumColors.GREEN; // == 2
EnumColors.YELLOW; // == 3
23
2017-08-21 10:34
Bu bildiğim eski bir şey, ama o zamandan beri TypeScript arabirimiyle uygulanan yol:
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["Foo"] = 0] = "Foo";
MyEnum[MyEnum["FooBar"] = 2] = "FooBar";
MyEnum[MyEnum["Bar"] = 1] = "Bar";
})(MyEnum|| (MyEnum= {}));
Bu, her ikisine de bakmanızı sağlar MyEnum.Bar
1 döndürür ve MyEnum[1]
beyan sırasına bakılmaksızın "Bar" döndürür.
17
2018-06-24 16:11
Bu benim kullandığım çözüm.
function Enum() {
this._enums = [];
this._lookups = {};
}
Enum.prototype.getEnums = function() {
return _enums;
}
Enum.prototype.forEach = function(callback){
var length = this._enums.length;
for (var i = 0; i < length; ++i){
callback(this._enums[i]);
}
}
Enum.prototype.addEnum = function(e) {
this._enums.push(e);
}
Enum.prototype.getByName = function(name) {
return this[name];
}
Enum.prototype.getByValue = function(field, value) {
var lookup = this._lookups[field];
if(lookup) {
return lookup[value];
} else {
this._lookups[field] = ( lookup = {});
var k = this._enums.length - 1;
for(; k >= 0; --k) {
var m = this._enums[k];
var j = m[field];
lookup[j] = m;
if(j == value) {
return m;
}
}
}
return null;
}
function defineEnum(definition) {
var k;
var e = new Enum();
for(k in definition) {
var j = definition[k];
e[k] = j;
e.addEnum(j)
}
return e;
}
Ve envanterinizi şöyle tanımlarsınız:
var COLORS = defineEnum({
RED : {
value : 1,
string : 'red'
},
GREEN : {
value : 2,
string : 'green'
},
BLUE : {
value : 3,
string : 'blue'
}
});
Ve bu sizin enumlarınıza nasıl erişeceğiniz:
COLORS.BLUE.string
COLORS.BLUE.value
COLORS.getByName('BLUE').string
COLORS.getByValue('value', 1).string
COLORS.forEach(function(e){
// do what you want with e
});
Genellikle enonları mesaj nesnelerinden eşlemek için son 2 yöntemi kullanırım.
Bu yaklaşımın bazı avantajları:
- Envanteri beyan etmek kolay
- Enumlarınıza kolayca erişin
- Enemleriniz karmaşık tipler olabilir
- Enum sınıfı, getByValue'yi çok kullanırsanız bazı ilişkilendirilebilir önbelleğe alma özelliğine sahiptir.
Bazı dezavantajları:
- Bazı karışık bellek yönetimi oraya gidiyor,
- Hala güvenlik yok
15
2018-05-15 09:26