Development/Javascript

[펌] +function() 의 원리

Dev. Jkun 2016. 3. 9. 15:18
반응형

출처 : http://blog.coderifleman.com

오픈소스나 레거시 읽다 보면 종종 +function(){}() 같은 코드를 마주하게됩니다. 이 코드가 혼란스러운 분들을 위해 +function(){}()이 무엇인지 그리고 어떻게 동작하는 것인지 간략히 정리해보겠습니다.

엔진이 함수를 실행하는 방법

함수를 실행하기 위해서는 이름(식별자)이 필요합니다. 이름이 있어야 스코프에서 값을 참조할 수 있기 때문입니다.

예를 들어 function foo(){}를 정의하면 foo(); 구문을 이용해 함수를 실행할 수 있습니다.

함수를 실행하는 흐름<그림 1 함수를 실행하는 흐름>

엔진이 함수 선언문을 만나면 식별자를 관리하는 특별한 집합(EnviromentRecord)에 함수의 이름을 식별자로 넣고 함수 객체를 생성하여 참조합니다. 그리고 함수 실행 구문 중 foo를 만나면 값을 스코프를 통해 가져옵니다. 그 다음 구문이 () 이므로 실행 가능하다면 실행합니다.

만약 스코프에서 식별자를 찾지 못했다면 참조 에러(ReferenceError)를 출력하고, 식별자는 찾았지만 실행할 수 없는 타입이라면 타입 에러(TypeError)를 출력합니다.

not(); // ReferenceError: not is not defined

var foo = 'some';
foo(); // TypeError: foo is not a function

익명함수를 선언하는 방법

function(){} 구문은 이름 없는 “익명함수” 이므로 엔진이 스코프를 통해 값을 가져올 수 있는 방법이 없습니다. 따라서 이 문법을 실행하면 함수의 이름이 필요하다고 문법 오류를 출력합니다.(이 오류 메시지는 브라우저 마다 다릅니다.)

function(){} // SyntaxError: function statement requires a name

이름 없는 함수를 선언할 수 있는 유일한 경우는 함수를 값으로 사용(전달, 대입, 반환, 연산)할 때 입니다.

var func = function(){console.log('ok');}() // ok
some(function(){console.log('ok');})() // ok
return function(){console.log('ok');}() // ok
(function(){console.log('ok');})(); // ok
+function(){console.log('ok');}() // ok
!function(){console.log('ok');}() // ok

자바스크립트 엔진은 단항연산자(-, +, ~, !)를 만나게 되면 function(){}을 값으로 평가합니다. 쉽게 말해 연산을 위해 함수 객체를 생성하게 되고 최종적으로 () 구문을 이용해 실행할 수 있는 것입니다.

+function(){}은 함수 객체를 + 하려고 했으므로 결과로 NaN이 출력됩니다.

+function(){} // NaN

결론

결국 +function(){}()은 익명 함수를 즉시 실행시키기 위해 엔진의 원리를 이용해 만든 편법입니다.

이 원리를 이용한 즉시 실행 함수 중 가장 대중적인 방식은 (function(){})()입니다. ()는 구문 평가를 하는데 평가된 결과가 함수이니 함수 객체를 만들고 이어서 () 구문으로 즉시 실행하는 방식입니다.

(function(){}) // function() 객체
(function(){})() // 즉시 실행

남이 읽을때 혼란스럽지 않아야 좋은 코드라고 할 수 있겠죠. 따라서 비대중적인 +function(){}() 보다 (function(){})() 사용하여 코드를 읽는 개발자가 즉시 실행하는 함수 임을 쉽게 알 수 있도록 하는편이 좋겠습니다.

자바스크립트는 구문이 유연하기 때문에 자신만의 규칙이나 법칙을 만들기 쉽습니다. 하지만 이는 협업시 독이 될 수 있음을 명심해야합니다.

반응형