-
항해 99 / 자바스크립트 언어의 특성 알아보기... 3항해99 2022. 7. 20. 23:49
호이스팅과 TDZ는 무엇일까 ?
- 스코프, 호이스팅, TDZ
스코프
언어를 그대로 번역하면 범위라는 뜻으로
자바스크립트에서는 변수에 접근할 수 있는 범위라고 할 수 있다.
자바스크립트의 스코프는 함수 레벨 스코프를 따른다.
같은 함수 레벨에 존재하면 값을 참조할 수 있으며
ES6에서 let 키워드가 도입되면서 블록 레벨 스코프를 사용할수 있게 됐다.
전역 스코프
-전역에 선언되어있어 어디서든 해당 변수 참조 가능
지역 스코프
-해당 지역에서만 접근할 수 있다.
var a = 1; // 전역 스코프 function print() { // 지역(함수) 스코프 var a = 111; console.log(a); //해당지역에서의 a = 함수 안에 있는 a여서 함수 안 a를 참조 } //하지만 함수 안에서의 변수a가 없었으면 전역 스코프인 a = 1을 참조하여서 //1을 갖게 될 것이다. print(); console.log(a); //함수 안 a와는 관계없이 전역 스코프를 참조
함수 레벨 스코프(var)
함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다.
즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.
var foo = 123; // 전역 변수 console.log(foo); // 123 { var foo = 456; // 전역 변수 } console.log(foo); // 456
블록 레벨 스코프 (let)
모든 코드 블록(함수, if 문, for 문, while 문, try/catch 문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며
코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.
let foo = 123; // 전역 변수 { let foo = 456; // 지역 변수 let bar = 456; // 지역 변수 } console.log(foo); // 123 console.log(bar); // ReferenceError: bar is not defined
호이스팅
'hoist'는 끌어 올리다의 뜻을 가지고 있다.
그 뜻 그대로 변수나 함수의 선언이 코드 최상단으로 끌어올려지는 듯한 현상을 말한다.
조금 풀어서 설명해보자면
스코프가 전역이라면 해당 스크립트의 최상단으로 끌어올려지고
스코프가 함수 내부에 국한된다면 해당 함수의 최상단으로 끌어올려진다.
하지만 변수의 선언과 할당 모두를 끌어올리는 개념이 아니라 선언부만 끌어올리는 것이다!
할당은 이루어지지 않으며 실제 호이스팅은 실제 메모리에 영향을 주지 않는다.
<호이스팅 예제1>
console.log(num); var num = 1;
호이스팅 예제 1이 있으면 변수가 선언되지도 않았는데 사용하고 있으면
다른 언어였으면 에러가 나야한다.
하지만 실행시에는 underfined를 출력한다.
즉 선언부를 최상단으로 끌어올렸기때문에 '선언만 되고 값은 할당되지 않은'
상태에서 호출을 하게 되어 ubdefined를 출력한 것
<호이스팅 예제2>
var num; console.log(num); //undefined var num = 1;
호이스팅 예제1의 코드는 내부적으로는 호이스팅 예제2와 같이 동작한다.
<호이스팅 예제3>
function test(){ console.log(num); // undefined var num = 1; console.log(num); // 1 } test();
스코프를 전역에서 함수 내부(지역)로 바꿔도 결과는 동일하다.
호이스팅 가능한 적용대상
호이스팅은 변수/함수에 공통적으로 적용되지만, 그렇다고 모든 변수/함수에 적용되지는 않는다.
변수를 살펴보면
var은 가능하고
let과 const는 불가능하다.
함수를 살펴보면
console.log(test()) function test(){ console.log("HI") }
이러한 일반적인 함수 식은 가능하지만
var func = function(){ console.log("HI") }
이렇게 변수안에 함수식을 넣은 것은 불가능하다.
함수 호이스팅이 발생하면 코드가 꼬일 수 있기때문에
함수를 선언할 때 함수 표현식을 이용하는게 좋습니다.
- 함수 선언문과 함수 표현식에서 호이스팅 방식의 차이
함수 선언식
function name () { return 'name' } name() //name
그냥 일반적인 선언 방식이다. 호이스팅에 영향을 받는다.
그래서 실무에서 선언식으로 개발한 컴포넌트는 함수 위치에 따른 에러가 없이 실행될 수 있었던 것이다.
앞서 얘기한 것 처럼 함수 선언식은 호이스팅에 영향을 받는다.
함수 표현식
let name = function () { return 'name' } name() //name
자바스크립트 언어의 유연성을 활용한 방식이다.
호이스팅에 영향을 받지 않는다.
그렇기 때문에 선언 순서를 잘 고려해야 에러가 나지 않는다.
- 여러분이 많이 작성해온 let, const, var, function 이 어떤 원리로 실행되는지 알 수 있어요.
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은 호이스팅이 불가능하다.
[1번 부가설명] 값 변경 가능 유무
const는 선언시에 반드시 값을 작성해주어야하고, 값을 변경하지 않을 때 사용하는 변수이다.
하지만 변수값 자체를 바꿀 수는 없지만 Object의 property값이나, 배열의 요소의 값은 바꿀 수 있다. 즉 참조하고 있는 주소를 바꿀 수 없는 것이지 그 주소가 가르키고 있는 데이터를 바꿀 수는 있다.
또한 자바스크립트에서 상수는 대문자 사용이 관례라고 하는데, const가 가지는 시멘틱 의미 자체가 값을 변경할 수 없는 변수 (=상수)이기 때문에 각자 코딩 스타일대로 하면 될것 같다)
[2번 부가 설명] 함수스코프 vs 블록스코프
블록스코프란 변수가 선언된 { 블록 } 이 해당 변수를 사용할 수 있는 영역(스코프)이라는 뜻이다.
let name = "yoy" if(name){ let name = "rooney"; console.log("블록 안에서",name); // 블록 안에서 rooney }; console.log("블록 밖에서",name); // 블록 밖에서 yoy
이렇게 if문을 감싸고 있는 { 블락 } 이 변수를 사용할 수 있는 영역이 되어 변수가 구분되어 진다.
위와 같이 let을 쓰면 if안과 밖으로 스코프가 달라지지만 (블록 안과 밖의 스코프가 달라져서 변수 이름이 같아도 값이 대체되지 않아 같은 스코프에는 같은 이름 사용 불가하다.), name을 var 변수로 선언 했을 경우에는 if 안과 밖이 같은 스코프가 되어서 "Uncaught SyntaxError: Identifier 'name' has already been declared" 오류가 뜬다.
- 실행 컨텍스트와 콜 스택
Execution context(실행 컨텍스트)
자바스크립트 코드가 실행되는 환경을 의미한다.
자바스크립트에서 대표적으로 두 가지 타입의 Execution context가 있다.실행할 코드에 제공할 환경 정보들을 모아놓은 객체들로
자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념이다.Global Execution context
자바스크립트 엔진이 처음 코드를 실행할 때 Global Execution Context가 생성된다. 생성 과정에서 전역 객체인 Window Object (Node는 Global) 를 생성하고 this가 Window 객체를 가리키도록 한다.Function Execution context
자바스크립트 엔진은 함수가 호출 될 때마다 호출 된 함수를 위한 Execution Context를 생성한다.
모든 함수는 호출되는 시점에 자신만의 Execution Context를 가진다.자바스크립트는 실행 컨텍스트가 활성화되는 시점에 다음과 같은 현상이 발생한다.
호이스팅이 발생한다(선언된 변수를 위로 끌어올린다)
외부 환경 정보를 구성한다
this 값을 설정한다.
call stack
코드가 실행되면서 생성되는 Execution Context를 저장하는 자료구조
엔진이 처음 script를 실행할 때, Global Execution Context를 생성하고 이를 Call Stack에 push한다.
그 후 엔진이 함수를 호출할 때 마다 함수를 위한 Execution Context를 생성하고 이를 Call Stack에 push 한다.
자바스크립트 엔진은 Call Stack의 Top에 위치한 함수를 실행하며 함수가 종료되면 stack에서 제거(pop)하고 제어를 다음 Top에 위치한 함수로 이동한다.
1줄 요약 : 프로그램이 함수 호출을 추적할때 사용한다.
- 스코프 체인, 변수 은닉화
자바스크립트는 우리나라의 행정구역을 광역시/도 ➡️ 시/군/자치구 ➡️ 읍/면/동으로 나누는 것처럼 코드의 영역을 스코프로 나누어 관리한다. 스코프는 단방향으로 연결되는 체인을 형성하며, 이 스코프 체인을 통해 상위 스코프로 이동하면서 식별자를 검색한다. 특히 스코프는
악명 높은클로저와 밀접한 관계를 갖기 때문에 꼭 알아두어야하는 개념이다.
스코프(Scope)
식별자의 유효 범위 ⇒ 모든 식별자는 자신이 선언된 위치에 의하여 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정됨.
한 스코프 내에서는 식별자가 유일해야 하지만, 다른 스코프에는 동명의 식별자를 사용할 수 있음.
⇒ 네임스페이스식별자 결정(identifier resolution) : 자바스크립트 엔진은 스코프를 통해서 어떤 변수를 참조할 것인지 결정함.
스코프의 종류
전역 스코프
전역은 코드의 가장 바깥 영역으로, 여기서 선언된 변수는 전역 변수가 됨.
전역 변수는 어디서든 참조 가능
지역 스코프
지역은 함수 코드의 내부 영역으로, 여기서 선언된 변수는 지역 변수가 됨.
지역 변수는 자신의 지역 스코프 및 하위 지역 스코프에서 참조 가능
⭐️ 함수 레벨 스코프 VS 블록 레벨 스코프
지역 스코프는 함수에 의해서 생성되는가, 코드 블록에 의해서 생성되는가에 따라 레벨이 나뉨.
블록 레벨 스코프 : if, for, while, try/catch 등 코드 블록이 지역 스코프 생성 ⇒ let, const 키워드로 선언된 변수는 모든 코드 블록을 지역 스코프로 인정함.
함수 레벨 스코프 : 함수가 지역 스코프 생성 ⇒ var 키워드로 선언된 변수는 오직 '함수'만을 지역 스코프로 인정함.
렉시컬 스코프 or 정적 스코프
자바스크립트에서는 함수 정의가 평가되는 시점에 상위 스코프가 정적으로 결정됨.
즉, 함수를 어디서 호출했는지가 아니라 '어디에 정의했는지'에 따라서 상위 스코프가 결정됨.
함수의 상위 스코프는 함수 정의가 실행될 때 정적으로 결정되며, 함수 정의가 실행되어 생성된 함수 객체는 상위 스코프를 기억함. ⇒ 클로저와 깊은 연관
스코프 체인(Scope Chain)
스코프는 함수의 중첩에 의해 계층적 구조를 가짐. ⇒ 외부 함수(outer function) / 중첩 함수(nested function)
변수를 참조할 때, 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프로 이동하면서 선언된 변수를 검색함.
여러 스코프에서 동일한 식별자를 선언한 경우, 무조건 스코프 체인 상에서 가장 먼저 검색된 식별자에만 접근 가능 ⇒ 변수 은닉화(variable shadowing)
스코프 체인은 outerEnvironmentReference와 밀접한 관계를 가짐.
💡 스코프 체인은 실행 컨텍스트의 렉시컬 환경을 '단방향'으로 연결한 링크드 리스트
'항해99' 카테고리의 다른 글
항해 8기를 마무리하며. (0) 2022.10.14 항해 99 / 자바스크립트 언어의 특성 알아보기... 2 (0) 2022.07.21 항해 99 리액트 과제 실습 (0) 2022.07.21 항해 99 / 자바스크립트 언어의 특성 알아보기 .... 1 (0) 2022.07.20 [Chapter 1] 6조 S.A(Starting Assignment) (0) 2022.07.11