인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.



스코프 체인


자바스크립트에서 굉장히 중요한 개념입니다. 

스코프 체인, 즉 유효범위인데 c++과는 다른 유효범위를 가지고 있기 때문에 주의해야합니다.


오직 함수만이 유효 범위의 한 단위가 되고 [[scope]] 프로퍼티로 각 함수 객체 내에서 연결 리스트 형식으로 관리됩니다.

이를 스코프 체인이라 합니다.


각각 함수는 [[scope]]프로퍼티로 자신이 실행된 실행 컨텍스트의 스코프 체인을 참조합니다. 함수가 실행되는 순간 실행 컨텍스트가 만들어지고 이 실행 컨텍스트는 실행된 함수의(실행된 함수가 속한 실행 컨텍스트의 scope) [[scope]] 프로퍼티를 기반으로 새로운 스코프 체인을 만듭니다.


스코프 체인

1. 현재 실행되는 함수 객체의 [[scope]] 프로퍼티를 복사한다.

2. 새롭게 생성된 변수 객체(활성 객체)를 맨앞에 추가한다.


-> 스코프 체인 = 현재 실행 컨텍스트의 변수 객체 + 상위 컨텍스트의 스코프 체인



var name = 'song';

function printName() {
    var age = 29;

    function printAge(){
        console.log(age);
    };

    console.log(name);
}; 


위와 같은 예제의 스코프 체인을 그려 보면 다음과 같습니다.




이렇게 만들어진 스코프 체인으로 식별자 인식이 이루어집니다. 식별자 인식은 첫 번째 변수 객체부터 시작하여 해당하는 프로퍼티가 있는 지 탐색하고, 발견하지 못하면 다음 객체로 이동하며 탐색을 진행합니다.



인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.



실행 컨텍스트


ECMAScript에서는 실행 컨텍스트를 "실행 가능한 코드를 형상화하고 구분하는 추상적인 개념"이라고 기술합니다.

이 컨텍스트 안에 실행에 필요한 여러 가지 정보를 담고 있습니다. 


실행 컨텍스트가 생성되는 경우는 세 가지가 있습니다.

1) 전역 코드

2) eval() 함수로 실행되는 코드

3) 함수 안의 코드를 실행할 경우


대부분 함수로 실행 컨텍스트를 만듭니다.

ECMAScript에서는 또 실행 컨텍스트 생성을 다음처럼 설명합니다.

"현재 실행되는 컨텍스트에서 이 컨텍스트와 관련 없는 실행 코드가 실행되면, 새로운 컨텍스트가 생성되어 스택에 들어가고 제어권이 그 컨텍스트로 이동한다."


전역 실행 컨텍스트는 일반적인 실행 컨텍스트와 다릅니다. arguments 객체가 없으며 전역 객체 하나만을 포함하는 스코프 체인이 있습니다.


약간 차이점이 있지만 C++에서 콜스택과 비슷한 개념이라고 보시면 쉬울 것 같습니다.


실행 컨텍스트가 생성되면 자바스크립트 엔진을 활성 객체를 생성합니다. 이 객체에 앞으로 사용하게 될 매개변수나 사용자가 정의한 변수 및 객체를 저장하고, 새로 만들어진 컨텍스트로 접근 가능하게 되어 있습니다.


활성 객체


실행 컨텍스트가 생성되면 자바스크립트에서는 해당 컨텍스트에서 실행에 필요한 여러가지 정보를 담을 객체를 생성합니다. 그게 바로 활성 객체입니다. 사용자가 접근할 수 있는 영역은 아니고 자바스크립트 엔진이 사용하는 영역입니다.


활성 객체가 지닌 정보

1) argumens 객체

인자로 들어온 arguments 객체를 arguments 프로퍼티로 접근합니다.


2) 스코프 정보// 스코프 체인 scope 프로퍼티

현재 컨텍스트의 유효 범위를 나타내는 스코프 정보를 생성합니다.


3) 변수

변수나 내부함수는 활성 객체가 생성되는 시점에 생성은 되지만 초기화는 해당 표현식이 실행될 때 이루어집니다.


4) this



인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.



1.prototype과 _proto_ 프로퍼티


