whatisthis?
javaScript. 함수 스코프(scope) 본문
자바스크립트에서 ECMAscript 5 이전에는 var로 선언한 변수로 데이터를 저장했었다.
(ECMA5이후에는 const와 let이 등장하였다. 현재 var은 웬만해선 쓰지 X)
var로 전역(global)변수를 만드는 것은 삼가야 한다!
그렇다면, 전역 변수란 무엇이며, 삼가야 하는 이유는 무엇일까?
** 전역변수 (global variable)
자바스크립트에서 가장 바깥 범위(window 객체)에 변수를 만드는 것.
함수 안에 포함되지 않음.
예제를 통해 살펴보자.
var x = 'global';
function ex() {
var x = 'local';
x = 'change';
}
ex(); // x를 바꿔본다.
alert(x); // 여전히 'global'
함수 ex 안의 x는 local변수(지역변수) 이고, 함수 바깥의 변수는 global변수(전역변수)이다.
ex()로 ex함수를 호출하여 x값을 change로 바꾸었으나,
함수 바깥에서의 x는 여전히 global 이다.
window 객체와 BOM에 대해 아래 포스팅에서 다루도록 하겠다.
🔻🔻🔻
https://mywebproject.tistory.com/231
전역 변수가 무엇인지 살펴보면 다음과 같다.
var hello = 'hello?';
window.hello; // 'hello?'
** 주의 > 위 예제는 var만 가능하다. / 즉, let이나 const는 window객체에 저장되는 전역변수가 ❌
전역변수는 어디에서나 쓸 수 있고,
그에 반대되는 개념인 지역변수는 그 함수 안에서만 쓸 수 있다.
❗ 지역변수는 아무리 해도 전역변수에 영향을 끼칠 수 없다. -> 함수 스코프(scope) 때문.
- 함수 안에서 선언된 변수는 해당 함수 안에서만 사용 가능하다.
예외를 살펴보면 다음과 같다.
var x = 'global';
function ex() {
x = 'change';
}
ex();
alert(x); // 'change'
첫번째 예제는 함수 내에서 var을 선언하였지만,
ex 함수 내에서 var을 선언하지 않은 경우에는 전역변수(global variable)의 값을 바꿀 수 있다.
> 함수 ex의 범위 안에 x가 없기 때문에 - 더 넓은 범위의 전역스코프에서 찾아온 것임.
왜?
자바스크립트는 변수의 범위를 호출한 함수의 지역스코프부터 전역스코프까지 점차 넓혀가며 찾기 때문임.
>> 즉, 지역 변수가 없다면 전역 변수를 호출해 오는 것임.
** 정확한 원리는 실행 컨텍스트 에서 추후 언급예정.
전역변수와 지역변수의 관계에서 스코프 체인(Scope Chain)이라는 개념이 나온다.
내부함수에서는 외부함수의 변수에 접근 가능하지만, 외부함수에서는 내부함수의 변수에 접근할 수 ❌ |
var myName = 'thisisyjin';
function outer() {
console.log(myName);
function inner() {
var yourName = 'injung';
console.log(myName);
}
inner();
}
outer();
console.log(yourName); //undefined
inner()함수는 myName이라는 변수를 찾기 위해서
1. 자신의 스코프에서 찾음
2. outer()함수 스코프에서 찾음
3. 전역스코프에서 찾음
위와 같은 순서대로 변수를 찾게 된다.
이렇게 꼬리를 물고 계속 범위를 넓히면서 찾는 관계를 스코프체인 이라고 한다.
+) 외부함수인 outer에서는 내부함수 inner의 변수를 찾지 못하므로
위 예제의 마지막줄은 undefined가 되는 것임.
💡 주의! 스코프는 '호출'할 때가 아니라 '선언'할 때 생김.
var name = 'zero'; // 전역변수 name
function log() {
console.log(name); // 'zero'
}
function wrapper() {
name = 'nero'; // 전역변수 name의 값 변경
log(); // log()함수에 의해 전역변수 name 출력
}
wrapper();
// RESULT | 'nero'
log()로 log함수를 호출하기 전에 전역변수 name을 'nero'로 바꾸었으므로
결과는 nero가 된다.
var name = 'zero'; // 전역변수 name
function log() {
console.log(name);
}
function wrapper() {
var name = 'nero'; // wrapper 내의 지역변수 name 선언
log(); // log()호출함. 전역변수 name을 로그함
}
wrapper();
// RESULT | 'zero'
log안의 name은 전역변수 name을 의미하므로, 정답은 zero가 된다.
이런것을 Lexical Scoping이라고 한다. (= 정적 스코프)
함수를 선언하는 순간, 함수 내부의 변수는 자기 스코프 상위범위에서 참조하게 된다. = 가까운 곳
위 예시에서는 log 함수안에 name은 전역변수 name을 참조하였다.
그래서 wrapper 의 log()를 호출해서 지역변수 name='nero'를 참조하지 않고 전역변수 name을 참고한 것.
💡 그렇다면, 왜 전역변수 만드는 것을 삼가야할까?
변수가 섞일 수 있기 때문.
** 해결방법 - 전역 변수 대신 함수 안에 넣어 지역변수로 만들면 됨.
- 또는 객체 안의 속성(property)로 만들 수 있음.
예>
var obj = {
x: 'local',
y: function() {
console.log(this.x);
}
}
위와 같이 하면 obj.x나 obj.y()와 같이 접근해야 하므로
다른 변수나 함수와 섞이는 문제를 해결할 수 있다.
>> 이런 방법을 네임스페이스를 만든다고 표현함.
- obj라는 고유 네임스페이스를 만들어서 겹치지 않도록.
- 대부분의 라이브러리가 네임스페이스를 사용중.
예> naver는 jindo / facebook은 FB / jquery는 jQuery(또는 $)
REFERENCE
https://www.zerocho.com/category/Javascript/post/5740531574288ebc5f2ba97e
이 포스팅은 zerocho님의 javascript 강의를 보고 작성한 글입니다.
공부+기록 용으로 작성한 것이며, 자세한 것은 위 포스팅을 참고하세요!
'WEB STUDY > JAVASCRIPT' 카테고리의 다른 글
javaScript. 실행 컨텍스트 (Execution Context) (0) | 2022.01.11 |
---|---|
javaScript. IIFE(즉시 호출 함수 표현식) (0) | 2022.01.11 |
javaScript. BOM (0) | 2022.01.10 |
javaScript. Window 객체 (0) | 2022.01.10 |
javaScript. call() / bind() / apply() (0) | 2022.01.09 |