Programming/Javascript

[Javascript] You Don't Know JS (문법)

알로그 2020. 4. 5. 11:28
반응형

Chapter 5. 문법

5.1 문과 표현식

3 * 6은 표현식이며, 각 줄은 표현식(Expression)이 포함된 문(Statement)이다.

var a = 3 * 6;
var b = a;
b;

 

5.1 문의 완료 값

모든 문은 완료 값을 가진다.
var a = 42를 콘솔창에 입력했을 때, 42 대신 undefined가 출력된다. (var 자체의 완료 값)

{ } 블록은 내부의 가장 마지막 문/표현식의 완료 값을 자신의 완료 값으로 반환하기 때문에 아래는 42가 출력된다.

var b;

if (true) {
    b = 4 + 38;
}

그렇지만 아래와 같은 코드는 동작하지 않는다.
문의 완료 값을 다른 변수에 할당한다는 건 쉬운? 구문/문법으론 불가능하다.

var a, b;

a = if (true) {
    b = 4 + 38;
};

ES7 명세에서 제안된 do 표현식을 사용하면 위의 문제를 해결 할 수 있다.

var a, b;

a = do {
    if (true) {
        b = 4 + 38;
    }
};

a;    // 42

do { } 표현식은 블록 실행 후 블록 내 마지막 문의 완료 값을 do 표현식 전체의 완료 값으로 반환하며 이 값이 변수 a에 할당된다.

eval은 사용하지 말자.

 

5.1.2 표현식의 부수 효과

var a = 42;

a++;    // 42
a;        // 43

++a;    // 44
a;        // 44

delete 연산자의 결과값은 유효한 연산일 경우 true, 그 외 false를 반환한다.

var obj = {
    a: 42
};

obj.a;            // 42
delete obj.a;    // true
obj.a;            // undefined

= 할당 연산자 역시 부수 효과를 유발하는 연산자라고 할 수 있다.
연쇄 할당문에서 유용하게 사용할 수 있다.

function vowels(str) {
    var matches;

    if (str) {
        // pull out all the vowels
        matches = str.match( /[aeiou]/g );

        if (matches) {
            return matches;
        }
    }
}

vowels( "Hello World" ); // ["e","o","o"]
function vowels(str) {
    var matches;

    // pull out all the vowels
    if (str && (matches = str.match( /[aeiou]/g ))) {
        return matches;
    }
}

vowels( "Hello World" ); // ["e","o","o"]

중괄호

중괄호가 나올 법한 곳은 크게 두 곳이다.

객체 리터럴

// assume there's a `bar()` function defined

var a = {
    foo: bar()
};

레이블
문법적으로 100% 옳은 코드이며, 특히 let 블록 스코프 선언과 함께 사용하면 유용하다.

// assume there's a `bar()` function defined

{
    foo: bar()
}

레이블 점프(labeled jump) 역할을 하는 예제이며, foo 라는 레이블이 붙은 루프의 다음 순회를 계속하라는 뜻이다.

// `foo` labeled-loop
foo: for (var i=0; i<4; i++) {
    for (var j=0; j<4; j++) {
        // whenever the loops meet, continue outer loop
        if (j == i) {
            // jump to the next iteration of
            // the `foo` labeled-loop
            continue foo;
        }

        // skip odd multiples
        if ((j * i) % 2 == 1) {
            // normal (non-labeled) `continue` of inner loop
            continue;
        }

        console.log( i, j );
    }
}
// 1 0
// 2 0
// 2 1
// 3 0
// 3 2

레이블은 비 루프 블록에도 적용할 수 있는데, 이 경우에는 break만 참조할 수 있다.

function foo() {
    // `bar` labeled-block
    bar: {
        console.log( "Hello" );
        break bar;
        console.log( "never runs" );
    }
    console.log( "World" );
}

foo();
// Hello
// World

레이블 루프/블록은 사용 빈도가 극히 드물고 사용하지 않는 것을 권장한다.
만약 레이블 점프 기능을 사용할 의도라면 상세한 주석으로 잘 문서화 할 것!

 

객체분해

ES6부터는 분해 할당(Destructuring Assignments), 객체 분해시 { }를 사용한다.

function getData() {
    // ..
    return {
        a: 42,
        b: "foo"
    };
}

var { a, b } = getData();

console.log( a, b ); // 42 "foo"

자바스크립트에서 else if 절은 존재하지 않으며, 숨겨진 특성이다.

if (a) {
    // ..
}
else if (b) {
    // ..
}
else {
    // ..
}

위의 소스 코드는 실제로 아래와 같이 파싱된다.

if (a) {
    // ..
}
else {
    if (b) {
        // ..
    }
    else {
        // ..
    }
}

즉 else if는 표준 스타일 가이드의 위반 사례가 되지만 누구나 쓰는 관용 코드이고, 들여쓰기를 하는 효과가 있어 나름의 매력은 있다.

또한 여러 스타일 가이드 문서에는 단일 문서도 { } 감싸라고 조언한다.

반응형