본문 바로가기
javascript

[자바스크립트] scope

by jinbro 2017. 3. 21.

[scope란]

- 변수의 범위를 말함
- 전역변수 / 지역변수로 구분됨


[자바스크립트 scope 특징]
- 자바스크립트 만의 변수 범위가 있음
- 자바스크립트는 c-family 언어(block-level scope :  코드블럭( { .... } )내에서 유효함)와 다른 스코프를 가지고 있음

1
2
3
4
5
6
7
8
int getSum(int a, int b) {
     int sum = a + b;
     /*
          sum은 해당 코드 블럭 내에서만 유효함
          (굳이 sum은 필요없지만 보여주기위해)
     */
     return sum;
}
cs


- 자바스크립트는 function-level scope임 
=> 코드 블럭과는 상관없이, function(함수) 내 정의된 변수는 함수 내에서만 사용가능함 
1
2
3
4
5
6
7
var x = 0
{
     console.log(x) // 0, block-scope였다면 undefined였겠지만....
     var x = 1;
     console.log(x) // 1
}
console.log(x) // 1, 코드 블럭( { .... } )과 전혀 상관없음
cs

- ECMA6부터 let 키워드를 사용하면 block-scope level variable 사용가능
1
2
3
4
5
6
7
8
var x = 0
{     
     let x = 2 // let 키워드로 block-level scope로 변경
     console.log(x) // 2, 위에 선언된 x는 더이상 function-level의 x가 아님
}
 
console.log(x) // 0
 
cs


[자바스크립트 변수 scope 종류]
1) 전역변수(global variable)
- function(함수) 밖의 글로벌영역에 선언하면 됨
- 전역변수는 전역객체(window)의 속성임
1
2
3
4
5
6
7
8
9
10
11
12
var global = 'global'
 
function myFunction(){
     console.log(global) // 'global'
     
     var local = 'local'
 
     console.log(local) // 'local'
}
 
console.log(global)
console.log(local) // Uncaught ReferenceError 발생(참조할 값이 없음)
cs

2) Non block-level scope
- 자바스크립트는 c-family 언어와 달리 코드 블럭( { ... } )에 스코프 영향을 받지않음
- 코드 블럭에 선언했다하더라도 글로벌영역으로 인식하여 전역변수로 선언됨
1
2
3
4
5
6
{     
     var x = 1;
     console.log(x) // 1
}
console.log(x) // 1, 코드 블럭( { .... } )과 전혀 상관없음
 
cs

3) function-level scope(function variable == local variable)
- 자바스크립트 scope 특징
- 함수 내에서 정의된 함수는 함수 내에서만 사용됨(지역변수)
- 전역변수와 함수 내 선언된 변수명이 같을 경우 지역변수에 우선순위를 두고 참조함
1
2
3
4
5
6
7
8
9
10
11
12
var a = 10;
var c = 30;
 
var myfunction = function(){
     var b = 20;
     var c = 100;
     console.log(c)
}
 
console.log(a) // 10
myfunction() // 100
console.log(b) // Uncaught ReferenceError
cs
 
- 내부 함수의 경우 내부함수를 감싸고 있는 외부함수의 변수를 참조할 수 있음
=> 유용한 방법이라고 함, 앞으로 포스팅에서 관련해서 다룰 것
1
2
3
4
5
6
7
8
9
10
11
12
function external() {
 
     var x = 100 // var라는 키워드가 새로운 변수를 만들고 값을 참조하는 것을 뜻함
 
     function internal() {
          console.log(x)
     }
 
     internal()
}
 
external() // 100, 오류나지않고 참조됨
cs

