JavaScript'te undefined'ın üzerine yazılmadığını varsaymak gerçekten ne kadar tehlikelidir?


87

Her zaman kimse karşı test bahseder undefined, 's sivri dışarıundefined öylesine bir anahtar kelime değil o ayarlı olabilir"hello" , böylece kullanmanız gereken typeof x == "undefined" yerine. Bu bana gülünç geliyor. Bunu kimse asla yapmaz ve eğer yapsalardı bu, yazdıkları hiçbir kodu asla kullanmamaları için yeterli bir sebep olurdu ... değil mi?

Bulduğum bir örnek yanlışlıkla set birinin undefinedetmek nullve bu varsayarak önlemek için bir neden olarak verildi undefinedyazılmaz. Ama bunu yapmış olsalardı, böcek tespit edilmezdi ve bunun nasıl daha iyi olduğunu göremezdim.

C ++ 'da herkes söylemenin yasal olduğunun farkındadır #define true false, ancak kimse bunun yerine kaçınmanızı trueve kullanmanızı tavsiye etmez 0 == 0. Sadece kimsenin bunu yapacak kadar büyük bir aptal olmayacağını varsayarsınız ve eğer yaparlarsa, bir daha asla kodlarına güvenmeyin.

Bu, başka birinin atandığı undefined(kasıtlı olarak) birini ısırdı mı ve kodunuzu kırdı mı, yoksa bu daha çok varsayımsal bir tehdit mi? Kodumu marjinal olarak daha okunaklı hale getirmek için şansımı denemek istiyorum. Bu gerçekten kötü bir fikir mi?

Reiterate için, ben am değil tanımsız yeniden karşı korumak için nasıl soran. Bu püf noktalarının 100 defa yazıldığını gördüm. Bu numaraları kullanmamanın ne kadar tehlikeli olduğunu soruyorum.


7
Memnun olurum, ancak verilen üç cevabın hiçbirinin soruyu cevaplamak için iyi bir iş çıkardığını düşünmüyorum. Bağlantı kurduğum cevapların yeniden sorulmasını istemediğimi netleştirmeye çalıştım, ama yine de sahip olduğum şey bu. Eğer sorduğum cevap bu olmasa bile bir cevabı kabul etmemekle ilgili olarak düşünülürse, bana bildirin ve ben devam edip bir cevabı kabul edeceğim!
Cosmologicon

1
Yine de tüm gerçeklerin burada ortaya konduğunu düşünüyorum. Öyleyse, söylediğiniz şey bunun yerine öznel bir cevap veya fikir istiyorsunuz, bu sadece anlaşmazlığa yol açar. Soru başlıklarında "en iyi uygulama" ifadesine izin verilmemesinin nedeni budur. Senaryonuzda bunun ne kadar tehlikeli olduğunu bilen tek kişi sizsiniz. Ve tüm 'değişkenleri' kontrol etmediğiniz popüler bir kitaplık yazıyorsanız, işlev (tanımsız) {} sarmalayıcı mükemmel bir cevap gibi görünüyor. Neden kullanıp bu cevabı kabul etmiyorsun?
shannon

4
Birisi birisinin yeniden tanımlanmasından undefinedendişe duyuyorsa, birinin yeniden tanımlaması konusunda daha fazla endişelenmelisiniz XMLHttpRequest, veya alert. Kullandığımız tüm işlevler windowyeniden tanımlanabilirdi. Ve bir iş arkadaşınızın bunu kazara yapmasından endişeleniyorsanız, neden yapmamalarına güvenesiniz window.addEventListener = "coolbeans"? Cevap, bunların hiçbiri için endişelenmemektir. Birisi sayfanıza kötü niyetle JS enjekte ediyorsa, yine de ısmarlanırsınız. İlk başta bunun olmasını önlemek için çalışın .
Chris Middleton

Yanıtlar:


57

