Vacuousness
Tüm dünyadaki herhangi bir değerin boş olup olmadığını hesaplayan bir işlev tanımlamaya veya kullanmaya çalışmanızı önermiyorum. Gerçekten "boş" olmak ne anlama geliyor? Eğer varsa let human = { name: 'bob', stomach: 'empty' }, isEmpty(human)geri dönmeli truemi? Eğer varsa let reg = new RegExp('');, isEmpty(reg)geri dönmeli truemi? Ne oldu isEmpty([ null, null, null, null ])- bu liste sadece boşluk içeriyor, bu yüzden listenin kendisi boş mu? Ben burada javascript "boşluk" (kasıtlı olarak karanlık bir kelime, önceden var olan ilişkilendirmeleri önlemek için) bazı notlar koymak istiyorum - ve ben javascript değerleri "boşluk" asla genel olarak ele gerektiğini tartışmak istiyorum.
Truthiness / Falsiness
Değerlerin "boşluğunu" nasıl belirleyeceğimize karar vermek için, javascript'in dahili, içsel, değerlerin "doğru" veya "sahte" olup olmadığını anlamamız gerekir. Doğal olarak, nullve undefinedher ikisi de "falsy" dir. Daha az doğal olarak, sayı 0(ve başka hiçbir sayı hariç NaN) de "sahte" dir. Doğal olarak en az: ''sahtelik, ama []ve {}(ve new Set(), ve new Map()) doğrudur - hepsi eşit derecede boş görünüyor!
Null ve Tanımsız
İle ilgili bazı tartışmalar da vardır nullvs undefinedbiz gerçekten bizim programlarında vacuousness ifade etmek amacıyla ikisine de ihtiyacım var? - Şahsen ben bu sırayla kodumda u, n, d, e, f, i, n, e, d harflerinin görünmesini önlerim. Her zaman null"boşluk" anlamına gelir. Yine de, javascript'in doğasında nasıl nullve nasıl undefinedfarklı olduğu fikrini karşılamak zorundayız :
- Var olmayan bir mülke erişmeye çalışmak,
undefined
- Bir işlevi çağırırken bir parametrenin atlanması o parametrenin alınmasına neden olur
undefined:
let f = a => a;
console.log(f('hi'));
console.log(f());
- Varsayılan değerlere sahip parametreler varsayılanı yalnızca verildiğinde alır
undefined, değil null:
let f = (v='hello') => v;
console.log(f(null));
console.log(f(undefined));
Jenerik Olmayan Boşluk
Boşluğun asla genel bir şekilde ele alınmaması gerektiğine inanıyorum. Bunun yerine her zaman boş olup olmadığını belirlemeden önce verilerimiz hakkında daha fazla bilgi almak için titizliğe sahip olmalıyız - Bunu esas olarak hangi tür verilerle uğraştığımı kontrol ederek yaparım:
let isType = (value, Cls) => {
try {
return Object.getPrototypeOf(value).constructor === Cls;
} catch(err) {
return false;
}
};
Bu işlevin polimorfizmi yok saydığına dikkat edin - bunun bir alt sınıfının örneği değil, valuedoğrudan bir örneği olmasını bekler . İki ana nedenden dolayı kaçınırım :ClsClsinstanceof
([] instanceof Object) === true ("Dizi Nesnedir")
('' instanceof String) === false ("Bir Dize Bir Dize Değildir")
Bu işlev Object.getPrototypeOfgibi bir durumu önlemek için kullanıldığını unutmayın let v = { constructor: String };( isTypeişlev) hala isType(v, String)(false) ve isType(v, Object)(true) için doğru döner .
Genel olarak, bu isTypeişlevi aşağıdaki ipuçlarıyla birlikte kullanmanızı öneririz :
- Bilinmeyen türdeki kod işleme değerlerinin miktarını en aza indirin. Örneğin, için
let v = JSON.parse(someRawValue);, bizim vdeğişken artık bilinmeyen türde. Mümkün olduğunca erken, olasılıklarımızı sınırlamalıyız. Bunu yapmanın en iyi yolu, belirli bir tür gerektirmek olabilir: örneğin if (!isType(v, Array)) throw new Error('Expected Array');- bu, genel doğasını kaldırmak ve vher zaman bir sağlamak için gerçekten hızlı ve etkileyici bir yoldur Array. Ancak bazen, vbirden fazla türde olmasına izin vermemiz gerekir . Bu durumlarda, vmümkün olduğunca erken, artık genel olmayan kod blokları oluşturmalıyız :
if (isType(v, String)) {
/* v isn't generic in this block - It's a String! */
} else if (isType(v, Number)) {
/* v isn't generic in this block - It's a Number! */
} else if (isType(v, Array)) {
/* v isn't generic in this block - it's an Array! */
} else {
throw new Error('Expected String, Number, or Array');
}
- Doğrulama için her zaman "beyaz listeleri" kullanın. Bir değerin örneğin Dize, Sayı veya Dizi olmasını istiyorsanız, bu 3 "beyaz" olasılığı kontrol edin ve 3'ten hiçbiri tatmin olmazsa bir Hata atın. "Siyah" olasılıkları kontrol etmenin çok yararlı olmadığını görebilmeliyiz: Diyelim ki yazıyoruz
if (v === null) throw new Error('Null value rejected');- bu, nulldeğerlerin bunu gerçekleştirmemesini sağlamak için harikadır , ancak bir değer bunu başarırsa , hala çok az şey biliyoruz bunun hakkında herhangi bir şey. vBu boş denetimi geçen bir değer hala ÇOK genel - bir şey amanull ! Kara listeler jenerikliği neredeyse hiç yok etmez.
Bir değer olmadığı sürece null, asla "boş bir değer" olarak düşünmeyin. Bunun yerine "boş olan bir X" düşünün. Esasen, asla böyle bir şey yapmayı düşünmeyin if (isEmpty(val)) { /* ... */ }- bu isEmptyfonksiyon nasıl uygulanırsa uygulansın (bilmek istemiyorum ...), anlamlı değil! Ve bu çok genel! Boşluk yalnızca türünün bilgisi ile hesaplanmalıdır val. Boşluk kontrolleri şöyle görünmelidir:
- "Karakter içermeyen bir dize":
if (isType(val, String) && val.length === 0) ...
- "0 sahne olan bir nesne":
if (isType(val, Object) && Object.entries(val).length === 0) ...
- "Sıfıra eşit veya sıfırdan küçük bir sayı":
if (isType(val, Number) && val <= 0) ...
"Öğe içermeyen bir Dizi": if (isType(val, Array) && val.length === 0) ...
Bunun tek istisnası, nullbelirli işlevleri belirtmek için kullanıldığındadır. Bu durumda "Boş bir değer" demek anlamlı:if (val === null) ...