let,const,var,function의 실행 원리

junghoon_you·2022년 7월 19일
1

React과제

목록 보기
2/10

var,let,const의 차이

let 변수와 const는 ES6 이후 스펙에서 새롭게 등장한 변수이다. 그래서 브라우저 배포용 코드같은 경우는 아직도 var변수만 사용되는 경우도 있다고 한다.

var,let,const 를 구분하는 가장 중요한 점을 요약하면
1.값 변경 가능 유무
2.스코프 범위
3.호이스팅 가능 유무

우선 순위는 const -> let -> var 이라고 하니 최대한 우선순위에 맞춰서 써야합니다.


1.값 변경 가능 유무

var와 let을 값이 선언된 이후에도 값을 변경할 수 있지만, const는 생성할 때 선언된 초기값을 변경할 수 없습니다.

2.함수스코프 vs 블록스코프

var은 함수스코프를 가지지만,
let과 const 변수는 블록 스코프를 가지게 됩니다.

3.호이스팅 가능 유무

var는 호이스팅이 가능하지만,
let과 const는 호이스팅이 불가능합니다.

2.번의 부가설명을 드리자면 블록스코프란 변수가 선언된 {블록}이 해당 변수를 사용할 수 있는 영역(스코프)이라는 뜻입니다.

이렇게 if문을 감싸고 있는 {블락} 이 변수를 사용할 수 있는 영역이 되어 변수가 구분되어 진다.

위와 같이 let을 쓰면 if안과 밖으로 스코프가 달라지지만 (블록 안과 밖의 스코프가 달라져서 변수 이름이 같아도 값이 대체되지 않아 같은 스코프에는 같은 이름 사용 불가하다), name을 var변수로 선언 했을 경우에는 if 안과 밖이 같은 스코프가 되어서 "Uncaught SyntaxError: Identifier 'name' has already been declared"오류가 뜨게됨

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(){})() 사용하여 코드를 읽는 개발자가 즉시 실행하는 함수 임을 쉽게 알 수 있도록 하는편이 좋겠습니다.

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

https://coderifleman.tumblr.com/post/100741227784/function%EC%9D%98-%EC%9B%90%EB%A6%AC 자세한 내용은 이주소를 참조하시면 감사하겠습니다.

profile
안녕하세요 코린이 입니다.

0개의 댓글