Hayır, hiç yapmadım. Bunun nedeni çoğunlukla ECMAScript 5 uyumlu modern tarayıcılarda geliştirme yapmamdır. ES5 standardı undefined, artık salt okunur olduğunu belirtir . Katı modu kullanırsanız (yapmanız gerekir), yanlışlıkla değiştirmeye çalışırsanız bir hata atılır.

undefined = 5;
alert(undefined); // still undefined
'use strict';
undefined = 5; // throws TypeError

Eğer gerekenler değil is Kendi Dürbünlü oluştururum, değişken undefined:

(function (undefined) {
    // don't do this, because now `undefined` can be changed
    undefined = 5;
})();

Sabit iyidir. Hala gereksiz, ama iyi.

(function () {
    const undefined = void 0;
})();

İlk ifadeniz yalnızca geliştirme sırasında yanlışlıkla tanımlanmayanların üzerine yazmamanızı sağlar, istemci bilgisayarlarda diğer kodlarla çalışırken yine de aynı tehdidi oluşturur.
bennedich

1
@bennedich: Biliyorum, bu problemle hiç karşılaşmadım diyordum ama yapman gereken şu .
Ry-

1
@bennedich Yanlışlıkla başka bir değişkenin üzerine yazma şansınız aynı değil mi?
Ateş Goral

40

Hiçbir doğru kod böyle bir şey yapmaz. Ancak bir akıllı geliştiricinin veya bir eklenti / kitaplık / komut dosyasının ne yaptığını asla bilemezsiniz. Öte yandan, bu son derece düşük bir ihtimaldir ve modern tarayıcılar hiçbir şekilde üzerine yazmaya izin vermez undefined, bu nedenle geliştirme için böyle bir tarayıcı kullanıyorsanız, herhangi bir kodun üzerine yazmaya çalışıp çalışmadığını hemen fark edeceksiniz.


Ve siz sormamış olsanız bile - birçok kişi muhtemelen bu soruyu daha yaygın olan "yeniden tanımlanmaya karşı nasıl korunmalı undefined" sorununu ararken bulacaktır , bu yüzden yine de yanıtlayacağım:

Tarayıcı ne kadar eski olursa olsun, gerçekten tanımlanmamış olmanın çok iyi bir yolu undefinedvar:

(function(undefined) {
    // your code where undefined is undefined
})();

Bu işe yarar çünkü belirtilmeyen bir bağımsız değişken her zaman olur undefined. Bunu bazı gerçek argümanları kabul eden bir işlevle de yapabilirsiniz, örneğin jQuery kullanırken bu gibi. Bu şekilde mantıklı bir ortam sağlamak genellikle iyi bir fikirdir:

(function($, window, undefined) {
    // your code where undefined is undefined
})(jQuery, this);

O zaman bu anonim işlevin içinde aşağıdaki şeylerin doğru olduğundan emin olabilirsiniz:

  • $ === jQuery
  • window === [the global object]
  • undefined === [undefined].

Ancak, not bazen typeof x === 'undefined'gerçekten gereklidir: değişken ise xbir değere (olmasının aksine kümesi olmamıştı seti için undefinedokuma) xgibi farklı bir şekilde if(x === undefined)bir hata verir. Ancak bu, nesne özellikleri için geçerli değildir, bu nedenle bunun yher zaman bir nesne olduğunu biliyorsanız if(y.x === undefined), tamamen güvenlidir.


2
Hakkında İfadende xbir değere getirilmedim (bkz oldukça doğru değildir jsfiddle.net/MgADz ); daha ziyade gerçekten tanımlanmamışsa (bkz. jsfiddle.net/MgADz/1 ).
Ry-

7
Yine, birisi yanlışlıkla bunun undefined = someVariablebir hata olduğunu söylüyorsa ve işlerin bozulmasını istiyorsanız . En azından ben yapıyorum.
Cosmologicon

