---
description: with 강혜정
---

# 01. 스코프 (Scope)

## 1. 스코프란?

&#x20;스코프란 현재 접근할 수 있는 변수들의 범위를 뜻한다.

어떠한 변수가 스코프 안에 선언되었으면 해당 스코프 안에서는 변수에 접근해서 읽거나 쓸 수 있고, 스코프 밖에서는 해당 변수에 접근할 수 없다.

```
for(var i = 0 ; i < 5 ; i++) {
    var temp = i;
}
console.log(temp)
```

이 코드를 실행해보면 어떤 결과가 나올까? 자바스크립트를 사용해보지 않은 프로그래머들은 에러가 날 것이라고 말한다. 하지만 실제 이 코드를 실행해보면 콘솔 창에 **4**라는 결과가 나온다.



\<div>를 3개 출력하고, 각각의 \<div>를 클릭했을 때 어떤 \<div>를 클릭했는지 알려주는 소스가 있다.

```
<div id="div0">Click me! Dive 0</div>
<div id="div1">Click me! Dive 1</div>
<div id="div2">Click me! Dive 2</div>
<script>
    var i , len = 3;
    for (i = 0 ; i < len ; i++) {
        document.getElementById("div" + i)
        .addEventListener("click", function () {
            alert("You clicked dive #" + i);
        }, false);
    }
</script>
```

이 소스를 실행하면 어떤 것을 클릭해도 알림창은 You clicked div #3 밖에 나오지 않는다.

왜냐하면 스코프가 생성되고 유지되는 방법이 문제이기 때문이다. 이 소스의를 분석해보자면 i가 글로벌 스코프이기 때문에 이러한 문제가 발생된다.

i는 이미 0에서부터 3까지 증가한 뒤, 이후에 for-loop가 끝나고 나서도 계속 유지된다. 따라서 나중에 alert() 함수가 호출될 때 변수 i의 값은 이미 for-loop가 끝난 후의 값인 3으로 출력된다.

## 2. 스코프의 생성

자바스크립트는 다른 언어와는 달리 일반적인 블록 스코프를 따르지 않는다. 자바 스크립트의 스코프는 특정 구문이 실행될 때 새로 생성하며, 그 특정 구문은 **function, width, catch**이다.

#### 1. function 구문의 스코프

```
function foo() {
    var b = "Can you access me?";
}
console.log(typeof b === "undefined");
```

function 블록 안에 있는 모든 내용이 새로운 내부 scope에 포함되어, 외부에서 내부에 선언된 변수에 접근할 수 없다.

#### 2. catch 구문의 스코프 생성

괄호 안에 인자로 받은 변수들만 새로운 내부 스코프에 포함되어 그 다음으로 오는 블록 안에서만 접근할 수 있다.

```
try {
    throw new exception("fake exception");
} catch (err) {
    var test = "can you see me";
    console.log(err instanceof ReferenceError === true);
}
console.log(test === "can you see me")
console.log(typeof err === "undefined")
```

위 코드에서 err 는 외부에서 접근할 수 없지만 test 번수는 catch 블록 외부에서도 접근할 수 있다.

#### 3. with 구문의 스코프

catch 구문과 비슷하다

```
with ({inScope : "You can't see me"}) {
    var notInScope = "but you can see me";
    console.log(isScope === "You can't see me");
}
console.log(typeof inScope === "undefined")
console.log(notInScope === "but you can see me");
```

## 3. with

자바스크립트 커뮤니티에서 거의 모든 사람이 공통으로 이야기하는 "사용하면 안 좋은" 구문 두 가지 중에 당당히 이름을 올린 구문이 있다. 그것은 바로 with이다.

먼저 with 구문이란 파라미터로 받은 개체를 스코프 체인에 추가하여 동작한다.

```
width (object) {
    statement;
}
```

with 구문은 다른 구문들과 유사하게 블록 괄호는 옵션이고, with의 인자로 받는 object는 그 이후 statement나 블록 안에 object가 가지고 있는 변수들을 스코프 체인에 추가해서 해당 변수들을 로컬 변수처럼 사용할 수 있다.



하지만 아까 말했 듯이 스코프를 생성하는 몇 안 되는 구문인데도 왜 사용하지 말라고 하는 것일까?

첫 번째 이유는 스코프를 생성함으로써 생기는 추가 자원 소모이다.

새로운 인자로 들어온 스코프에서만 데이터와 함수들을 이용하면 서능이 향상되겠지만, 스코프 체인 상위에 있는 스코프에서 데이터를 가져올 때는 검색 시간고 자원 소모 등 처리에 드는 비용이 추가로 든다.

두 번째는 with로 생기는 소스의 모호성이다.

```
function doSometing(value, obj) {
    width(obj) {
        console.log(value);
        value = "which scope is this?";
    }
}
```

위의 소스를 보면 콘솔에 출력하는 value가 doSomethig에서 넘어가는 value 인자인지, with를 통해서 넘어가는 obj의 value일 수도 있다.



그래서 ECMAScript 6 표준에서 with 구문을 제외하였고, 이제는 with 구문이 없었던 것처럼 개발을 해야 한다.
