if 조건문에 변수 할당, 모범 사례? [닫은]


113

1 년 전에 Java와 같은 고전적인 OO 언어에서 JavaScript로 옮겼습니다. 다음 코드는 Java에서 확실히 권장되지 않거나 올바르지 않습니다.

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;
}

기본적으로 방금 if 조건 문의 값에 변수를 할당하고 할당 된 값이 부울 인 것처럼 즉시 확인할 수 있다는 것을 알았습니다.

더 안전한 내기를 위해 일반적으로 코드를 두 줄로 분리하고 먼저 할당 한 다음 변수를 확인합니다.하지만 이제는 이것을 발견 했으므로 경험이 많은 JavaScript 개발자의 눈에 좋은 방법인지 아닌지 궁금합니다.


"The following code is definitely not recommended (or event not correct) in Java..."JavaScript에서도 정확합니까? 내가 볼 수있는 한 true이면 정수 ( return parseInt(...)) 를 반환하고 dayNumber != -1false이면 부울을 반환하기 때문입니다.
Daniel Kvist 2015

답변:


117

나는 그것을 추천하지 않을 것입니다. 문제는 값을 비교하려고하지만 또는 =대신 단일을 사용하는 일반적인 오류처럼 보입니다 . 예를 들어 다음과 같은 경우 :=====

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

그게 의도 한 것인지, 아니면 이렇게 작성하려고했는지 알 수 없습니다.

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

실제로 할당을 수행하려면 명시 적 비교도 수행하는 것이 좋습니다.

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

1
@Matthew Crumley : 이것은 내 질문에 명확한 방법으로 대답합니다. 할당을 통해 확인하는 것이 아니라 할당 후 값이 무엇인지 확인합니다. 이 이해가 맞습니까?
Michael Mao

1
@Michael : 네, 맞습니다. 비교를 추가하면 기본적으로 의도가 더 명확 해집니다.
Matthew Crumley 2010-04-05

4
그러나 부울을 반환하는 함수의 실패 / 성공을 테스트하는 경우 마지막 예제는 작동하지 않습니다. 즉, if (resultArr = myNeedle.exec(myHaystack)) {...}작동 하는 동안 if ((resultArr = myNeedle.exec(myHaystack)) === true) {...}함수 결과가 아닌 경우에도 resultArr에 대한 할당이 항상 진실이기 때문이 아닙니다. 누군가 this .. 구조를 사용하는 경우 먼저 결과 변수를 선언해야합니다. 'var'는 if 조건문 내에서 유효하지 않습니다.
Ville

3
를 사용할 수 if (!!(value = someFunction()))있지만 말했듯이 문제는 var내부에서 사용할 수 없으므로 if결국 전역을 만들거나 value어쨌든 별도의 줄에서 선언해야하므로 아무것도 달성하지 못한다는 것 입니다. 부끄러워, 나는 C ++로이 구조를 정말 좋아했다.
riv

1
@riv, 당신 말이 맞아요; 함수가 부울을 반환하는 경우-위의 설명에서 말했듯이-조건부 예상대로 작동합니다. 그러나 함수가 부울을 반환하면 (제 예에서와 같이) 전체 구조는 일종의 의미가 없습니다. 분명히 내 생각은 – 예제에서 판단 할 때 – 함수가 배열을 반환한다는 것입니다. 빠른 테스트는 true함수가를 반환 할 때만 조건이 평가 true되지만 다른 모든 경우 (배열, 문자열, 숫자 또는 null이 반환되는 경우 포함)에서는 조건이으로 평가됨을 나타 false냅니다.
Ville

28

좋은 습관이 아니라는 증거는 없습니다. 예, 실수처럼 보일 수 있지만 현명한 댓글로 쉽게 해결할 수 있습니다. 예를 들어 :

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

이 함수가 다음과 같이 두 번째로 실행되도록 허용해야하는 이유 :

alert(processorIntensiveFunction());

첫 번째 버전이 나빠 보이기 때문에? 나는 그 논리에 동의 할 수 없습니다.