- var 키워드로 새로 생성하지않고, 전역변수를 참조하여 전역변수 값 변경 가능함 
    => 앞서까지는 전역변수와 지역변수의 차이를 보이기위해 변수명은 같지만 새로운 변수를 선언한 것
    => 지금은 변수명으로 값을 가져오고, 값을 변경하는 것임
    => 물론 함수 내에서 전역변수를 가져오는 것은 당연히 됨
    => 지역변수에서 새롭게 선언한 변수는 전역에서 사용 불가지만, 함수 내에서 전역변수를 수정하는 것은 된다는 것
1
2
3
4
5
6
7
var x = 100
 
function myfunction(){
     x = 200
}
 
console.log(x) // 200
cs

4) 암묵적 전역변수(implied global)
- 함수 내에서 변수를 선언할 때 var 키워드를 사용하지않으면됨
- var 키워드가 새로운 변수를 생성할 때 사용하는 키워드라는 것을 잊지말 것
1
2
3
4
5
6
7
var x = 100
 
function myfunction(){
     x = 200
}
 
console.log(x) // 200
cs

5) 호이스팅(hoisting)
- var 구문이나 function 선언문을 해당 스코프 맨위로 올리는 것을 말함(최상위 선언)
- 원인 : 변수생성과 값 초기화를 분리해서하기때문에(자세한 것은 다음 공부 후 포스팅할 것, 자바스크립트 엔진 내부 동작)
    => 코드를 실행하기 전 호이스팅을 함, 이후 코드 실행

- 자바스크립트 코드는 모두 호이스팅을 함
- 함수선언식(기명함수)은 함수 호이스팅 : 맨 뒤에 함수선언식으로 선언을 해도 맨 앞에서 호출 가능
    => 스크립트가 로딩 되는 시점에 초기화를 함, 코드를 실행할 때는 이미 초기화가 되어있음
1
2
3
4
5
6
foo() // 100
 
function foo() {
     var x = 100
     console.log(x)
}
cs

- 함수표현식(익명함수)은 변수 호이스팅
    => 런타임 시점에 함수를 해석하여 실행함
1
2
3
4
5
6
foo() //Uncaught TypeError
 
var foo = function(){
     var x = 100
     console.log(x)
}
cs

6) 변수명의 중복
- 서로 다른 js 파일이 있음(a.js, b.js)
- 각각의 파일에 선언된 변수명이 같고, 모두 전역변수임
- 게다가 같은 변수명을 호출하는 루프문이 돌고 있음
    => 무한루프문에 빠지기 쉬움
    => 아주 극단적인 예이지만 피해야할 것들을 알아둘 것
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* a.js */
function foo(){
     i = 0
}
 
/* b.js */
var a = 0
 
for(var i=0; i<10; i++){
     foo()
     /*
          for은 i도 전역변수이기때문에 foo()가 계속해서 0으로 초기화
          그 결과 무한루프가 돔
     */
 
     console.log(i)
}
cs

- 변수명을 짤 때 무의미하게 짜지 않기
- 전역변수는 딱 필요한 부분에서만 선언하기
- 반드시 전역변수가 필요한 것이 아니라면 지역변수 이용하기
    => 속도면에서도..... 중요..!


[함수 전역변수 줄이기]
- 전역변수 남발을 막기위해 어떤이의 제안임
- 전역변수 객체고 필요한 변수를 속성으로 만들고 값을 저장하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var global = { // 객체를 전역변수로
     global_variable1: "전역변수1",
     global_variable2: "전역변수2"
}
 
console.log(global.global_variable1) // "전역변수1"
 
var MYAPP = { }
 
/* 객체 내 객체 */
MYAPP.student = {
     name"jinbro",
     num: "2011890031"
}
 
console.log(MYAPP.student.name)
cs






'javascript' 카테고리의 다른 글

[웹 기본개념] 쿠키  (0) 2017.03.28
[웹 기본개념] URL / URI / REST API  (0) 2017.03.24
[웹 기본개념] HTTP 통신  (0) 2017.03.21
[자바스크립트] 프로토타입  (0) 2017.03.18
[자바스크립트] 함수는 무엇이다  (0) 2017.03.15

댓글