2
Tanımlanmayanın üzerine yazan küçültülmüş eski bir komut dosyasına sahip bir kod tabanıyla çalıştım, komut dosyasını yeniden yazmak için zamanımız veya bütçemiz yoktu, bu, typeof x == "tanımsız" ın gerekli olduğu bir örnek, o kadar da garip değil ve muhtemelen iyi bir alışkanlık.
Damen TheSifter

2
Neden tüm örneklerin işlevde ek argüman olarak "tanımsız" ı kullandığını merak ediyorum? Ancak, birisinin hatalı olarak fazladan bir parametre (tanımlanmış) geçmesi ve tüm mantıkların başarısız olması durumu olabilir. Neden function () gibi bir şey kullanmıyorsunuz {var _undef; eğer (bazıVal == _undef) {bir şeyler yap}};
Oleksandr_DJ

4
@Oleksandr_DJ Kesinlikle. Bir o değeri Makyaj biliyor olduğunu undefinedolduğunu ve ata undefinedkapsamında. "Çok fazla" argüman iletirseniz üzerine yazmak için açık bırakmayın undefined. Bu, hataları davet eder ve doğası gereği savunmaya yönelik olmayan bir modeldir, özellikle de Lucero'nun da işaret ettiği gibi undefined, kapsamda katı değerler elde etmek için çok kolay alternatifler olduğunda .
2014

19

Bunun basit bir çözümü var: void 0Her zaman tanımsız olanla karşılaştırın.

==Değerleri zorlayabileceğinden kaçınmanız gerektiğini unutmayın . Kullanım ===(ve !==) onun yerine.

Bununla birlikte, tanımlanmamış değişken, birisi bir şeyi karşılaştırmak =yerine yazarsa, hata ile ayarlanabilir .==undefined


IMO, bu en iyi cevap.
abhisekp

1
Bu uyumluluk tablosunda görebileceğiniz foo === void 0gibi foo === undefined, bunun kadar pürüzsüz okunmayabileceğini ve değişmezin undefinedmodern tarayıcılar (IE 9+) tarafından tamamen desteklendiğini düşünün .
Daniel AR Werner

3

Hangi kodu kullandığınızı ve dolayısıyla ne kadar tehlikeli olduğunu yalnızca siz bilirsiniz. Bu soru, cevaplanmasını istediğinizi açıkladığınız şekilde cevaplanamaz.

1) Bir ekip politikası oluşturun, tanımlanmayanın yeniden tanımlanmasına izin vermeyin, daha popüler kullanımı için ayırın. Tanımlanmamış sol atama için mevcut kodunuzu tarayın.

2) Tüm senaryoları kontrol etmiyorsanız, kodunuz sizin veya politikalarınızın kontrol ettiği durumlar dışında kullanılıyorsa, cevabınız kesinlikle farklıdır. Komut dosyalarınızı kullanan kodu tarayın. Heck, isterseniz tanımlanmamış sol atamanın istatistikleri için web'i tarayın, ancak bunun sizin için yapıldığından şüpheliyim, çünkü burada sadece 1 veya 3 numaralı cevabı takip etmek daha kolay.

3) Ve eğer bu cevap yeterince iyi değilse, bunun nedeni muhtemelen yine farklı bir cevap istemenizdir. Belki kurumsal güvenlik duvarları içinde kullanılacak popüler bir kitaplık yazıyorsunuz ve arama koduna erişiminiz yok. O zaman buradaki diğer güzel cevaplardan birini kullanın. Popüler jQuery kitaplığının ses kapsüllemeyi uyguladığına dikkat edin ve başlar:

(function( window, undefined ) {

Sorunuzu yalnızca aradığınız şekilde yanıtlayabilirsiniz. Söyleyecek daha ne var?

edit: ps gerçekten benim fikrimi istiyorsan, sana hiç de tehlikeli olmadığını söyleyeceğim. Kusurlara neden olması muhtemel olan her şey (açık bir şekilde iyi belgelenmiş riskli bir davranış olan, tanımlanmamışa atamak gibi) kendi başına bir kusurdur. Risk olan kusurdur. Ama bu sadece benim senaryolarımda, bu perspektife sahip olmayı göze alabildiğim yer. Size tavsiye ettiğim gibi, kullanım durumlarım için soruyu cevapladım.


3

Tanımsız'a karşı test etmek güvenlidir. Zaten bahsettiğiniz gibi. Eğer onu geçersiz kılan (ki bu oldukça geliştirilebilir) bir koda ulaşırsanız, artık onu kullanmayın.

Belki kamu kullanımı için bir kütüphane oluşturuyorsanız, kullanıcının değiştirmesini önlemek için bazı teknikleri kullanabilirsiniz. Ancak bu durumda bile bu onların sorunu, kitaplığınız değil.


2

undefinedECMAScript 5.1'i destekleyen tarayıcıları kodlarken , dil spesifikasyonuna göre değişmez olduğu için kodunuzda kullanabilirsiniz .

Ayrıca, bu uyumluluk tablosuna bakın veya bu , tüm modern tarayıcıların (IE 9+) immutable uyguladığını görmek için ECMAScript 5'i kullanabilir .undefined


1

Hiç tehlikeli değil. Yalnızca bir ES3 motorunda çalışırken üzerine yazılabilir ve bunun artık kullanılma olasılığı yoktur.


0

Her şeyden önce, eğer kodunuz bozulursa bunun nedeni muhtemelen dışarıdaki başka bir geliştiricinin sizin deyiminizle "aptal olmaya çalıştığı" değildir.

Bunun undefinedbir anahtar kelime olmadığı doğrudur . Ama olan ilkel bir küresel düzeyde. Bu şekilde kullanılması amaçlanmıştır ( developer.mozilla.org adresindeki "tanımsız" bölümüne bakın ):

var x;
if (x === undefined) {
    // these statements execute
}
else {
    // these statements do not execute
}

Bunun ortak alternatifi (ayrıca MDN'den ) ve bence daha iyi yol:

// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
    // these statements execute
}

if(x === undefined){ // throws a ReferenceError

}

Birkaç avantajı olan, (yorumlardan) bariz olanı, x bildirilmediğinde bir istisnayı tetiklememesidir. MDN ayrıca kullanılmasının önemli olduğuna işaret dikkati çekiyor da bu kadar ===aşırı ==İlk durumda çünkü:

var x=null;
if (x === undefined) {
    // this is probably what you meant to do
    // these lines will not execute in this case
}
else if (x == undefined) {
    // these statements will execute even though x *is* defined (as null)
}
else {
    // these statements do not execute
}

Bu, her durumda ikinci alternatifi kullanmanın muhtemelen daha iyi olmasının bir başka sıklıkla gözden kaçan nedenidir.

Sonuç: İlk olarak kodlamak yanlış ve kesinlikle tehlikeli değildir. Buna karşı örnek olarak kullandığınız gördüğünüz argüman (üzerine yazılabileceği), alternatifi kodlamak için en güçlü argüman değil typeof. Ancak kullanmak typeof, özellikle bir nedenle daha güçlüdür: varlığınız bildirilmediğinde bir istisna oluşturmaz. Bunun ==yerine kullanmanın ===yaygın bir hata olduğu ve bu durumda beklediğiniz şeyi yapmadığı da tartışılabilir . Öyleyse neden kullanmıyorsunuz typeof?


1
"Birkaç avantajı olan, açık olanı, x bildirilmediğinde bir istisnayı tetiklememesidir." Şunu açıklığa kavuşturayım. Bildirilmemiş bir değişken kullandığınızda meydana gelen istisnayı sessizce görmezden gelmenin bir avantaj olduğunu mu düşünüyorsunuz ? Bu hataya çok açık görünüyor. Bunun neden korkunç bir dezavantaj olmadığını düşündüğünüzü açıklayabilir misiniz?
Cosmologicon
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.