32
오래된 의견을 파 헤치려는 것은 아니지만 나는 당신의 주장에 동의하지 않습니다. 읽을 수있는 코드는 주석이 필요없이 스스로 설명되어야합니다. 혼란스러운 코드에 주석을 추가하는 것은 해결책이 아닙니다. 두 번째 부분에 관해서는 대안이 함수를 다시 호출하는 것이라고 말하고 있지만 누구도 그렇게하려는 의도는 없다고 생각합니다. 대신 당신이 할 것x = processorItensiveFunction(); if(x) { alert(x); }
막심

9
@maksim : 읽을 수있는 코드를 좋아하지만, 그렇다고해서 코드가 멍청하거나 너무 장황해야한다는 의미는 아닙니다. 여러 줄에 걸쳐 분산하고 변수간에 값을 저글링하면 실제로 코드가 더 나빠질 수 있습니다. 삽입 된 코드는 JS와 같이 형식이 약한 / 유연한 언어에서 예기치 않은 부작용을 일으킬 수 있습니다. 조건 문의 할당은 자바 스크립트에서 유효합니다. "할당이 유효한 경우 할당 결과를 포함 할 수있는 작업을 수행하십시오." 그러나 실제로 조건문 앞에 할당하는 것도 유효하고 너무 장황하지 않고 더 일반적으로 사용됩니다.
okdewit 2015

1
@maksim 왜 if ( ! x = anyFunction() )읽을 수 없다고 생각 하십니까? 주석이 전혀 필요하지 않습니다.
JDrake 2017-06-08

OPC를 수정하고 다양한 기술 수준의 다른 개발자와 함께 작업하면 (즉, 전문가입니다) 이것이 가능하다는 사실을 싫어할 것입니다.
davidjmcclelland

2
@maksim-또한 귀하의 솔루션은 if-else상황 에서 매우 불편할 것 입니다. 고려 if (condition) {...} else if (x = processorIntensiveFunction()) {alert(x)} - x = processorIntensiveFunction();이니셜 condition이 사실이라면 이전 은 낭비되는 노력이 될 것입니다.
Adrian Bartholomew 19

16

나는 그것을 여러 번했다. JavaScript 경고를 우회하기 위해 두 개의 괄호를 추가합니다.

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

그것을 피해야합니다. 정말로 그것을 사용하고 싶다면 그 위에 무엇을하고 있는지에 대한 주석을 작성하십시오.


1
@SHiNKiROU : 자바 스크립트 경고를 어떻게 볼 수 있습니까? Javascript 컴파일러가 있습니까? 아니면 통역사가 일종의 경고를 생성합니까? 나는 항상 자바 스크립트 디버깅에서와 같이 Firefox 콘솔을 사용하고 있지만 비슷한 출력을 보지 못했습니다. 제한된 경험에 대해 죄송합니다.
Michael Mao

5
@Michael : JSLint ( jslint.com )는 JavaScript 프로그램에서 가능한 실수 나 잘못된 코드를 확인하는 인기있는 프로그램 / 라이브러리입니다.
Matthew Crumley

Mozilla Firefox와 Firebug 및 / 또는 Web Developer 확장을 사용하여 경고를 확인합니다.
Ming-Tang

나는 아직 어디서도 초기화되지 않은 if ((a = [1, 2]).length > 0) { console.log(a); }곳에서 시도했지만 a실제로 작동했습니다 (좋습니다! 정규식 사용이 훨씬 쉬워집니다). var|const|let여기에서 필요하지 않은 것이 맞 습니까? 이 트릭 에 대해 더 많이 읽을 수있는 곳을 아십니까 ?
t3chb0t

4

Java에서도이 작업을 수행 할 수 있습니다. 그리고 그것은 좋은 습관이 아닙니다. :)

(그리고 ===형식화 된 동등성을 위해 자바 스크립트에서 사용하십시오 . JS에 대한 Crockford의 The Good Parts 책을 읽어보십시오.)


