Değişken atama if koşul ifadesi, iyi uygulama mı değil mi? [kapalı]


113

Bir yıl önce Java gibi klasik OO dillerinden JavaScript'e geçtim. Aşağıdaki kod Java'da kesinlikle önerilmez (hatta doğru değildir):

if(dayNumber = getClickedDayNumber(dayInfo))
{
    alert("day number found : " + dayNumber);
}
function getClickedDayNumber(dayInfo)
{
    dayNumber = dayInfo.indexOf("fc-day");
    if(dayNumber != -1) //substring found
    {
        //normally any calendar month consists of "40" days, so this will definitely pick up its day number.
        return parseInt(dayInfo.substring(dayNumber+6, dayNumber+8));
    }
    else return false;
}

Temel olarak, if koşul ifadesindeki bir değere bir değişken atayabileceğimi ve atanan değeri sanki booleanmış gibi hemen kontrol edebileceğimi öğrendim.

Daha güvenli bir bahis için, genellikle bunu iki satır koda ayırırım, önce atarım sonra değişkeni kontrol ederim, ancak şimdi bunu bulduğuma göre, deneyimli JavaScript geliştiricilerinin gözünde bunun iyi bir uygulama olup olmadığını merak ediyorum.


"The following code is definitely not recommended (or event not correct) in Java..."JavaScript'te bile doğru mu? Çünkü görebildiğim kadarıyla, return parseInt(...)eğer dayNumber != -1doğruysa bir tamsayı ( ) , yanlışsa bir boole döndürüyorsunuz.
Daniel Kvist

Yanıtlar:


117

Bunu tavsiye etmem. Sorun şu ki, değerleri karşılaştırmaya çalıştığınız, ancak veya =yerine tek bir tane kullandığınız yaygın bir hata gibi görünüyor . Örneğin, bunu gördüğünüzde:=====

if (value = someFunction()) {
    ...
}

Yapmak istediklerinin bu mu, yoksa bunu yazmak isteyip istemediklerini bilmiyorsunuz:

if (value == someFunction()) {
    ...
}

Görevi gerçekten yerinde yapmak istiyorsanız, aynı zamanda açık bir karşılaştırma yapmanızı da tavsiye ederim:

if ((value = someFunction()) === <whatever truthy value you are expecting>) {
    ...
}

1
@Matthew Crumley: Bu, soruma net bir şekilde cevap veriyor. Atayarak değil, atamadan sonra değer olarak değerlendirilen değeri kontrol ediyorum. Bu anlayış doğru mu?
Michael Mao

1
@Michael: evet, bu doğru. Karşılaştırmayı eklemek temelde niyetlerinizi daha net hale getirir.
Matthew Crumley

4
Bununla birlikte, bir boole döndüren bir işlevin başarısızlığını / başarısını test ediyorsanız, son örnek çalışmaz. Başka bir deyişle, if (resultArr = myNeedle.exec(myHaystack)) {...}işe if ((resultArr = myNeedle.exec(myHaystack)) === true) {...}yararken, sonuçArr'a yapılan atama işlevin sonucu olmasa bile her zaman doğru olduğu için değildir. Bu .. yapısını kullanan biri varsa, önce sonuç değişkenini bildirmeyi unutmayın; if koşul ifadesi içinde 'var' yasal değildir.
Ville

3
Kullanabilirsin if (!!(value = someFunction())), ama dediğin gibi, sorun şu ki, variçeride kullanamıyorsun, bu ifyüzden ya bir global yaratıyorsun ya da valuezaten ayrı bir satırda beyan etmek zorunda kaldığın gibi hiçbir şey elde etmiyorsun . Utanç, bu yapıyı C ++ 'da gerçekten beğendim.
riv

1
@riv, haklısın; fonksiyonun bir boole döndürmesi durumunda - yukarıdaki yorumumda söylediğim gibi - o zaman koşullu beklendiği gibi çalışır. Ancak işlev bir mantıksal değer döndürürse (benim örneğimde olduğu gibi), tüm yapı bir tür anlamsızdır; Açıkça benim düşüncem - örnekten yola çıkarak - fonksiyonun bir dizi döndüreceğiydi. Hızlı bir test, koşulun trueyalnızca işlev döndüğünde değerlendirildiğini true, ancak diğer tüm durumlarda (bir dizi, dize, sayı veya null döndürüldüğünde dahil olmak üzere) olarak değerlendirildiğini gösterir false.
Ville

28

