한빛미디어 - You Don't Know JS yet
그런데 .... 혼공JS도 다 끝나가는데 이제 초급이 아닌 중상급이 되야지! 포부도 당당하게 도전하겠다 마음먹고 구매했습니다....
클로저는 뭐고 , 호이스팅은 뭔가... 또 스코프는 뭐시여.... 전 그런 어려운 용어 배운적 없습니다 ㅠㅠ....
초급자에서 중급자로 승급하는것이 이렇게 어렵습니다.... ㅠㅠ
그래서 새로운 책을 공부하기전에 모르는 용어들을 찾아보고 공부하기 위해서 이 글을 쓰고 있습니다.
1. 스코프
스코프 정의
스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙이다. 자바스크립트는 이 규칙대로 식별자를 찾는다. -https://poiemaweb.com/js-scope
var x = 'global';
function foo () {
var x = 'function scope';
console.log(x);
}
foo(); // ?
console.log(x); // ?
foo() 는 함수 내부의 function scope가 출력되고
console.log(x) 는 외부 글로벌 변수 x의 global이 출력된다.
즉 전역에 선언된 변수 x는 어디에든 참조할 수 있다.
하지만 함수 foo 내에서 선언된 변수 x는 함수 foo 내부에서만 참조할 수 있고 함수 외부에서는 참조할 수 없다.
이러한 규칙을 스코프라고 한다.
스코프의 구분
전역 스코프 (Global scope) -전역 변수
코드 어디에서든지 참조할 수 있다.
지역 스코프 (Local scope or Function-level scope) - 지역변수 (함수내부 변수)
함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.
자바스크립트 스코프 특징
함수 레벨 스코프
함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다(참조할 수 없다)는 것이다.
블록 레벨 스코프
블록 레벨 스코프란 코드 블록({…})내에서 유효한(참조가능한) 스코프를 의미한다.
var x = 0;
{
var x = 1;
console.log(x); // 1
}
console.log(x); // 1 var의 경우 블록 밖에서도 사용됨
let y = 0;
{
let y = 1;
console.log(y); // 1
}
console.log(y); // 0 let의 경우 블록레벨스코프가 가능함
전역 스코프
전역에 변수를 선언하면 이 변수는 어디서든지 참조할 수 있는 전역 스코프를 갖는 전역 변수가 된다.
var global = 'global';
function foo() {
var local = 'local';
console.log(global);
console.log(local);
}
foo();
console.log(global);
console.log(local); // Uncaught ReferenceError: local is not defined
//전역변수 local 이 없기때문에 함수 내부에선 사용가능해도 외부에선 불가능함
그러나 전역 변수의 사용은 변수 이름이 중복될 수 있고, 의도치 않은 재할당에 의한 상태 변화로 코드를 예측하기 어렵게 만드므로 사용을 억제하여야 한다. ===> 그래서 대부분 var보단 let을 사용하여 재할당을 막음
비 블록 레벨 스코프
if (true) {
var x = 5;
}
console.log(x);
함수 내부에서 선언된것이 아니므로 var는 전역스코프를 가진다.
함수 레벨 스코프
var a = 10; // 전역변수
(function () {
var b = 20; // 지역변수
})();
console.log(a); // 10
console.log(b); // "b" is not defined
함수 내부에서 선언한 b는 외부에서 사용불가 - 함수레벨 스코프!
중복선언된 함수 스코프
var x = 'global';
function foo() {
var x = 'local';
console.log(x);
}
foo(); // local
console.log(x); // global
변수가 중복으로 선언되었으며 전역변수는 어디서나 참조가능!
하지만 함수 내부에서는 지역변수를 우선으로 한다 foo() // Local
함수 내부함수의 내부 함수
var x = 'global';
function foo() {
var x = 'local';
console.log(x);
function bar() { // 내부함수
console.log(x); // ?
}
bar();
}
foo();
console.log(x); // ?
내부의 내부 bar() local --지역 변수 우선!
함수 내부 foo() local
console.log(X) global
함수 내부 함수의 경우에도 지역변수를 우선으로 확인하고 그 후 그 주변 전역변수로 점점 크게 바라보면 된다!
함수내부 변수의 상위 스코프 참조
var x = 10;
function foo() {
x = 100;
console.log(x);
}
foo(); //100
console.log(x); //100
var의 특이한 점인데 함수 내부에서도 참조가 가능하므로 전역변수도 값이 변경된다.
var x = 10;
function foo(){
var x = 100;
console.log(x); 100
function bar(){ // 내부함수
x = 1000;
console.log(x); // 1000
}
bar();
}
foo();
console.log(x); // 10
중첩 스코프는 가장 인접한 값을 우선하여 참조함
렉시컬 스코프
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // ?
bar(); // ?
모두 값이 1이 나온다 이유는 렉시컬 스코프는 함수를 어디서 호출하는지가 아니라 어디에 선언하였는지에 따라 결정된다.
즉 bar()의 전역에 선언 되었고 이에 따라 전역 변수인 x=1을 참조하게 되여
foo() , bar() 모두 1이 된것이다.
결론
ECMAScript 6 이전 버전 var을 사용할때 재할당 문제와 함수 레벨스코프 특성, 전역변수 등등의문제들이 있었으며 그래서 위와같이 다양한 스코프 종류들이 나왔다.
그리고 이와 같은 문제를 보완하기위해 ECMAScript 6 이후부턴 let, const와 같은 블록레벨스코프가 가능한 키워드들을 추가하여 생산성을 늘려주었다.
어렵게 생각하지 말고 변수가 어디에 있는지 그리고 어디서 선언됬는지 생각해보면 쉽게 이해될거 같다.
2.호이스팅
https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Grammar_and_types
JavaScript 호이스팅은 인터프리터가 코드를 실행하기 전에 함수, 변수, 클래스 또는 임포트(import)의 선언문을 해당 범위의 맨 위로 끌어올리는 것처럼 보이는 현상을 뜻합니다.
즉 변수와 함수의 선언부가 각자의 현재 스코프 영역 최상단으로 옮겨지는 것을 뜻합니다.
예시 : 함수 선언식 호이스팅
helloWorld(); // Hello World!
function helloWorld(){
console.log('Hello World!');
}
함수 helloWorld가 밑에 선언되었지만 위에서도 호출하여 사용할 수 있는 것을 호이스팅이라 한다.
예시 : 함수 표현식 호이스팅
baz(); // TypeError: baz is not a function
var baz = function () {
console.log("bar2");
};
함수 표현식의 경우 호이스팅이 되지 않습니다. - > 자바스크립트는 오직 선언만을 호이스팅 한다고 합니다.
var baz의 경우 호이스팅은 되었으나 초기화이후 할당이 되지않아 fuction으로 나오지 않는것 같습니다.
예시 : 변수 호이스팅
console.log(x === undefined); // true
var x = 3;
// undefined 값을 반환함.
var myvar = "my value";
(function () {
console.log(myvar); // undefined
var myvar = "local value";
})();
변수 호이스팅의 경우 undefined가 나오는 이유는 변수 자체는 호이스팅이 되었지만 초기화 이후 할당이 되지 않아 undefined가 나오는 것이다.
결론
간단하게 함수나 변수를 선언하면 코드의 제일 상단으로 올라간다라고 생각하는게 맞는거 같다.
다만 위의 변수 호이스팅이나 함수 선언식의 경우에도 나왔듯이 키워드 종류에 따라 동작하는 방식이 달라져 호이스팅이 제대로 이루어지지 않는 경우도 있으니 조심해야겠다.
'프로그래밍 공부 > Javascript' 카테고리의 다른 글
[혼공JS] 미니 프로젝트- 명언 생성기 (2) | 2024.01.24 |
---|---|
[혼공JS] 3주차 미션 (0) | 2024.01.23 |
[혼공JS] 클래스 chapter 9 (0) | 2024.01.21 |
[혼공JS] 예외처리 chapter 8 (0) | 2024.01.21 |
[혼공JS] 문서 객체 모델 chapter 7 (0) | 2024.01.19 |