이력
드디어.. 아키텍처와 메커니즘 파트로 들어왔네요 ㅎㅎ,
이제부터는 글도 많고 내용도 조금 어렵습니다.
되게 당연한 내용들도 있지만 계속 읽어보면서 익숙해져야 될것 같아요. 끝까지 고고!
21.1 생각의 전환#
1
| var sports = function(){};
|
- 자바스크립트 엔진이 위의 코드를 해석하면 {sports: Function 오브젝트} 형태로 글로벌 오브젝트에 설정합니다. sports(); 코드를 만나면 글로벌 오브젝트에서 sports를 검색하여 value를 구하고 Function 오브젝트이므로 함수로 호출합니다. 자바스크립트 엔진은 오브젝트의 프로퍼티 값 타입에 따라 함수를 호출하거나 문자열 값을 반환합니다.
- 지금부터 이 개념으로 접근해야 합니다. 자바스크립트 엔진이 {name: value} 형태, 구조로 처리하므로 이에 맞추어 생각해야 논리가 맞습니다. function(){} 코드를 보면 {name: value} 형태의 오브젝트가 연상되어야 합니다.
- Object와 object
- 필자에게 자바스크립트 핵심이 무엇이냐고 물으면 주저하지 않고 “Object와 object"라고 대답합니다. Function 오브젝트, Number 오브젝트, Object 오브젝트와 같은 자바스크립트 네이티브 오브젝트(스펙에 명시적으로 선언되어 있음)가 대문자 Object에 속합니다. Object에서 제공하는 함수, 메소드, 프로퍼티를 사용하여 자바스크립트 코드를 작성합니다. 이 책에서 지금까지 다루었던 내용입니다.
- new sports()와 같이 new 연산자로 생성한 인스턴스가 소문자 object에 속합니다. new 연산자와 Function 오브젝트로 인스턴스를 생성하고 생성한 인스턴스에 프로퍼티를 추가하거나 삭제합니다. 지금부터 다룰 내용입니다.
21.2 아키텍처와 메커니즘 개요#
- 아키텍처의 사전적인 의미는 구조입니다. 사전적으로는 구조를 의미하지만 여기에 “목적"을 추가해야 합니다. 목적이 없는 구조는 아키텍처가 아닙니다. 사람이 살기 불편한 아파트 구조는 목적을 완전하게 달성하지 못한 것이므로 아키텍처가 잘못된 것입니다.
- 아키텍처만으로 목적을 달성할 수 없으므로 방법이 필요하며 이를 메커니즘이라고 합니다.
- 아키텍처와 메커니즘에 따라 프로그램 개발 방법, 기준 방향이 달라지므로 매우 중요합니다.
- 자바스크립트 프로그램의 목적
- 자바스크립트는 프로그래밍 언어입니다. 언어의 목적은 상대방과 소통하기 위합입니다. 자바스크립트와 소통하기 위해서는 자바스크립트 문법에 맞추어 프로그램을 작성해야 합니다. 하지만 이것은 소통하기 위한 수단이지 목적은 아닙니다. 문법은 자바스크립트가 프로그램을 해석하기 위한 기본으로, 기본을 준수하는 것만으로 목적을 달성했다고 할 수 없습니다.
- 상대방과 잘 소통하려면 상대방을 잘 알아야 하듯이, 자바스크립트의 근간을 이루는 아키텍처와 메커니즘을 이해해야 자바스크립트의 상태를 파악할 수 있으며 나가아 소통할 수 있습니다.
21.3 아키텍처와 메커니즘 키워드 리스트#
21.4 Function 오브젝트와 Function 인스턴스#
- 이 책에서는 아래 기준으로 Function 오브젝트와 Function 인스턴스를 구분하여 표기합니다.
- Function 오브젝트
- function 키워드를 인식해 빌트인 Function 오브젝트의 prototype에 연결된 프로퍼티로 새로운 오브젝트를 생성하여 반홥합니다. 생성한 오브젝트를 Function 오브젝트, sports 오브젝트, sports Function 오브젝트로 표기합니다.
- 빌트인 Function 오브젝트로 다수의 Function 오브젝트를 생성하므로 Function 인스턴스가 더 적절합니다. 그런데 new sports()로 생성한 것도 Function 인스턴스이므로 지금부터 이를 구분하기 위해 Function 오브젝트로 표기합니다.
- Function 인스턴스
- 위 문장을 수행하려면 우선 sports가 Function 오브젝트여야 합니다. new 연산자와 sports Function 오브젝트로 새로운 오브젝트를 생성하여 반환하여 반환된것이 인스턴스입니다. sports 인스턴스, sports Function 인스턴스라고 표기합니다.
21.5 Function 오브젝트 생성#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| 1. 빈 오브젝트를 생성합니다.
- {코드} function sports(){}
- {설명} 생성한 오브젝트 이름이 sports입니다. 현재는 Function 오브젝트가 아니며 오브젝트 타입이 "function"
인 빈 오브젝트입니다. 아래의 처리를 통해 빈 오브젝트를 채우게 되며 Function 오브젝트 모습이 됩니다.
2. sports 오브젝트에 prototype 오브젝트를 첨부합니다.
- {설명} sports = {prototype: {}} 형태가 됩니다.
3. prototype에 constructor 프로퍼티를 설정합니다.
- {설명} sports = {prototype: {constructor: 값}} 형태가 됩니다.
4. prototype.constructor에 sports 오브젝트의 참조값을 설정합니다.
- {설명} constructor가 sports 오브젝트의 메모리 주소를 참조합니다.
- {설명} 따라서 개발자가 독에서 sports 오브젝트의 프로퍼티를 표시할 수 있습니다.(저는 뭔말인지 모르겠습니다..)
5. prototype에 __proto__ 오브젝트를 첨부합니다.
- {설명} sports = {prototype: {constructor: 값, __proto__: {}}} 형태가 됩니다.
6. 빌트인 Object 오브젝트의 prototype에 연결된 프로퍼티로 Object 인스턴스를 생성합니다.
7. 생성한 Object 인스턴스를 prototype.__proto__에 첨부합니다.
- {설명} 이를 상속이라고 합니다.
8. sports 오브젝트에 __proto__ 오브젝트를 첨부합니다.
- {설명} sports = {prototype: {...}, __proto__: {}} 형태가 됩니다.
9. 빌트인 Function 오브젝트의 prototype에 연결된 프로퍼티로 Function 인스턴스를 생성합니다.
10. 생성한 Function 인스턴스를 sports.__proto__에 첨부합니다.
- {설명} 빌트인 Function 오브젝트의 메소드를 사용할 수 있게 됩니다.
11. sports 오브젝트 프로퍼티로 프로퍼티 이름과 초기값을 설정합니다.
- {설명} arguments, caller, length, name 프로퍼티를 설정합니다.
- {설명} sports = {arguments: null, name:"sports", prototype: {...}, __proto__: {...}} 형태가 됩니다.
|
21.7 __proto__ 오브젝트#
- __proto__는 프로퍼티를 감싸기 위한 오브젝트로 별 다른 기능은 없습니다. 만약 __proto__안에 프로퍼티를 작성하지 않고 풀어서 작성하면 한 단계 위에 놓이게 되므로 오브젝트 프로퍼티와 같은 단계에 놓이게 되어 중복문제가 발생하게 됩니다. 이를 방지하기 위함입니다.
1
2
| js.log(sports.__proto__ === Function.prototype);
//true
|
- 자바스크립트 엔진이 function sports(){}; 문장을 만나면 빌트인 Function 오브젝트의 prototype에 연결된 프로퍼티로 새로운 Function 오브젝트를 생성합니다. 이 때 생성한 Function 오브젝트의 프로퍼티를 구분하여 sports Function 오브젝트에 첨부해야 하는 할 곳이 없으므로 __proto__를 만들어 첨부하고 __proto__에 생성한 Function 오브젝트의 프로퍼티를 첨부합니다.
- 쉽게 말하기 위해 첨부한다고 했지만, 참조하는 것입니다. 그래서 === 비교시 true가 나오는 것입니다.
- __proto__에 표시된 length 프로퍼티는 빌트인 Function 오브젝트 프로퍼티이며 arguments, caller, name 프로퍼티는 빌트인 Function 오브젝트 프로퍼티가 아닙니다. 그런데도 __proto__에 표시된 것은 Function 오브젝트를 만들 때 디폴트로 설정하기 때문입니다.
- 빌트인 Function 오브젝트의 prototype에 연결된 프로퍼티로 Function 오브젝트에 생성하여 __proto__를 첨부하는 것은, 빌트인 Function 오브젝트에서 제공하는 메소드를 사용하기 위함입니다. 첨부하지 않으면 apply, bind, call 메소드를 호출할 수 없습니다.
1
| js.log(sports.__proto__.__proto__ === Object.prototype);
|
- 자바스크립트 엔진이 렌더링될 때 빌트인 Function 오브젝트의 __proto__에 빌트인 Object 오브젝트의 prototype에 연결된 프로퍼티롤 인스턴스를 생성하여 설정합니다. 따라서 Function 오브젝트를 생성하면 __proto__도 같이 첨부됩니다. 이처럼 자바스크립트의 모든 네이티브 오브젝트에 빌트인 Object 오브젝트의 prototype으로 생성한 Object 인스턴스가 첨부됩니다.
21.8 공통 내부 프로퍼티#
- 자바스크립트 엔진이 Function 오브젝트를 생성하는 목적은 Function 오브젝트이어야 호출할 수 있으며 실행할 수 있기 때문입니다.
- 함수를 실행하려면 실행환경(코드 등)을 인식할 수 있어야하고, 그렇다면 어딘가에 저장하고 있어야합니다. 실행환경은 생성하는 Function 오브젝트에 저장합니다. 다른 곳에 저장한다면 찾고 가져오는 과정이 추가되므로 비효율적입니다.
- 자바스크립트 엔진이 인식할 수 있는 프로퍼티를 내부 프로퍼티라고 합니다. 스펙상의 사양으로 외부에서 접근할 수 없으며 내부적으로 어떻게 처리하는지 알 수 없습니다. 외부에서 접근할 수 없는데도 내부 프로퍼티를 살펴보는 것은 자바스크립트를 근본적으로 접근하기 위해서 입니다.
- 내부 프로퍼티를 [[scope]]와 같이 대괄호[] 두개로 표기하고 있습니다.
- 내부 프로퍼티는 모든 오브젝트에 설정되는 공통 프로퍼티와 오브젝트에 따라 선택적으로 설정되는 선택적 프로퍼티로 나눕니다.
프로퍼티 이름 | 값 형태 | 개요 |
---|
[[Prototype]] | Object 또는 Null | 오브젝트의 Prototype |
[[Class]] | String | 오브젝트 유형 구분 |
[[Extensible]] | Boolean | 오브젝트에 프로퍼티 추가 가능 여부 |
[[Get]] | any, **참조1 | 이름을 가진 프로퍼티 값을 반환 |
[[GetOwnProperty]] | 프로퍼티 디스크립트 또는 Undefined | 오브젝트 소유의 프로퍼티 디스크립터 속성 반환 |
[[GetProperty]] | 프로퍼티 디스크립트 또는 Undefined | 오브젝트의 프로퍼티 디스크립터 속성 반환 |
[[Put]] | | 프로퍼티 이름에 값 설정 |
[[CanPut]] | Boolean | |
[[HasProperty]] | Boolean | 프로퍼티의 존재 여부 반환 |
[[Delete]] | Boolean | 오브젝트에서 프로퍼티 이름 삭제 |
[[DefaultValue]] | 프리미티브 값 | 오브젝트의 프리미티브 값 반환 |
[[DefinedOwnProperty]] | Boolean | 오브젝트에 프로퍼티 추가, 속성 변경 |
- 내부 프로퍼티는 Function 오브젝트를 생성할 때 설정됩니다.
- Function 오브젝트 중심으로 설명하고 있지만 Function 오브젝트뿐만 아니라 자바스크립트의 모든 오브젝트가 대상입니다.
- [[Prototype]]
- 모든 오브젝트에 prototype에 존재한다는 것을 의미합니다.
- prototype에 연결된 프로퍼티는 사람이 사용하고 [[Prototype]]은 자바스크립트 엔진이 사용합니다. 따라서 prototype과 [[Prototype]]이 같아야 합니다.
- new 오브젝트로 생성한 인스턴스는 오브젝트의 prototype에 연결된 프로퍼티를 공유합니다. 오브젝트의 prototype에 연결된 프로퍼티를 변경(추가, 삭제, 값 변경)하면, [[Prototype]]에 반영되며 모든 인스턴스에서 변경됩니다.
- [[Class]]
- 오브젝트 타입을 구분합니다. 엔진이 Function 키워드를 만나 Function 오브젝트를 생성하는 것이 아니라 {name: value} 형태의 오브젝트를 생성하고, [[Class]] 프로퍼티에 “Function"을 설정하여 Function 설정하여 Function 오브젝트가 되는 것 입니다.
- Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String을 설정하여 오브젝트를 구분합니다.
- [[Prototype]]과 [[Class]] 이외 내부 프로퍼티
- 다른 내부 프로퍼티는 20장에서 프로퍼티 이름을 사용하지 않았지만 메소드로 기능을 다루었습니다. 즉 Object 오브젝트와 관련된 프로퍼티입니다. 모든 오브젝트에서 Object 오브젝트를 상속받으므로 Object 오브젝트 관련 프로퍼티가 필요하며 Function 오브젝트 또한 오브젝트이므로 오브젝트를 제어하기 위한 프로퍼티가 필요합니다.
- 오브젝트에 따라 내부 프로퍼티 이름이 같지만 처리 기능이 다를 때는 해당하는 오브젝트에 대체 처리 방법을 기술하고 있습니다(예, Function 오브젝트의 [[Get]] 프로퍼티)
21.9 선택적 내부 프로퍼티#
내부 프로퍼티 | 값 형태 | 개요 |
---|
[[PrimitiveValue]] | 프리미티브 값 | Boolean, Date, Number, String 오브젝트에서 사용 |
[[Constuctor]] | Object | Function 오브젝트의 메모리 주소 참조 |
[[Call]] | any | 함수 호출 |
[[HasInstance]] | Boolean | 오브젝트에 의해 생성한 인스턴스 여부 반환 |
[[Scope]] | 렉시컬 환경 | Function 오브젝트의 렉시컬 환경 |
[[FormalParameters]] | 문자열 리스트 | 호출된 함수의 파라미터 이름 리스트 |
[[Code]] | 자바스크립트 코드 | 함수에 작성된 자바스크립트 코드가 설정되며 함수가 호출되었을 때 사용 |
[[TargetFunction]] | Object | bind 메소드로 생성된 타깃 Function 오브젝트 |
[[BoundThis]] | any | bind 메소드로 생성된 Function 오브젝트에 바인딩된 this |
[[BoundArguments]] | 리스트 | bind 메소드로 생성된 Function 오브젝트에 바인딩된 파라미터 리스트 |
[[Match]] | 매치 결과 | 정규 표현식 매치 결과 |
[[ParameterMap]] | Object | 아규먼트 오브젝트의 호출된 함수 파라미터 매핑 |
- [[PrimitiveValue]]
- Boolean, Date, Number, String 인스턴스를 생성할 때 설정된다.
- 해당 인스턴스들은 출력하면 [[PrimitiveValue]]를 반환하기 때문에 값이 반환된다.
- [[Constructor]]
- 생성하는 오브젝트의 참조값이 설정 된다. 따라서 [[Constructor]]와 생성하는 오브젝트가 같습니다.
- [[HasInstance]]
- 오브젝트로 생성한 인스턴스 여부를 Boolean 값으로 반환하는데 사용합니다.
- obj instanceof sports 와 같이 작성하면 이때 사용됩니다.
- [[FormalParameters]]
- 함수의 파라미터 이름이 설정됩니다.
- [[Code]]
- 함수에 작성한 자바스크립트 코드가 설정된다.
- [[TargetFunction]], [[BoundThis]], [[BoundArguments]]
- bind 메소드에 설정합니다.
1
| var bindObj = sports().bind();
|
- 메소드를 호출하면 바로 실행되지만 bind 메소드는 바로 실행되지 않습니다. sports 메소드를 바인딩한 오브젝트를 생성하여 반환합니다. bindObj의 [[TargetFunction]], [[BoundThis]], [[BoundArguments]]에 sports 오브젝트 실행 환경을 설정합니다. 이 시점에서 처리가 종료되어 흐름이 끊어집니다. bindObj()를 호출하면 내부 프로퍼티 값을 사용하여 sports 오브젝트를 실행합니다.
- [[Match]]
- 정규표현식을 사용한 match 결과를 저장
- [[ParameterMap]]
- [[FormalParameters]]에 설정된 파라미터이름을 사용하여 값을 할당할 때 [[ParameterMap]]을 사용합니다.
21.10 함수 선언문과 함수 표현식#
1
| var sports = function(){};
|
21.11 자바스크립트 엔진 해석#
- 자바스크립트가 스크립팅 언어이므로 작성된 자바스크립트 코드를 위에서 아래로 한 줄씩 해석한다고 생각할 수 있습니다. 하지만 이는 스크립팅 언어의 일반적인 개념으로 자바스크립트는 함수 형태에 따라 순서를 바꾸어 해석합니다.
- 엔진은 아래의 순서대로 코드를 실행합니다.
1
2
3
| 1) 함수 선언문 해석
2) 변수 초기화
3) 자바스크립트 코드 실행
|
21.12 함수 앞에서 호출#
1
2
3
4
5
6
7
8
9
| function sports(){
soccer();
function soccer(){
js.log('축구')
}
}
sports();
//"축구" 가 출력됨
|
- 위의 코드에서 soccer()이 아래에 선언됐지만 호출이 가능한 것은 엔진의 해석순서에 의해 선언문을 먼저 해석했기 때문입니다.
- (호이스팅이라고 하는데 let, const 키워드는 해당되지 않으므로 유의필요)
21.13 함수 오버라이딩#
21.14 함수 표현식 오버라이딩#
21.15 함수 선언문, 함수 표현식 오버라이딩#
21.16 함수 표현식, 함수 선언문 오버라이딩#
- 위에서는 2개의 함수를 선언문, 표현식으로 바꿔가며 오버라이딩이 되고 안되고를 설명하고 있습니다. 적기에는 너무 많아서 알아둬야할 내용만 적겠습니다.
- 렉시컬 환경에 Function 오브젝트가 저장된다.
- 엔진해석의 2단계 변수초기화 단계에서는 변수에 초기값을 설정하기 전에 렉시컬 환경에 확인 후 존재하면 초기값을 설정하기 않음, 3단계 실행 단계에서는 존재하더라도 설정함입니다.