Bunun iyi bir uygulama olmadığına dair bir kanıt göremiyorum. Evet, bir hata gibi görünebilir, ancak bu mantıklı yorumlarla kolayca giderilebilir. Örneğin alın:

if (x = processorIntensiveFunction()) { // declaration inside if intended
    alert(x);
}

Neden bu işlevin aşağıdakilerle 2. kez çalışmasına izin verilsin:

alert(processorIntensiveFunction());

Çünkü ilk sürüm kötü GÖRÜNÜYOR? Bu mantığa katılmıyorum.


32
Eski bir yorumu karıştırmak istemem ama argümanlarınıza katılmıyorum. Okunabilir kod, bir yoruma ihtiyaç duymadan kendini açıklamalıdır - kafa karıştırıcı koda yorum eklemek çare değildir. Alternatifin fonksiyonu tekrar çağırmak olduğunu söyleyen ikinci kısma gelince, kimsenin bunu yapmaya niyetli olduğunu düşünmüyorum. Bunun yerine yapardınx = processorItensiveFunction(); if(x) { alert(x); }
maksim

9
@maksim: Okunabilir kodu severim, ancak bu kodun basitleştirilmesi veya çok ayrıntılı olması gerektiği anlamına gelmez. Bir şeyleri birden çok satıra yaymak ve değişkenler arasında değerleri karıştırmak aslında daha kötü kodlara yol açabilir. Eklenen kod, JS gibi zayıf yazılmış / esnek bir dilde öngörülemeyen yan etkilere sahip olabilir. Bir koşullu ifadede atama javascript'te geçerlidir, çünkü sadece "atama geçerliyse, muhtemelen atamanın sonucunu içeren bir şey yapın" diye soruyorsunuz. Ama aslında, koşulludan önce atama da geçerlidir, çok ayrıntılı değildir ve daha yaygın olarak kullanılır.
okdewit

1
@maksim neden if ( ! x = anyFunction() )okunabilir olmadığını düşünüyorsunuz ? Herhangi bir yoruma ihtiyaç duymaz.
JDrake

OPC'yi düzeltirseniz, farklı beceri seviyelerine sahip diğer geliştiricilerle çalışın (başka bir deyişle, siz bir profesyonelseniz), bunun mümkün olmasından bile nefret edeceksiniz.
davidjmcclelland

2
@maksim - ayrıca çözümünüz bir if-elsedurumda çok sakıncalı olacaktır . Düşünün if (condition) {...} else if (x = processorIntensiveFunction()) {alert(x)} : x = processorIntensiveFunction();Öncekiniz, başlangıç conditiondoğru olursa boşa harcanan bir çaba olur.
Adrian Bartholomew

16

Bunu birçok kez yaptım. JavaScript uyarısını atlamak için iki parantez ekliyorum:

if ((result = get_something())) { }

Bundan kaçınmalısınız, gerçekten kullanmak istiyorsanız, üstüne ne yaptığınızı söyleyen bir yorum yazın.


1
@SHiNKiROU: JavaScript uyarılarını nasıl görebilirim? Bir Javascript derleyicisi var mı? yoksa tercüman bir tür uyarı üretecek mi? Firefox konsolunu her zaman javascript hata ayıklamasında olduğu gibi kullanıyorum ama benzer çıktılar görmüyorum. Sınırlı deneyimim için üzgünüm.
Michael Mao

5
@Michael: JSLint ( jslint.com ), JavaScript programlarını olası hatalar veya kötü kodlar için kontrol eden popüler bir program / kitaplıktır.
Matthew Crumley

Uyarıları kontrol etmek için Firebug ve / veya Web Developer uzantısıyla Mozilla Firefox kullanın.
Ming-Tang

Sadece ile denedim if ((a = [1, 2]).length > 0) { console.log(a); }nerede ahenüz hiçbir yerde başlatılır değil ve gerçekten çalıştı (güzel! Çok daha kolay regex kullanarak yapar). var|const|letBuradan herhangi birine ihtiyacım olmadığı doğru mu? Bu numara hakkında daha fazla bilgiyi nerede okuyabileceğimi biliyor musun ?
t3chb0t

4

Bunu Java'da da yapabilirsiniz. Ve hayır, bu iyi bir uygulama değil. :)

