Javascript

[Javascript] 함수앞에 느낌표(특수기호)가 있는 경우 : 자기호출 익명함수

728x90
반응형

const 팽수 = 함수

!(function () {
    //..
})

위와 같이 함수 앞에 느낌표가 있는 건 어떤 의미인지 알아보자.

간단히 말하자면, 반대되는 값을 리턴해주고 동시에 함수를 즉시 실행한다.

 

더 자세히 이해하기 위해선 익명 함수, 자기 호출 함수에 대해 이해해야 한다.

본문과는 관련 없지만, 기본 상식으로 모든 함수는 일단 호출이 되면 어떤 것이든 반환한다. 그게 undefined라도 말이다.

 


 

익명 함수

이름이 없는 함수.

아래와 같은 형식으로 사용될 수는 없지만, 다른 함수의 매개변수로 쓰일 경우에는 정상 작동한다.

사용할 수 없는 이유는 함수 선언문의 경우 함수 이름을 생략할 수 없기 때문에 에러가 발생한다.

function () {
    //...
}

 

 

 

자기 호출 익명 함수 (IIFE)

스스로 실행하는 이름 없는 함수.

선언과 동시에 즉시 실행한다 (IIFE, Immediately Invoked Function Expressions)

즉시 실행 함수는 단 한 번만 호출되며 다시 호출할 수 없다.

(function () {
    //..
})();

 

다른 표현방식

마지막 괄호를 처음 괄호 안에 넣은 방식으로도 호출이 가능하다.

(function () {
    //..
}());

 

 

즉시 실행 함수를 그룹 연산자(괄호)로 감싸는 이유

function () {
    //..
}(); // 함수명이 없기에 오류 발생
function foo() {
    //..
}(); //오류발생

자바스크립트 ASI로 인해 함수 선언문이 끝나는 위치에 세미콜론이 추가됨. function foo() { };(); -> 이렇게 된 것
그룹 연산자(괄호)로 즉시 실행 함수를 감싸는 이유는 함수를 평가해서 함수 객체를 생성하기 위해서다.
그룹 연산자 안의 함수는 자바스크립트 엔진이 함수 리터럴로 해석하고 평가하여 함수 객체로 생성한다.

 

 

 

느낌표와 자기 호출 익명 함수

첫째, 자기 호출을 가능하게 해 준다.

느낌표를 앞에 붙이면 그룹 연산(괄호)으로 묶지 않아도 작동된다. 뒤에 ()를 이용해 함수 내에서 사용될 매개변수도 받을 수 있다.

!function () {
    console.log("느낌표를 사용한 자기호출 익명함수");
}();

 

이때, 맨 마지막 ()가 없으면 작동하지 않는다.

!function () {
    console.log("느낌표를 사용한 자기호출 익명함수");
}; //작동x

 

다른 표현방식

함수명(); 형식으로 괄호를 마지막에 넣는다.

!(function () {
    //..
})();

 

다른 표현방식

마지막 괄호를 함수 선언부를 감싸는 괄호에 넣은 방식으로도 호출이 가능하다.

!(function () {
    //..
}());

 

 

 

둘째. 반대의 값을 리턴해준다.

느낌표를 사용하면 return값을 반대로 바꿀 수 있다. ture -> false, 1 -> 0

(function () {
    const ans = true;
    //const ans = 1;

    //느낌표를 사용해 return값을 반대로 바꿈
    const a = !function () {
        return ans;
    }();
    console.log("느낌표를 사용해 return값을 반대로 바꿈 : " + a);

    const a1 = !!(function () {
        return ans;
    })();
    console.log("느낌표 두개를 사용해 return값을 반대로 바꿈 : " + a1);

    // 틸드 한개
    const num = 5; 
    const a3 = ~(function () {
        return num;
    })();
    console.log("~ : " + a3);

    // 틸드 두개
    const num1 = '2234.5678'; 
    const a2 = ~~(function () {
        return num1;
    })();
    console.log("~~ : " + a2);

    //다른 표현방식(괄호로 묶음), 위의 값과 같은지 확인
    const b = !(function () {
        return ans;
    })();
    console.log("다른 표현방식, 위의 값과 같은지 확인 : " + b);


    //느낌표 함수에서 리턴값이 없는 경우, undefined가 ! 되어 ture가 나온다.
    const c = !(function () {
        //return ans;
    })();
    console.log("느낌표 함수에서 리턴값이 없는 경우 : " + c);

    //느낌표를 사용하지 않은 경우
    const d = (function () {
        return ans;
    })();
    console.log("느낌표를 사용하지 않은 경우 : " + d);
})();

 

 

 

+ 특수기호를 이용한 즉시 실행 함수

1. 객체 앞에 +,- 가 붙을 경우

연산식으로 해석하기 때문에 즉시 실행한다. 단, *,/,%는 오류 발생

+function () {
    console.log("+를 사용한 자기호출 익명함수");
}();

-function () {
    console.log("-를 사용한 자기호출 익명함수");
}();

 

2. 느낌표 두 번 (강제 형 변환 연산자)

!!function () {
    console.log("!!를 사용한 자기호출 익명함수");
}();

 

3. 틸드 (~) 물결

return값의 -(n+1)된 값을 리턴

indexOf와 함께 사용하면 글자 존재 여부를 쉽게 작성할 수 있다.

~function () {
    console.log("~를 사용한 자기호출 익명함수");
    if(~'oh my god'.indexOf('g')){
        console.log("zz");
    }
}();

 

4. 틸드 2개 (~~) 물결 두 개, 이중 물결

Math.floor()와 동등하게 쓰이는 연산자

~~function () {
    console.log("~~를 사용한 자기호출 익명함수");
}();

 

5. ;를 앞에 붙이는 경우

이 경우는 위에 연산자처럼 사용되는 용도와는 다르다.

(function () {
    //..
})() //오류 발생
//단독으로 사용하는 경우에는 문제 없지만, 함수뒤에 함수가 있는 경우에는 마지막에 세미콜론이 없으면 오류가 난다.

(function () {
    //..
}());

자바스크립트에서 표현식 등의 면접 끝에 세미콜론을 붙이는 것이 맞다. 하지만 가끔 빼먹어도 오류 없이 작동한다.
자바스크립트 ASI(Automatic semicolon insertion)이라고 하는 세미콜론을 생략하더라도 자동으로 넣어주는 기능이 있기 때문에 오류를 내지 않은 것이다.
그러나 일부 경우에 대해서는 ASI가 적용되지 않기 때문에 개발자는 세미콜론 ;을 실수로 누락하지 않도록 조심해야 한다. 

위의 소스 또한 앞에 있는 함수에서 ;이 생략되었기 때문에 발생한 오류다. 그러나 뒤에 있는 함수의 앞에 ;이 추가될 경우 오류가 나지 않는다.

(function () {
    //..
})() //정상작동

;(function () {
    //..
}());

즉 앞에 세미콜론을 붙이는 이유는 이전 소스에서 세미콜론이 누락되어 발생할 수 있는 오류를 없애기 위한 것이다.

 

 

 

4. 괄호 안의 변수 사용

마지막 괄호 안에 있는 값을 함수에 이용될 매개변수로 사용할 수 있다.

(function (msg) {
    console.log(msg);
})("hello");

 

다른 표현방식

마지막 괄호를 처음 괄호 안에 넣은 방식으로도 호출이 가능하다.

(function (msg) {
    console.log(msg);
}("hello!"));

 

 

 

 

 

 

[참고 글]

728x90
반응형