# 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 구문이 없었던 것처럼 개발을 해야 한다.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wlrma-study.gitbook.io/js-study/undefined/undefined-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
