고리타분한 개발자
함수 (Function) - 스코프와 네임스페이스 (Scopes and Namespaces) 본문
Javascript는 '{}' 블럭이 배배 꼬여 있어도 문법적으로는 잘 처리하지만, Block Scope는 지원하지 않는다. 그래서, Javascript에서는 항상 함수 스코프를 사용한다.
그리고, Javascript에는 Namespace 개념이 없기 때문에 모든 값이 하나의 전역 스코프에 정의된다.
변수를 참조할 때마다 Javascript는 해당 변수를 찾을 때까지 상위 방향으로 스코프를 탐색한다. 변수 탐색을 하다가 전역 스코프에서도 찾지 못하면 ReferenceError를 발생시킨다.
전역 변수 문제
이 두 스크립트는 전혀 다릅니다. Script A는 전역 스코프에서 monkey라는 변수를 정의하는 것이고 Scipt B는 현재 스코프에 변수 monkey를 정의하는 것이다.
다시 말하면, 이 둘은 전혀 다르고 var가 없을때 특별한 의미가 있다.
test 함수안에 있는 'monkey' 변수에 var 구문을 빼면 Global Scope의 foo의 값을 바꿔버린다. Javascript에서 코드가 길어지면 var를 빼먹어서 생긴 버그를 해결하기는 어렵다.
subLoop 함수는 전역 변수 i의 값을 변경해버리기 때문에 외부에 있는 for문은 subLoop를 한번 호출하고나면 종료됩니다. 두번째 for문에 var를 사용하여 i를 정의하면 이 문제는 생기지 않습니다. 즉, 의도적으로 외부 스코프의 변수를 사용하는 것이 아니라면 var를 꼭 넣어주어야 합니다
지역변수
Javascript에서 지역 변수는 함수의 파라미터와 var로 정의한 변수입니다.
foo변수와 i변수는 test함수 스코프에 있는 지역 변수라서 전역 공간에 있는 monkey, i 값은 바뀌지 않는다. 하지만, animal은 전역변수이기 때문에 전역 공간에 있는 animal의 값이 변경됩니다.
호이스팅(Hoisting)
Javascript는 선언문을 모두 호이스팅 한다. 호이스팅이란 var구문이나 function 선언문을 해당 스코프의 맨 위로 옮기는 것을 말합니다,
코드를 본격적으로 실행하기 이전에 Javascript는 var 구문과 function 선언문을 해당 스코프의 맨 위로 옮깁니다.
블록 스코프(Block Scope)는 없으므로 for문과 if문 안에 있는 var 구문들까지도 모두 함수 스코프 앞쪽으로 옮겨집니다. 그래서, if Block의 결과는 좀 이상해집니다.
원래 코드에서 if Block은 전역 변수 monkey를 바꾸는 것처럼 보였지만 호이스팅 후에는 지역변수를 바꿉니다.
호이스팅을 모르면 다음과 같은 코드는 referenceError를 낼 것으로 예상 되어질 것입니다.
var 구문은 전역 스코프의 맨위로 옮겨지기 때문에 이 코드는 잘 동작합니다.
이름 찾는 순서
Javascript의 모든 Scope는 현 객체를 가리키는 this를 가지고 있습니다. 전역 스코프에도 this가 있습니다.
함수 스코프에는 arguments라는 변수가 하나 더 있습니다. 이 변수는 함수에 인자로 넘겨진 값들이 담겨 있습니다.
예를 들어, 함수 스코프에서 monkey라는 변수에 접근할 때 Javacript는 다음과 같은 순서로 찾습니다.
1. 해당 Scope에서 var monkey 구문으로 선언된 것을 찾는다.
2. Function 파라미터에서 monkey라는 것을 찾는다.
3. 해당 Function 이름이 monkey인치 찾습니다.
4. 상위 Scope로 있는지 확인하고 있으면 1부터 다시 시작한다.
네임스페이스
Javascript에서는 전역 공간(Namespace)이 하나밖에 없어서 변수 이름이 중복되기 쉽습니다. 하지만, 이름없는 랩퍼(Anonymous Wrapper)를 사용하여 쉽게 처리할 수 있습니다.
이름없는 함수는 표현식(expression)이기 때문에 호출되려면 먼저 평가(Evaluate) 되어야 합니다.
함수를 평가하고 바로 호출하는 방법이 몇가지 더 있습니다.
결론
코드를 캡슐화할 때는 항상 이름없는 랩퍼(Anonymous Wapper)를 사용하여 네임스페이스를 만들어 사용할 것을 추천합니다. 이 래퍼(Wapper)는 이름이 중복되는 것을 막아주고 쉽게 모듈화할 수 있도록 도와 줍니다.
전역변수를 사용하는것은 좋지 못한 습관입니다.
License
이 게시글은 JavaScript Garden을 참고하여 작성 되었습니다. (https://github.com/BonsaiDen/JavaScript-Garden)
'JavaScript > Garden' 카테고리의 다른 글
함수 (Function) - 생성자 (Constructors) (0) | 2017.11.10 |
---|---|
함수 (Function) - arguments 객체 (0) | 2017.11.10 |
함수 (Function) - 클로저와 참조 (Closures and References) (0) | 2017.11.10 |
함수 (Function) - this 의 동작원리 (0) | 2017.11.09 |
함수 (Function) - 함수 선언과 표현식 (Function Declarations and Expressions) (0) | 2017.11.09 |