(Ve ===tiplendirilmiş eşitlik için Javascript'te kullanın . Crockford'un JS'deki The Good Parts kitabını okuyun.)


@quixoto: Bu numarayı Java'da yapabilir miyim? Merak ediyorum ... elimde jdk atm yok, bu yüzden Java'da örnek bir kod alamıyorum. Zayıf belleğimden, geri dönen değer boole olmayan bir şeyi koşullu ifadede olduğu gibi değerlendirirse Java size sadece bir Çalışma Zamanı hatası verecektir, değil mi?
Michael Mao

1
Ah, evet, Java'da boole türü olması için tür denetimli. Ama olabilir yapmakif (foo = getSomeBoolValue()) { }
Ben Zotto

Evet bu doğru. bir şeyin başarılı olup olmadığını test etmek için bir boole değişkeni ve döndürülen değeri depolamak için başka bir değişken. Java'nın işini böyle yapıyor, buna çok aşinayım, bu yüzden Javascript'in tek bir satırda iki şeyi yapabildiğini görmek beni garip hissediyorum :)
Michael Mao

@BenZotto bu iyi bir uygulama değil neden? "Bir değişkenin yanlışlıkla yanlış kullanımından kaçınmak için, değişkeni mümkün olan en küçük kapsama dahil etmek genellikle iyi bir fikirdir. Özellikle, bir değişkenin tanımını bir başlangıç ​​değeri verene kadar ertelemek genellikle en iyisidir ... Bu iki ilkenin en zarif uygulamalarından biri, koşullu bir değişken bildirmektir. " - Stroustrup, "C ++ Programlama Dili."
JDrake

1
Merhaba, buraya node.js javascript kullanıcısı olarak geldim. Neden sorun yaşadığım bir durumda iyi bir uygulama yok: if (myvar = 'sadece bir test') Bir node.js GLOBAL değişkeni oluşturur myvar ( nodejs.org/docs/latest-v12.x/api/globals.html #globals_global ). Yani benim gibiyseniz ve bu değişkeni sunucu isteği işlemede kullandıysanız (birkaç saniye sonra başka istekler düştüğü zaman ona geri dönerseniz), aldığınız sonuçlara şaşırabilirsiniz. Bu yüzden öneri şudur: Bu desenin node.js'de global bir değişken oluşturduğunun farkında olun.
pein-consulting.de

4

Bunu while-döngülerle yaptığınızda bir durum var .
Dosyaları okurken, genellikle şunu yaparsınız:

void readFile(String pathToFile) {
    // Create a FileInputStream object
    FileInputStream fileIn = null;
    try {
        // Create the FileInputStream
        fileIn = new FileInputStream(pathToFile);
        // Create a variable to store the current line's text in
        String currentLine;
        // While the file has lines left, read the next line,
        // store it in the variable and do whatever is in the loop
        while((currentLine = in.readLine()) != null) {
            // Print out the current line in the console
            // (you can do whatever you want with the line. this is just an example)
            System.out.println(currentLine);
        }
    } catch(IOException e) {
        // Handle exception
    } finally {
        try {
            // Close the FileInputStream
            fileIn.close();
        } catch(IOException e) {
            // Handle exception
        }
    }
}

while9. satırdaki -loop'a bakın . Burada, yeni bir satır okunur ve bir değişkende saklanır ve ardından döngünün içeriği çalıştırılır. Bunun bir olmadığını biliyorumif ifadesi , ancak sanırım bir while döngüsü de sorunuza dahil edilebilir.

Bunun nedeni, a kullanırken FileInputStream, her çağırdığınızda FileInputStream.readLine(), dosyadaki bir sonraki satırı okur, yani eğer onu sadece fileIn.readLine() != nulldeğişkeni atamak yerine döngüden çağırırsanız , çağırmak yerine(currentLine = fileIn.readLine()) != null ve sonra onu denilen Döngünün içinde de, yalnızca her ikinci satırı alırsınız.

Umarım anlarsın ve iyi şanslar!


3

Java'da da if ifadeleri içinde atamalar yapabilirsiniz. İyi bir örnek, bir şeyi okuyup yazmak olabilir:

http://www.exampledepot.com/egs/java.io/CopyFile.html?l=new

Kod:

// Copies src file to dst file.
// If the dst file does not exist, it is created
void copy(File src, File dst) throws IOException 
{
    InputStream in = new FileInputStream(src);
    OutputStream out = new FileOutputStream(dst);

    // Transfer bytes from in to out
    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
    }
    in.close();
    out.close();
}

@Nitrodist: Bu örnek için teşekkürler. Java ya da javascript konusunda gerçekten profesyonel değilim ... Bu yaklaşımın Java'da da uygulanabilir olduğunu bilmek güzel :)
Michael Mao

Bunun amacını anlamıyorum. Java, PHP ve diğer birçok dilde yapabilirsiniz. Soru Javascript hakkındaydı.
pmrotule

