글 작성자: 택시 운전사
반응형

변수 범위(Variable Scope)

변수 범위는 특정 변수가 존재하는 영역입니다. 이를 통해 어디서 변수를 접근할 수 있는 지 알 수 있습니다.

변수(variable)은 지역 범위(local scope)와 전역 범위(global scope)를 둘 중 하나를 갖게 됩니다.

지역 범위(local scope, function-level)

C 혹은 C++이나 JAVA같은 프로그래밍 언어와는 달리, JavaScript는 블록 수준(block-level)의 범위를 가지고 있지 않습니다. 대신 JavaScript는 함수 수준(function-level)의 범위를 가집니다. 함수 안에서 정의된 변수는 지역 범위(local scope)를 가지며, 해당 함수와 그 내부 함수에서만 접근 가능합니다. 내부 함수에서의 외부 함수 변수 접근을 위한 클로저(Closure)를 통해 가능합니다.

함수 수준(function-level) 범위의 예제

var name = "Paris";
function showName() {
     var name = "Taxi"; // 지역 변수; showName()함수에서만 접근가능.
     console.log(name); // Taxi
}
console.log(name); // Paris : 전역 변수

잘못된 예제 (블록 수준(block-level) 범위로 오해할 경우)

var name = "Paris";
// 아래의 if문은 name변수에 대한 지역-범위를 생성하지 않습니다.
if (name) {
     name = "Taxi";
     console.log(name); // Taxi : 전역 변수
}
// name은 여전히 전역변수이며 if문에서 변경되었습니다.
console.log(name); // Taxi

지역 변수는 반드시 사용하기 이전에 선언해야합니다. 만약 ESlint를 사용하면 해당 오류를 줄일 수 있습니다.

// 지역변수를 var키워드로 선언하지 않았을 경우, 그것은 전역-범위(global-scope)가 됩니다.
var name = "Michael Jackson";
function showCelebrityName() {
     console.log(name);
}
function showOrdinaryPersonName() {
     name = "Johnny Evers";
     console.log(name);
}
showCelebrityName(); // Michael Jackson
// name 은 지역변수가 아닙니다. 이것은 전역변수 name을 변경해 버립니다.
showOrdinaryPersonName(); // Johnny Evers
// 이제 전역변수 name은 Johny Evers입니다. 더이상, 셀럽의 이름은 없습니다. -.-;;
showCelebrityName(); // Johnny Evers
// 해결책은 지역변수 선언시 var 키워드를 사용하는 것입니다.
function showOrdinaryPersonName() {
     var name = "Johnny Evers"; // 이제 name은 항상 지역변수이며, 전역변수를 덮어쓰지 않습니다.
     console.log(name);
}

지역 변수(local variable)은 함수 내에서 전역 변수(global variable)보다 높은 우선순위를 가집니다.

만약, 같은 이름의 전역 변수(global variable)와 지역 변수(local variable)가 존재할 경우 이 변수를 함수 내에서 사용한다면, 지역 변수(local variable)이 우선권을 갖게됩니다.

var name = "Paul";
function users() {
     var name = "Jack";
     console.log(name);
}
users(); // Jack

전역 범위(global scope)

함수의 외부에서 선언된 모든 변수(variable)은 전역 범위(global scope)를 가집니다. 브라우저에서 전역 범위는 window 객체를 가리킵니다. 따라서, 전역 변수(global variable)은 전체 애플리캐이션에서 사용 가능합니다.

// 전역변수는 아래와 같이 선언될 수 있습니다.
var myName = "Paris";
// 또는
firstName = "Paris";
// 또는
var name;
name;

모든 전역 변수는 window 객체와 연결됩니다. 따라서 아래와 같이 window 객체를 통해 모든 전역 변수에 접근할 수 있습니다.

console.log(window.myName); // Paris
// 또는
console.log("myName" in window); // true
console.log("firstName" in window); // true

만약 변수가 최초의 선언 없이 var를 이용하여 초기화되었다면, 이 변수는 자동으로 전역 범위에 추가됩니다.

function showAge() {
     // age는 전역 변수입니다.
     age = 90;
     console.log(age);
}
showAge(); // 90
// age는 전역 변수이므로, 이런식으로도 호출될 수 있습니다.
console.log(age); // 90

아래의 firstName은 둘 다 전역 범위(global scope)입니다. 두번째 firstName은 { } 블록으로 쌓여있지만 위에 언급한 것처럼 JavaScript는 블록 단위(block-level) 범위를 지원하지 않기 때문에 전역 변수로 취급합니다.

var firstName = "Paris";
{
     var firstName = "Taxi";
}
console.log(firstName); // Taxi
for (var i=1; i<=10; i++) {
     console.log(i); // 1~10까지 출력
}
// 변수 i는 전역 변수입니다. 그러므로, 아래 함수 호출시 i는 for문에서 실행된 후 마지막 값을 가르키게 됩니다.
function aNumber() {
     console.log(i);
}
aNumber(); // 11

setTimeout 변수는 전역 범위에서 실행됩니다.

setTimeout 안에서 선언된 모든 함수는 전역 범위(global variable)에서 실행됩니다.

// setTimeout 함수내에서 사용된 "this"객체는 myObj가 아니라, window객체를 참조합니다.
var highValue = 200;
var constantVal = 2;
var myObj = {
     highValue: 20,
     constantVal: 5,
     calculateIt: function() {
          setTimeout(function() {
               console.log(this.constantVal * this.highValue);
          }, 2000);
     }
}
// 전역변수인 highValue와 constantVal을 사용하여 계산됩니다. 200*2.
myObj.calculateIt(); //400

전역 범위와 지역 범위를 잘 구분해야합니다

가급적 전역 범위에 변수를 생성하는 것을 피해야 합니다.

// 다음 두 변수는 전역 범위에 있습니다.
var firstName, lastName;
function fullName() {
     console.log("Full Name : " + firstName + " " + lastName);
}

다음은 개선된 코드로 전역 범위(global variable)과 지역 범위를 잘 구분한 경우입니다.

// 함수내에 선언함으로서 이것은 지역변수 입니다.
function fullName() {
     var firstName = "Michael", lastName = "Jackson";
     console.log("Full Name : " + firstName + " " + lastName);
}

위의 예제에서 fullName() 함수 역시 전역 범위에 있습니다.

참고

반응형