Scope
- 스코프의 목적
- 범위를 제한하여 식별자를 해결하려는 것. 스코프에서 식별자를 해결
- Identifier Resolution(식별자 해결)
- 변수 이름, 함수 이름을 찾는 것
- 이때 스코프를 사용
- 이름을 찾게 되면 값을 구할 수 있음
- 크게는 이름을 설정하는 것도 식별자 해결
- 스코프는 식별자 해결을 위한 것
- 스코프 설정
- 엔진이 function book(){}을 만나면 function object가 생성되고 scope를 설정한다.
- 생성한 function object의 [[Scope]]에 scope를 설정한다. 즉, 이 때 scope가 결정된다.
- 내부 프로퍼티 [[Scope]]에 결정되는 것을 정적 스코프라 하고, 함수를 호출할 때 scope를 결정하는 것을 동적 스코프라고 한다.
- 동적 스코프를 10000번 호출하면 10000번 스코프를 설정하지만 정적 Scope를 설정하면 한번만 스코프를 설정하면된다.
function book() { var point = 123; function get() { console.log(point); }; get(); }; book();
- book()함수를 호출한다.
- 엔진 컨트롤이 book function에 첫번째 줄로 이동한다.
- 함수 선언을 먼저 찾는다. function get()을 만나게 되어 function object를 생성한다.
- 스코프를 설정한다.
- function object의 [[Scope]]에 스코프를 설정한다. 이 때 정적으로 스코프가 결정된다.
- 표현식을 처리한다. - point 변수 선언(undefined)
- 코드를 실행한다. - point 에 123 값을 대입, get() 함수를 호출한다.
- 엔진이 function book(){}을 만나면 function object가 생성되고 scope를 설정한다.
Global Object
- Global Object
var value = 100; function book() { var point = 200; return value; } book();
- var value = 100;
- 100을 value 변수에 할당한 것은 value로 검색하여 값을 사용하기 위한 것(Identifier Resolution)
- 함수 안에 변수를 선언하면 변수가 함수에 속하게 되지만
- value 변수를 함수 안에 작성하지 않았다.
- value 변수가 속하는 object가 없으며, 이 때, Global Object를 설정하게 된다.
- point 변수는 함수 안에 선언했기 때문에 book이란 function object에 속하게 되지만 value 변수는 함수 안에 없고, 전역적인 위치에 선언되었기 때문에 Global Object에 설정된다.
- 이런 메커니즘을 구현할 수 있는 것으 Global Object가 하나만 있기 때문이다.
- var value = 100;
- Global Object 특징
- JS 소스 파일 전체에서 Global Object는 하나만 있다.
- new 연산자로 인스턴스 생성이 불가하다.
- JS 소스 파일 전체 기준으로 에 작성된 모든 코드이며 모든 코드에서 사용가능하다.
<script src="./abc.js"> <script src="./def.js">
// abc.js var value = 100; function book() { return value + 50; }
// def.js console.log(value); // 100 console.log(book()); // 150
- def.js 파일의 코드에서
- 글로벌 오브젝트에 작성된 변수 value 값을 출력하고 book() 함수를 호출한다.
- def.js 파일의 코드에서
- JS 소스 파일 전체에서 Global Object는 하나만 있다.
- Global Scope
- Global Object가 Global Scope이다.
- Object는 개발자 관점으로 오브젝트에 함수와 변수를 작성
- Global Object는 Number, Math와 같은 Object는 아니다.
- 함수와 변수를 작성하기 위해서는 Object가 있어야 하기 때문에 host object 개념으로 Window Object를 Global Object로 사용하여 함수와 변수가 작성된다.
- Scope는 식별자 해결을 위한 것으로 엔진 처리 관점
- 엔진이 식별자 해결을 위해 Scope를 사용하는 것
- Global Scope는 최상위 스코프로 함수에서 보면 최종 스코프
- 함수 스코프에 변수, 함수가 없으면 그 다음 스코프를 찾게 된다. 계층적으로 따라 올라가다가 최종적으로 Global Scope를 만나게 된다.
var value = 100; function book() { return value; }; book();
- function book(){…}
- book 함수가 속한 오브젝트가 없으므로, book 함수란 function object를 글로벌 오브젝트에 설정
- book 함수는 글로벌 함수가 된다. (전역 함수)
- var value = 100;
- value 변수가 글로벌 오브젝트에 설정
- 글로벌 변수 (전역 변수)
- 글로벌 오브젝트에 설정된다는 것은 오브젝트 관점이다.
- 스코프와 식별자 해결 관점은 Scope가 Global Scope라는 것
- book();
- book 함수를 호출하려면, “오브젝트.book()” 형태로 작성해야 하는데 오브젝트를 작성하지 않고 함수만 작성했다.
- 오브젝트를 작성하지 않으면, 글로벌 오브젝트를 “오브젝트”로 간주하여 글로벌 오브젝트의 book() 함수를 호출한다.
- 즉, 글로벌 스코프에서 book을 찾아 호출한다.
- function book(){…}
- 함수 스코프에 변수, 함수가 없으면 그 다음 스코프를 찾게 된다. 계층적으로 따라 올라가다가 최종적으로 Global Scope를 만나게 된다.
- Scope Binding
- 바인딩
- 구조적으로 결속된 상태로 만드는 것.
- 대상: 프로퍼티 이름 (변수, 함수의 이름)
- 바인딩 목적
- 스코프 설정, 식별자 해결
- 바인딩 시점 구분
- 정적 바인딩(Lexical, Static Binding) / 정적 스코프(Lexical Scope)
- 동적 바인딩(Dynamic Binding) / 동적 스코프(Dynamic Scope)
- 구조적으로 결속된 상태로 만드는 것.
- 정적, 동적 바인딩
- 정적 바인딩 (Lexical Binding)
- 초기화 단계에서 바인딩
- 함수 선언문 이름을 바인딩
- 표현식(변수, 함수) 이름을 바인딩
- Javascript는 대부분 정적 바인딩이다.
- 동적 바인딩 (Dynamic Binding)
- 실행할 때 바인딩
- eval() 함수, with 문
- 정적 바인딩 (Lexical Binding)
- 바인딩 시점의 중요성
- 바인딩 시점이 중요한 이유: 바인딩할 때 스코프가 결정되기 때문
- function object 생성 시점에 스코프 결정
- 스코프를 function object의 [[Scope]]에 설정
- 스코프가 변경되지 않음 (정적 스코프)
- 함수 안의 모든 함수의 Scope가 같다.
function book() { var point = 100; function add(param) { point += param; }; var get = function() { return point; }; add(200); console.log(get()); // 300 }; book();
- 마지막 줄에서 book() 함수를 호출
- 초기화 단게에서 함수와 변수 이름을 선언적 환경 레코드(DER)에 바인딩
- function add(param) {…}
- function object 생성
- add 함수가 속한 스코프(영역)를 add 오브젝트의 [[Scope]]에 설정
- add 이름을 레코드에 바인딩
- var point = 100;
- point 이름을 레코드에 바인딩 (point: undefined)
- var get = function() {…}
- get 이름을 레코드에 바인딩 (get: undefined)
- 바인딩으로 함수와 변수의 식별자가 해결됨 == 코드 실행 ==
- var point = 100;
- point에 100 할당 (point: 100)
- var get = function() {};
- function object 생성, get에 할당
- get 함수가 속한 Scope(영역)를 get object의 [[Scope]]에 설정 == add() 함수 호출 ==
- add(200); 을 호출
- point += param;
- 먼저 add() 함수 안에 선언적 환경 레코드(DER)에서 point 이름을 찾습니다. point가 해당 스코프에 없으므로 다시 검색하게 되며 ( add() 함수 안에 선언적 환경 레코드는 아무런 값이 없다. 다만, add() 밖 book()에 있는 point는 외부 렉시컬 환경 참조(OLER)에 설정된다.)
- add object의 [[Scope]]를 스코프로 사용하지만 없으므로 외부 스코프로 이동
- book object가 스코프이며 point가 있으므로 값을 더한다.
- console.log(get());
- return point;
- 레코드에 point가 없으므로 다시 검색
- get 오브젝트의 [[Scope]]를 스코프로 사용
- book 오브젝트가 스코프이며 point 가 있으므로 값을 반환한다.
- 마지막 줄에서 book() 함수를 호출
- 동적 바인딩
- 코드를 실행할 때마다 바인딩
- with 문
- eval() 함수
- with 문
- “use strict” 환경에서 에러 발생
- eval() 함수
- 보안에 문제가 있다.
- 코드를 실행할 때마다 바인딩
- 바인딩
** 출처1. 인프런 강좌_자바스크립트 중고급: 근본 핵심 이해