일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 취준
- Groo
- 개발일기
- SSR
- Binding
- 상태관리
- 우아한테크러닝
- Hooks
- react
- npm
- vanilla.js
- Redux
- 리액트
- useState
- Modules
- CSR
- 취업준비
- mobx
- scope
- 코딩테스트
- JavaScript
- 환경오염
- 함수 바인딩
- excutionContext
- state
- 카카오페이
- react.js
- 리액트를 다루는 기술
- lexicalEnvironment
- closure
- Today
- Total
개발하자
Javascript Scope, hoisting, Closure (스코프, 클로저, 호이스팅) 본문
Execution Context를 먼저 학습하는 것을 추천한다!!
https://hyesunie.tistory.com/14
Scope
공식 문서에서 정의한 내용을 보면 아래와 같이 간단하게 정의 돼있다.
현재 실행되는 컨텍스트를 말한다.
간단하지만 이해하기 위해서는 Execution Context 에 대한 개념이 있어야한다.
Execution Context는 JS 코드가 실행 평가되는 환경의 추상적 개념이다.
변수가 참조할 수 있는 범위라고도 할 수 있다.
Scope chain
실행 컨텍스트의 프로퍼티(Variable Object, Scope Chain, thisValue) 중 하나이다.
일종의 리스트로서 전역 객체와 중첩된 함수의 스코프의 레퍼런스를 차례로 저장하고 있다. 다시 말해, 스코프 체인은 해당 전역 또는 함수가 참조할 수 있는 변수, 함수 선언 등의 정보를 담고 있는 리스트를 가리킨다.
엔진은 스코프 체인을 통해서 렉시컬 스코프를 파악한다.
함수가 중첩될 때마다 부모함수의 Scope가 자식함수의 Scope chain에 포함 된다.
함수 실행 중에 변수를 만나면 현재스코프에서 검색하고,
실패하면 스코프 체인에 담겨진 순서대로 검색한다.
Closure
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.
함수는 생성 당시의 lexical evironment를 기억하여 가지고 있다.
스코프 체인을 이해했다면 Closure는 쉽게 이해할 수 있다.
상위의 스코프를 검색하여 자원을 참조하는 것 이기 때문이다.
아래의 예시를 보면 이해가 쉽다.
function state() {
let word = "hello"
return function (newState) {
word = newState
console.log(word)
}
}
const setState = state()
setState("hi") // "hi"
return 된 내부함수는 자신이 선언된 함수의 자원을 참조할 수 있기 때문에 위의 코드가 가능하다.
javascript 에서의 scope
보통 다른 언어들은 block-level scope를 따른다.
JS는 기본적으로 function-level scope를 따른다.
이 말은 코드블럭 내에서 선언된 변수라도 함수에서 자유롭게 사용할 수 있다는 의미이다.
아래의 예시를 보면 빠르게 이해할 수 있다.
function greeting() {
const isKnown = true;
if(isKnown) {
var word = "hello"
}
console.log(word)
}
위의 코드를 실행했을 때의 결과이다.
요약하자면 function-level scope 는 내가 선언된 함수 내의 자원을 모두 나의 유효 범위로 보는 것이다.
function-level scope 는 복잡한 개발에서 예상치 못한 이슈가 발생 할 수 있는 요소이다.
그래서 ES6 이상부터는 let 과 const 지원하기 시작했다.
let , const VS var
let, const 는 block-level scope 를 따른다.
그래서 변수의 중복이나 할당에 대한 문제가 발생하지 않는다.
var 와 let, const 는 중복 선언에서 차이가 있다.
var 변수는 중복 선언이 가능하고, 기존의 변수의 값을 변경한다.
let과 const는 중복 선언이 불가능하다.
var word1 = "var"
var word1 = "not var"
// not var 로 변경
let word2 = "let"
let word2 = "not let"
//Uncaught SyntaxError: Identifier 'word2' has already been declared
const word3 = "const"
const word3 = "not const"
//Uncaught SyntaxError: Identifier 'word3' has already been declared
var 와 let, const 는 excution context 생성과정에서도 차이가 있다.
var는 변수 생성과 동시에 undefined 가 할당된다.
let 과 const는 변수명만 선언 돼있을 경우 선언 변수명을 등록은 하지만 초기값을 할당하지는 않는다.
실제 변수 선언문에 도달 했을 때 그 값으로 초기화 한다.
아래의 코드를 보면 이해가 쉽다.
console.log(word) //undefined
var word
console.log(word2) //Uncaught ReferenceError: word2 is not defined
let word2
console.log(word3) //Uncaught SyntaxError: Missing initializer in const declaration
const word3
hoisting
바로 위의 코드를 보면 자연스럽게 hoisting 이야기가 나온다
아래의 정의가 가장 정확한 것 같아 가져와 봤다.
var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동작하는 특성을 말한다.
사실 javascript는 모든 선언을 hoisting 한다.
하지만 let, const는 실제 값이 할당 되는 코드가 나올때까지 초기값(메모리 공간)을 할당하지 않기 때문에
hoisting 되지 않는 것 처럼 보인다.
let hoisting = "yes"
{
console.log(hoisting)
let hoisting = "no"
}
//Uncaught ReferenceError: Cannot access 'hoisting' before initialization
hoisting이 안되고 있다면 전역의 변수 값이 출력되어야 한다.
let도 hoisting이 되고 있기 때문에 에러가 발생하는 것이다.
참고한 자료
https://developer.mozilla.org/ko/docs/Glossary/Scope
https://poiemaweb.com/es6-block-scope
https://poiemaweb.com/js-scope
https://poiemaweb.com/js-closure
https://poiemaweb.com/js-execution-context
'Javascript' 카테고리의 다른 글
Javascript Prototype 최종 정리!!(프로토타입 체인, 다이어그램) (0) | 2021.12.15 |
---|---|
Scope와 Closure 이해하기 위한 선행 학습 (Execution Context, Lexical Environment ) (0) | 2021.07.09 |