개발하자

Javascript Scope, hoisting, Closure (스코프, 클로저, 호이스팅) 본문

Javascript

Javascript Scope, hoisting, Closure (스코프, 클로저, 호이스팅)

hyesun 2022. 7. 8. 23:22

Execution Context를 먼저 학습하는 것을 추천한다!!

 

https://hyesunie.tistory.com/14

 

Scope와 Closure 이해하기 위한 선행 학습 (Execution Context, Lexical Environment )

JS에서 Scope와 Closure를 이해하기 위해서는 Lexical Evironmet에 대한 이해가 선행되어야 한다. 그래서 아래 포스팅을 해석하며 Execution Context를 이해해보려고 했다!! https://blog.bitsrc.io/understanding..

hyesunie.tistory.com


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

 

스코프 - 용어 사전 | MDN

현재 실행되는 컨텍스트를 말한다. 여기서 컨텍스트는  값과 표현식이 "표현"되거나 참조 될 수 있음을 의미한다. 만약 변수 또는 다른 표현식이 "해당 스코프"내에 있지 않다면 사용할 수 없

developer.mozilla.org

 

https://poiemaweb.com/es6-block-scope

 

let, const | PoiemaWeb

ES5까지 변수를 선언할 수 있는 유일한 방법은 var 키워드를 사용하는 것이었다. var 키워드로 선언된 변수는 아래와 같은 특징이 있다. 이는 다른 언어와는 다른 특징으로 주의를 기울이지 않으면

poiemaweb.com

https://poiemaweb.com/js-scope

 

Scope | PoiemaWeb

스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙으로 자바스크립트는 이 규칙대로 식별자를 찾는다.

poiemaweb.com

https://poiemaweb.com/js-closure

 

Closure | PoiemaWeb

클로저(closure)는 자바스크립트에서 중요한 개념 중 하나로 자바스크립트에 관심을 가지고 있다면 한번쯤은 들어보았을 내용이다. execution context에 대한 사전 지식이 있으면 이해하기 어렵지 않

poiemaweb.com

https://poiemaweb.com/js-execution-context

 

Execution Context | PoiemaWeb

Execution Context(실행 컨텍스트)는 scope, hoisting, this, function, closure 등의 동작원리를 담고 있는 자바스크립트의 핵심원리이다. 실행 컨텍스트를 바로 이해하지 못하면 코드 독해가 어려워지며 디버

poiemaweb.com

 

Comments