전역 변수와 지역 변수
자바스크립트에서 주로 변수를 사용해 데이터를 저장했었습니다. var로 선언했었습니다. 물론 변수를 만드는 일은 문제가 되지 않았지만. 전역(global)변수를 만드는 일은 최대한 지양해야 합니다. 전역변수란 자바스크립트에서 제일 바깥 범위(함수 안에 포함되지 않은)에 변수를 만드는 겁니다. window객체나 global객체에 변수를 만드는 것입니다.
var x = 'global'
function ex() {
var x = 'local';
x = 'change';
}
ex();
alert(x);
다음을 보시면 같은 x여도 ex함수 바깥의 x는 전역변수이고 ex함수 안의 x는 ex함수의 지역변수가 됩니다. 지역 변수는 함수 안에 들어있는 변수를 의미합니다.
스코프
위의 상황에서 지역변수는 아무리 해도 전역변수에 영향을 끼칠 수 없습니다. 바로 함수 스코프 때문입니다. 범위라는 말처럼 함수 안에서 선언된 변수는 해당 함수 안에서만 사용할 수 있습니다. var x = 'local'은 ex함수 안에서만 그 데이터를 사용할 수 있습니다. 그 밑에 x = 'change'도 함수 안의 지역변수 x를 바꾸는 겁니다.
var x = 'global'
function ex() {
x = 'change';
}
ex();
alert(x);
아까와 달리 ex함수에 var를 선언하지 않았습니다. 이때는 전역변수가 바뀌게 됩니다. 자바스ㅡ립트는 변수의 범위를 호출한 함수의 지역 스코프부터 전역 변수들이 있는 전역 스코프까지 점차 넓혀가며 찾기 때문입니다. 함수 ex의 범위 안에 x가 없기 때문에 더 넓은 범위인 전역 스코프에서 찾는 겁니다.
lexical scoping
스코프는 함수를 호출할 때가 아니라 선언할 때 생깁니다. 호출이 아닌 선언입니다. 정적 스코프라고도 불립니다.
var name = 'zero';
function log() {
console.log(name);
}
function wrapper() {
name = 'nero';
log();
}
wrapper();
여기서 당연히 wrapper함수 안에서 name을 'nero'로 바꾸었으므로 뭔 짓을 해도 nero가 나올 것입니다. 하지만 다음과 같은 상황을 봅시다.
var name = 'zero';
function log() {
console.log(name);
}
function wrapper() {
var name = 'nero';
log();
}
wrapper();
이렇게 하게 되면, zero가 나오게 됩니다. 그 이유는 log안의 name은 wrapper안의 지역 변수 name이 아니라, 전역변수 name을 가리키고 있는 겁니다. 이런 것을 lexical scoping이라고 합니다.
lexical scoping은 함수를 처음 선언하는 순간, 함수 내부의 변수는 자기 스코프로부터 가장 가까운 곳에 있는 변수를 계쏙 참조하게 됩니다. 무슨 짓을 해도 log함수가 한 번 선언된 이상, 전역변수를 가리키게 되어 있는 name변수가 다른 걸 가리키게 하려면 전역 변수의 값 자체를 바꾸는 것 뿐입니다.
전역 변수를 만드는 일은 지양하라고 했는데, 그 이유는 변수가 섞일 수 있기 때문입니다. 자바스크립트 앱을 만들면서 혼자만 개발하는게 아니라, 여러 명과 협동도 하고, 다른 사람의 라이브러리를 사용하는 일도 많습니다. 그런데 전역변수를 사용하다 보면, 우연의 일치로 인해 같은 변수 이름을 사용해서 이전에 있던 변수를 덮어쓰는 불상사가 발생할 수도 있습니다.
이의 간단한 해결 방법은 전역 변수 대신 한 번 함수 안에 넣어 지역변수로 만드는 것입니다. 아니면 객체 안의 속성으로 만들 수 도 있습니다.
var obj = {
x: 'local',
y: function() {
alert(this.x);
}
}
위처럼 하면 obj.x, obj.y()이렇게 접근해야 하기 때문에 다른 사람과 섞일 염려가 없습니다. obj를 통째로 덮어쓰지 않는 이상은요
이런 방법을 네임스페이스를 만든다고 합니다. obj라는 고유 네임스페이스를 만들어서 겹치지 않게 하는 겁니다. 대부분의 라이브러리가 네임스페이스를 사용하고 있습니다. naver는 jindo, facebook은 FB, jquery는 $같이요
하지만 만약에 obj.x = 'hacked'라고 한다면 obj.y();을 했을 시 local대신 hacked가 alert됩니다. 이를 방지하려면
var another = function () {
var x = 'local';
function y() {
alert(x);
}
return { y: y };
}
var newScope = another();
조금 복잡하지만 위와 같이 하면 됩니다. another();하는 순간 return에 의해 {y: function() {alert(x)}};가 newScope에 저장됩니다. 이제 newScope라는 네임스페이스를 통해서 y에 접근할 수 있습니다.
const newScope = (function () {
var x = "local";
function y() {
alert(x);
}
return { y: y };
})();
console.log(newScope.y());
또한 이렇게 IIFE(즉시 호출 함수 표현식)을 통해서 간결하게 표현할 수 있습니다. 많은 라이브러리가 이 구문을 활용하고 있습니다. 여기서는 x에 임의로 접근해서 값을 바꿀 수 없고 y만을 호출 할 수 잇습니다. 비공개 변수가 없는 자바스크립트에 비공개 변수 기능을 만들어 주기 때문에 많은 라이브러리에서 이 모듈 패턴 방식을 사용합니다.!!
'Web > Advanced Web Programming' 카테고리의 다른 글
Advanced Web Programming - Closure (0) | 2022.06.14 |
---|---|
Advanced Web Programming - lexical scope ( 2 ) (0) | 2022.06.13 |
Java Script - this 바인딩 (0) | 2022.06.04 |
고급 웹 프로그래밍 - 정리 - 2 (0) | 2022.06.04 |
고급 웹 프로그래밍 - 기말 정리 - 1 (0) | 2022.06.04 |