Scope와 변수
Scope는 '범위'를 나타낸다.
좀 더 자세히 말하자면 변수가 적용되는 '유효 범위'의 개념이다.
유효 범위에 따라서 변수는 지역 변수(Local variable)와 전역 변수(global variable)로 나뉜다.
예를 들어 지역 변수는 해당 스코프, 즉 자신이 영향을 미칠수 있는 범위에서만 호출, 변경 될 수 있고
전역 변수는 전 영역에서 사용될 수 있다.
이는 프로그래밍에서 상당히 중요한 개념이며 각 언어마다 스코프의 개념이 조금 다를 수 있다.
자바스크립트가 대표적으로 Scope의 개념이 전통적인 방식과 다른 예인데,
C나 Java 등의 언어는 블록 단위로 스코프가 매겨지만, 자바 스크립트는 함수 단위 스코프이다.
그 말인즉, C나 Java 등이 if나 while 등의 블록 내에서 변수를 선언할 경우 해당 블록내에서만 영향을 미치는데 반해,
자바스크립트는 블록과 상관없이 function 단위로 구분되어진다.
이 때문에 처음 자바스크립트를 접하는 사람들은 간혹 실수를 저지르게 된다.
이러한 Scope 특징의 장단점과 보완을 따지기에 앞서 자바스크립트 변수선언에 사용되는 Var의 특징을 알아보자
1. 함수 단위의 유효 범위
1 2 3 4 5 6 7 8 9 10 11 12 | function scope() { var a = 0; if (true) { var b = 0; for (var c = 0; c < 5; c++) { console.log("c=" + c); } console.log("c=" + c); } console.log("b=" + b); } scope(); | cs |
앞서 말했던것과 같이 Var는 함수 단위의 유효 범위를 가진다.
따라서 if문안에 있는 b를 밖에서도 사용할 수 있고, for 또한 마찬가지이다.
위의 코드를 콘솔창에서 돌려보면 에러가 발생하지 않고 모든 값이 출력된다.
2. 변수명의 중복 허용
1 2 3 4 5 6 | var scope = 10; function scopeExam(){ var scope = 20; console.log("scope = " +scope); } scopeExam(); | cs |
처음 자바스크립트를 접했을 때 느낀점은 관대하다는 것 이였다.
위의 사례도 그 중 하나이다.
변수명이 중복될 경우 Java나 다른 언어는 바로 컴파일 에러를 발생시키면서 코드가 실행되지 않지만
자바스크립트는 그렇지 않다.
실행되고 있는 컨텍스트(context)에 있는 변수를 우선적으로 찾아 실행을 하게되면
이를 스코프 체이닝(Scope Chaining) 이라고 한다.
가까운 변수를 참조 한다고 말할수도 있겠으나, scopeExam 함수가 끝난 바로 아래에서
변수 scope를 호출할 경우, 전역으로 선언된 scope가 불려지기 때문에
현재 실행되고 있는 context의 변수를 찾는다고 할 수 있다.
만약 해당 컨텍스트에서 변수를 찾지 못하면 상위 컨텍스트로 넘어가며
최상위 main 컨텍스트에서도 변수를 찾지 못하면 그때서야 에러가 발생한다.
3. var 키워드의 생략
1 2 3 4 5 6 7 8 9 10 | function scopeExam(){ scope = 20; console.log("scope = " +scope); } function scopeExam2(){ console.log("scope = " + scope); } scopeExam(); scopeExam2(); | cs |
자바스크립트의 관대함의 연장선에 있는 특징이다.
자그마치 var 키워드가 생략 가능하다.
이렇게 var 키워드가 생략 되었을 때는 전역으로 판단되어, 최상위 컨텍스트에 등록된다.
따라서 첫번째 함수에서 선언된 변수지만 최상위 컨텍스트로 이동하여 전역 변수가 되며,
때문에 두번째 함수에서도 호출이 가능하다.
이러한 특징 때문에 자신도 모르는 사이에 var를 생략하여 전역 변수를 만드는 일이 생길수 있다.
이렇게 되면 변수끼리 이름이 부딪혀 예상치 못한 결과를 불러 올 수 있으니
평소에 각 텍스트 에디터에서 제공되는 JSHint등을 사용하도록 하자.
4. 렉시컬 특성
1 2 3 4 5 6 7 8 | function f1(){ var a= 10; f2(); } function f2(){ return a; } f1(); | cs |
렉시컬 특성이란 함수 실행 시 유효 범위를 함수 실행 환경이 아닌 함수 정의 환경으로 참조하는 특성이다.
위의 코드를 보면 f1에 지역변수 a가 선언되어있고 내부에서 f2를 호출하는데,
f2를 '선언할 때' 지역변수 a를 가져올수 없으므로 a의 값은 찾을수 없게 된다.
즉, 함수를 정의 할 때의 상태만 반영 되며, 함수가 생성되고 난 후의 상태는 의미가 없다는 것이다.
let과 const
위에서 살펴본대로 자바스크립트의 var는 장점과 단점이 둘 다 존재한다.
여기서 크나큰 단점이 존재하는데, 함수 단위 스코프와 전역에 대한 처리이다.
기존 블럭단위 스코프 패턴에 익숙해져있던 프로그래머들로 하여금 var의 스코프는 사용하기 난감했었고
여러 개로 나뉜 js 파일들이 합쳐지면서 전역으로 선언된 변수들이 충돌하거나 예상치못한 오류를 낳을때가 있다.
따라서 스코프에 대한 해결책의 수요가 증가하는 가운데 ES6에서 새로운 변수 키워드를 제공하게 되었다.
바로 let과 const 이다.
1. let
et은 블록 단위의 변수 타입이며 var보다 엄격하므로, 같은 스코프내에서 중복이나 호이스팅을 허용하지 않는다.
따라서 let의 유효범위는 {}, 브라켓 내부가 된다.
2.const
const는 타 언어에서 상수로 사용되는 변수 타입이다.
실제로 원시형 변수에 대해서는 const를 사용하게 되면 상수의 역할을 하게된다(초기값을 설정하지 않으면 에러 발생).
하지만 참조형 변수(Object, array, function)의 경우 const로 선언하는것이 좋은데,
참조형 변수의 경우 const로 선언하더라도 멤버값을 조작하는것이 가능하다.
이유는 해당 참조형 변수를 가르키는 값이 변한것이 아니라 메모리 내부의 변수값을 변경한 것이기 때문이다.
따라서 const로 지정된 참조형 변수의 참조값을 변경하려고 할 경우만 오류가 일어난다.
마찬가지로 블록 스코프를 가진다.
'개발' 카테고리의 다른 글
[Javascript] 함수(function) (0) | 2017.05.26 |
---|---|
[Javascript] 자바스크립트의 실행 문맥(Context) (0) | 2017.05.24 |
[Javascript] 객체(Object) (0) | 2017.05.23 |
[AWS] S3 소개 (0) | 2017.05.23 |
[AWS] S3 콘솔을 통한 기본 조작 방법 (0) | 2017.05.23 |
댓글