Hayır, bu zorunlu değildir, soruyu dikkatlice tekrar okumanız gerekir.
Nitrodist

3

Martin Fowlers'ın mevcut kodun tasarımını iyileştirmek için Yeniden Düzenleme kitabına başvurursanız ! Daha sonra, örneğin iyi bir uygulama olabileceği birkaç durum vardır. durumunuzu ileri sürmek için bir işlev veya yöntem çağrısı kullanmak için uzun karmaşık koşul ifadeleri:

"Motivasyon

Bir programdaki en yaygın karmaşık alanlardan biri, karmaşık koşullu mantıktır. Koşulları test etmek ve çeşitli koşullara bağlı olarak çeşitli şeyler yapmak için kod yazarken, kısa sürede oldukça uzun bir yöntem elde edersiniz. Bir yöntemin uzunluğu başlı başına okumayı zorlaştıran bir faktördür, ancak koşullar zorluğu arttırır. Sorun genellikle, hem durum kontrollerinde hem de eylemlerdeki kodun size ne olduğunu söylemesi, ancak neden olduğunu kolayca gizleyebilmesi gerçeğinde yatmaktadır.

Herhangi bir büyük kod bloğunda olduğu gibi, onu ayrıştırarak ve kod parçalarını bu kod bloğunun amacına göre adlandırılan bir yöntem çağrısıyla değiştirerek amacınızı daha net hale getirebilirsiniz. > Koşullarla, bunu koşullu kısım ve alternatiflerin her biri için yaparak daha fazla fayda elde edebilirsiniz. Bu şekilde durumu vurgular ve neye daldığınızı net bir şekilde ortaya koyarsınız. Ayrıca dallanmanın nedenini de vurguluyorsunuz. "

Ve evet cevabı Java uygulamaları için de geçerli. Örneklerde olsa da, koşullu işlevi bir değişkene atamaz.


1

Bu iyi bir uygulama değil. Yakında kafanız karışacak. Genel bir hataya benziyor: kötüye kullanım "=" ve "==" operatörleri.

Bunu 2 satır koda bölmelisiniz. Yalnızca kodu daha net hale getirmekle kalmaz, aynı zamanda gelecekte yeniden düzenlemeyi de kolaylaştırır. IF koşulunu değiştirdiğinizi hayal edin? Yanlışlıkla satırı kaldırabilirsiniz ve değişkeniniz artık ona atanan değeri almayacaktır.


@thethanghn: Tam olarak korktuğum şey bu. Yaşlandıkça ve tembel ben sadece koduna daha yazın istemiyorsanız eğer daha az tuş vuruşlarını olacak sadece yeterli durumdadır :)
Michael Mao

1
Hayır, kafam karışmıyor ve bunu her zaman yapıyorum. Bunun faydaları var.
JDrake

Gerçi gerçekten bağlıdır, değil mi? 'C' geçmişinden (ve C'ye dayalı diğer dillerden) geliyorsanız, yapı çok tanıdık gelir ve alternatifler çok gariptir. IMO, bir kez öğrenilen bir şeydir ve sonra bilirsiniz. Bu, birden çok kez takılıp düşeceğiniz bir şey değil.
Max Waterman

0

Bunu daha çok eski usul bir C tarzı olarak düşünürdüm; JavaScript'te gerçekten iyi bir uygulama değildir, bu yüzden bundan kaçınmalısınız.


8
Bunun C'de de iyi bir uygulama olduğunu düşünmüyorum.
Matthew Crumley

1
Bunu birçok dilde iyi bir uygulama olarak görüyorum.
JDrake

Sadece 'iyi uygulama değil' demek yeterli değil, imo. Bu gerçekten sadece eğitimle ilgili - bir kez öğrenildi ve hepsi bu.
Max Waterman

0

şöyle bir şey yapabilirsin:

if (value = /* sic */ some_function()){
  use_value(value)
}

0

Buraya golang'dan geldim, burada yaygın olarak

if (err := doSomething(); err != nil) {
    return nil, err
}

Hangi erro kapsama aldığı ifblokta sadece. Bu nedenle, es6'da yaptığım şey şu ki, oldukça çirkin görünüyor, ancak benim oldukça katı eslint kurallarımı sızlatmıyor ve aynı şeyi başarıyor.

{
  const err = doSomething()
  if (err != null) {
    return (null, err)
  }
}

Ekstra kaşlı ayraçlar yeni bir "sözcük kapsamı" mı tanımlar? Bu da kullanabileceğim constve errdış blokta müsait olmadığım anlamına geliyor .

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.