자바스크립트에서는 프로토타입 기반의 객체지향 프로그래밍을 지원합니다.(ES6 부터는 클래스가 도입되었음.)

그 근간이 되는 것이 프로토타입과 프로토타입 체이닝입니다.


자바스크립트의 모든 객체는 자신의 부모인 프로토타입 객체를 가리키는 참조 링크 형태의 숨겨진 프로퍼티가 있습니다. ECMAScript에서는 이러한 링크를 암묵적 프로토타입 링크(implicit prototype link) 라 부르며이러한 링크는 모든 객체의 _proto_ 프로퍼티에 저장됩니다.


주의할 점이 _proto_ 프로퍼티와 prototype 프로퍼티가 다르다는 점입니다. 도대체 왜 이렇게 헷갈리게 네이밍을 했는지 모르겠어요..


자바스크립트에서 모든 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 프로토타입 객체를 자신의 부모 객체로 설정하는 _proto_ 프로퍼티에 링크로 연결합니다.



var Person = function(name){
    this.name = name;
};

var song = new Person('song');


위와 같은 예제에서 Person() 생성자 함수로 생성된 song객체는 Person() 함수의 프로토타입 객체 즉 prototype 프로퍼티와 연결되어있는 객체를 자신의 _proto_ 프로퍼티에 링크로 연결합니다.


prototype 프로퍼티는 함수의 입장에서 자신과 링크된 프로토타입 객체를 가리키고,

_proto_ 프로퍼티는 객체의 입장에서 자신의 부모 객체인 프로토타입 객체를 내부의 숨겨진 링크로 가지고 있습니다.


Person() 생성자의 prototype 프로퍼티와 song 객체의 _proto_ 프로퍼티는 동일한 객체를 가리키는 겁니다.


정리하자면 자바스크립트에서 모든 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체(부모 객체)로 취급합니다.


2.프로토타입 체이닝


자바스크립트에서 객체는 자기 자신의 프로퍼티뿐 아니라, 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티 또한 자신의 것처럼 접근할 수 있습니다. 이것을 가능하게 하는 것이 바로 프로토타입 체이닝입니다.


자바스크립트에서 특정 객체의 프로퍼티나 메서드에 접근하려고 할 때, 해당 객체에 접근하려면 프로퍼티 또는 메서드가 없다면 _proto_ 링크를 따라 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티를 차례대로 검색하는 것을 프로토타입 체이닝이라 합니다.

자바스크립트에서 모든 타입의 프로토타입 체이닝의 종점은 Object.prototype입니다.

자바스크립트의 기본 데이터 타입들도 표준 메서드를 가지고 있고, 이 표준 메서드들은 각각 Number.prototype, String.prototype, Array.prototype등과 같이 이들의 프로토타입 객체에 정의되어 있습니다.

그리고 결국 이러한 기본 내장 프로토타입 객체 또한 Object.prototype을 자신의 프로토타입으로 가지고 프로토타입 체이닝으로 연결됩니다. 때문에 모든 객체가 아닌 모든 타입의 프로토타입 종점이 Object.prototype이라고 한 것 입니다.

그리고 객체의 프로퍼티를 읽거나 메서드를 실행할 때에만 프로토타입 체이닝이 일어납니다. 당연한 말이지만 해당 객체에 없는 프로퍼티나 메서드를 접근할 때 프로토타입 체이닝이 일어납니다.




3.디폴트 프로토타입 변경


디폴트 프로토타입 객체는 함수가 생성될 때 같이 생성되며, 함수의 prototype 프로퍼티에 연결됩니다. 이렇게 자바스크립트에서 함수를 생성할 때 해당 함수와 연결되는 디폴트 프로토타입 객체를 다른 일반 객체로 변경할 수 있습니다.

이를 통해서 상속을 구현합니다.


프로토타입을 통한 상속 구현이 가능한 이유는 프로토타입 또한 객체이므로 프로퍼티와 메서드를 가질 수 있습니다. 때문에 사용자가 기존에 클래스를 통해 상속을 하듯이 물려주고 싶은 메서드와 프로퍼티를 프로토타입에 정의함으로써 상속을 구현할 수 있습니다. 상속에 관한 자세한 내용은 따로 포스팅 하도록 하겠습니다.