@quixoto : Java에서이 트릭을 할 수 있습니까? 궁금합니다 ... 손으로 jdk가 없어서 Java로 샘플 코드를 얻을 수 없습니다. 내 빈약 한 메모리에서 반환 값이 if 조건문과 같이 부울이 아닌 것을 평가하면 Java는 런타임 오류를 얻습니다.
Michael Mao

1
아, 예, Java에서는 부울 유형으로 유형 검사됩니다. 하지만 당신은 할 수 있습니다if (foo = getSomeBoolValue()) { }
벤 Zotto

응, 그거야. 성공 여부를 테스트하는 부울 변수와 반환 된 값을 저장할 다른 변수. 그것이 Java가 그 일을하는 방식입니다. 저는 그것에 너무 익숙해서 Javascript가 한 줄로 두 가지 일을 할 수 있다는 것을 보는 것이 이상하다고 느낍니다. :)
Michael Mao

@ BenZotto 그것은 좋은 습관이 아닌 이유는 무엇입니까? "우연한 변수의 오용을 방지하려면 일반적으로 변수를 가능한 한 가장 작은 범위에 도입하는 것이 좋습니다. 특히 변수 정의를 초기 값을 제공 할 수있을 때까지 지연하는 것이 가장 좋습니다. 이 두 가지 원칙의 가장 우아한 응용 프로그램 중 하나는 조건부로 변수를 선언하는 것입니다. " -Stroustrup, "C ++ 프로그래밍 언어".
JDrake 2017-06-08

1
안녕하세요, 저는 node.js 자바 스크립트 사용자로 여기에 왔습니다. 내가 고통을 겪은 한 가지 경우에 좋은 습관이 아닌 이유 : if (myvar = 'just a test') node.js GLOBAL 변수 myvar ( nodejs.org/docs/latest-v12.x/api/globals.html #globals_global ). 따라서 저와 같고 서버 요청 처리에서 해당 변수를 사용했다면 (다른 요청이 들어 왔을 수있는 몇 초 후에 다시 돌아옴) 어떤 결과를 얻게되는지 놀라실 수 있습니다. 따라서 권장 사항은 다음과 같습니다.이 패턴은 node.js에 전역 변수를 생성합니다.
pein-consulting.de

4

while루프를 사용 하는 경우가 하나 있습니다 .
파일을 읽을 때 일반적으로 다음과 같이합니다.

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 행 에서 -loop를 보십시오. 거기에서 새로운 행을 읽고 변수에 저장 한 다음 루프의 내용을 실행합니다. 나는 이것이-문이 아니라는 것을 알고 if있지만 while 루프도 귀하의 질문에 포함될 수 있다고 생각합니다.

이에 대한 이유는를 사용하는 경우이다 FileInputStream, 당신이 전화를 할 때마다 FileInputStream.readLine(), 당신이 단지와 루프에서 호출했을 그렇다면, 파일의 다음 라인을 읽어 fileIn.readLine() != null변수를 할당하는 대신 호출하지 않고 (currentLine = fileIn.readLine()) != null, 다음에서 호출 루프 내부에서도 두 번째 줄만 얻을 수 있습니다.

당신이 이해하고 행운을 빕니다!


3

Java의 if 문 내에서도 할당을 수행 할 수 있습니다. 좋은 예는 무언가를 읽고 쓰는 것입니다.

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

코드:

// 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 :이 예에 감사드립니다. 나도 자바 나 자바 스크립트에서 정말 프로 아니에요 ...이 방법을 알고하는 것이 좋다 또한 : 자바에서 가능하다
마이클 마오

나는 이것의 요점을 보지 못한다. Java, PHP 및 기타 여러 언어로 할 수 있습니다. 문제는 자바 스크립트에 관한 것이 었습니다.
pmrotule 2016

반드시 그런 것은 아닙니다. 질문을주의 깊게 다시 읽어야합니다.
Nitrodist

3

Martin Fowlers의 책 리팩토링 을 참조하면 기존 코드의 디자인을 개선 할 수 있습니다 ! 그런 다음 좋은 연습이 될 몇 가지 경우가 있습니다. 함수 또는 메서드 호출을 사용하여 케이스를 주장하는 길고 복잡한 조건 :

"자극

프로그램에서 가장 일반적인 복잡성 영역 중 하나는 복잡한 조건부 논리에 있습니다. 조건을 테스트하고 다양한 조건에 따라 다양한 작업을 수행하는 코드를 작성하면 매우 긴 방법으로 빠르게 끝납니다. 방법의 길이는 그 자체로 읽기 어렵게 만드는 요소이지만 조건은 어려움을 증가시킵니다. 문제는 일반적으로 조건 검사와 작업의 코드가 어떤 일이 발생하는지 알려주지 만 그 이유를 쉽게 모호하게 할 수 있다는 사실에 있습니다.

큰 코드 블록과 마찬가지로, 코드 블록을 분해하고 해당 코드 블록의 의도를 따서 명명 된 메서드 호출로 코드 청크를 대체하여 의도를 더 명확하게 만들 수 있습니다. > 조건을 사용하면 조건부 부분과 각 대안에 대해이 작업을 수행하여 추가 혜택을받을 수 있습니다. 이렇게하면 상태를 강조하고> 당신이 무엇을 기준으로 삼고 있는지 명확하게 알 수 있습니다. 분기 이유도 강조합니다. "

그리고 네 그의 대답은 Java 구현에도 유효합니다. 예제에서는 변수에 조건부 함수를 할당하지 않습니다.


1

좋은 습관이 아닙니다. 곧 그것에 대해 혼란 스러울 것입니다. 일반적인 오류 인 "="및 "=="연산자를 잘못 사용하는 것과 비슷해 보입니다.

두 줄의 코드로 나누어야합니다. 코드를 더 명확하게 만드는 데 도움이 될뿐만 아니라 나중에 쉽게 리팩토링 할 수 있습니다. IF 조건을 변경한다고 상상해보십시오. 실수로 줄을 제거하고 변수에 더 이상 할당 된 값을 얻지 못할 수 있습니다.


@thethanghn : 정확히 내가 두려워하는 것. 나는 나이와 게으른 난 그냥 코드에 더 많은 입력하지 않으려는 경우 경우 적은 수의 키 입력 것이다 단지 충분할 :)
마이클 마오

1
아니요, 혼란스럽지 않고 항상 그렇게합니다. 그것에 대한 이점이 있습니다.
JDrake 2017-06-08

그래도 정말 다르죠? 'C'배경 (및 C를 기반으로하는 다른 언어)에서 온 경우 구성이 매우 친숙하고 대안이 매우 어색합니다. IMO, 그것은 한 번 배운 것입니다. 한 번 이상 넘어가는 것은 아닙니다.
Max Waterman

0

나는 이것을 좀 더 구식 C 스타일이라고 생각한다. JavaScript에서는 실제로 좋은 습관이 아니므로 피해야합니다.


8
C에서도 좋은 습관이라고 생각하지 않습니다.
Matthew Crumley

1
여러 언어에서 좋은 습관이라고 생각합니다.
JDrake

'좋은 연습이 아니다'라고 말하는 것만으로는 충분하지 않습니다. 그것은 정말로 교육에 관한 것입니다. 한 번 배웠고 그게 다입니다.
Max Waterman

0

다음과 같이 할 수 있습니다.

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

0

나는 golang에서 왔는데, 다음과 같은 것을 보는 것이 일반적입니다.

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

err것과 범위가 if블록 만. 따라서 여기에 내가 es6에서하고있는 작업이 있는데, 꽤보기 흉해 보이지만 내 엄격한 eslint 규칙이 윙윙 거리게하지 않고 똑같이 달성합니다.

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

추가 중괄호는 새로운 "어휘 범위"를 정의합니까? 즉 const,을 err사용할 수 있으며 외부 블록에서는 사용할 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.