1.function 형태, function 오브젝트 생성, 오브젝트 저장, 생각의 전환
function 형태
•
빌트인(Built-in)Function 오브젝트
◦
Function.prototype.call()
•
function 오브젝트
◦
function book(){...}
◦
var book = function(){...}
◦
이것들도 다 인스턴스이지만 new 연산자로 생성한 인스턴스와 구분하기위해 function 오브젝트라 표기합니다.
•
function 인스턴스
◦
new Book() 처럼 new연산자를 사용하여 Book.prototype에 연결된 메소드로 생성
function 오브젝트 생성
•
var book = function(){...};
•
엔진이 function 키워드를 만나면 빌트인 Function 오브젝트의 prototype에 연결된 메소드로 function 오브젝트를 생성합니다.
•
생성한 오브젝트를 book변수에 할당합니다.
•
book()형태로 호출합니다.
◦
function 오브젝트이므로 호출할 수 있습니다.
•
오브젝트 저장
•
함수를 호출하려면 생성한 function 오브젝트를 저장해야 합니다.
•
function 오브젝트의 저장 형태는 key/value 형태.
◦
{name: value} 형태로 저장
◦
{book: 생성한 function 오브젝트} 형태
•
함수를 호출하면
1.
저장된 오브젝트에서 함수 이름(book)으로 검색
2.
value 값을 구하고
3.
value가 function 오브젝트이면 호출
생각의 전환
•
함수가 호출되면 엔진은 함수의 변수와 함수를 {name: value} 프로퍼티 형태로 실행 환경을 설정하고 함수 코드를 실행합니다.
•
{name: value} 프로퍼티 형태로 생각을 전환해야 JS의 아키텍처와 메커니즘을 이해하기 용이해집니다.
•
function (){} 코드를 보면 함수의 변수와 함수가 {name: value}형태로 연상되어야 합니다. (엔진 관점의 접근)
2. function 오브젝트 생성 과정, function 오브젝트 구조
function 오브젝트 생성 과정
1.
function sports(){...}형태에서 function 키워드를 만나게 됩니다.
2.
오브젝트를 생성하고 저장합니다.
a.
{ sports: {...} }
b.
sports는 function 오브젝트 이름입니다.
c.
오브젝트{...}에 프로퍼티가 없는 상태입니다.
이제부터 빈 오브젝트를 채웁니다.
sports 오브젝트 형태
var sports = function(){}을 전개하연 우측과 같은 설정들이 나열됩니다.
-sports
--arguments:null
--caller: null
--length: 0
--name: "sports"
--prototype:
---constructor: sports
---__proto__: Object.prototype
--__proto__: Function.prototype
Plain Text
복사
구조는 위와 같습니다. prototype 안의 __proto__는 빌트인 오브젝트 Object의 prototype을 담고있고, prototype과 동격인 외부 __proto__에서는 빌트인 Function 오브젝트의 프로토타입을 담고 있습니다.
3. sports 오브젝트에 prototype 오브젝트 첨부
4. prototype에 constructor 프로퍼티 첨부
•
prototype.constructor가 sports 오브젝트 참조
5. prototype에 __proto__오브젝트 첨부
•
ES5스펙에 __proto__가 기술되어 있지 않고 ES6에 기술되어 있습니다.
•
엔진이 사용한다는 뉘앙스로 정의되어있습니다.
•
ES5 기준에서 볼땐 표준이 아니지만 2000년대 초부터 파이어폭스에서 사용했기에
그대로 사용합니다.
sports = {
prototype: {
constructor: sports
__proto__: {}
}
}
Plain Text
복사
6. 빌트인 Object.prototype의 메소드로
•
Object인스턴스를 생성하여 prototype.__proto__에 첨부합니다.
7. sports 오브젝트에 __proto__ 오브젝트 첨부
•
sports.__proto__ 구조가 됩니다.
8. 빌트인 Function.prototype의 메소드로 function인스턴스를 생성하여 sports.__proto__에 첨부합니다.
9. sports오브젝트 프로퍼티에 초기값 설정을 해줍니다.
•
arguments, caller, length, name 프로퍼티
sports = {
arguments: {},
caller: {},
length: 0,
name: "sports",
prototype: {
constructor: sports
__proto__: Object.prototype
}
__proto__: Function.prototype
}
Plain Text
복사
function 오브젝트 구조
function 오브젝트에 prototype이 있으며 constructor가 연결됩니다. 그리고 __proto__가 연결되어 있으며 Object 인스턴스가 연결됩니다.
function 오브젝트에 __proto__가 있으며 Function 인스턴스가 연결됩니다. Array이면 Array인스턴스가 연결되고 String이면 String 인스턴스가 연결됩니다.
3. 함수 실행 환경 인식, 함수 실행 환경 저장, 내부 프로퍼티
함수 실행 환경 인식
1. 함수 실행 환경 인식이 필요한 이유
•
함수가 호출되었을 때 실행 될 환경을 알아야 실행 환경에 맞추어 실행할 수 있기 때문입니다.
2. 실행 환경 설정 시점
•
function 키워드를 만나 function 오브젝트를 생성할 때
→즉, 정적으로 생성한다는 것입니다. (Lexical Environment)
3. 설정하는 것
•
실행 영역( 함수가 속한 스코프), 파라미터, 함수 코드 등
함수 실행 환경 저장
function 오브젝트를 생성하고 바로 실행하지 않기에 함수가 호출되었을 때 사용할 수 있도록 환경을 저쟝해야 합니다.
저장되는 위치는 생성한 function 오브젝트에 저장되기에 생성한 function 오브젝트를 읽으면 다른 곳 읽을 필요 없이 함수가 실행될 수 있는 환경이 설정되어 있습니다.
이렇게 생성한 function 오브젝트의 내부 프로퍼티로 인식한 환경을 설정({name:value})합니다. =
내부 프로퍼티
내부 프로퍼티란 엔진이 내부 처리에 사용하는 프로퍼티이기에 스펙 표기로 외부에서는 사용 불가합니다.
•
스펙 표기
◦
[[ ]] 형태
⇒Ex: [[Scope]]
4. 내부 프로퍼티 분류: 공통 내부 프로퍼티, 선택적 내부 프로퍼티
내부 프로퍼티
내부 프로퍼티는 공통 프로퍼티, 선택적 프로퍼티로 분류할 수 있습니다.
•
공통 프로퍼티
◦
모든 오브젝트에 공통으로 설정되는 프로퍼티로써 여기서 모든 오브젝트란 빌트인(Built-in)오브젝트로 만드는 오브젝트를 뜻합니다.
•
선택적 프로퍼티
◦
오브젝트에 따라 선택적으로 설정되는 프로퍼티를 말합니다. 해당되는 오브젝트에만 설정됩니다.
⇒Ex: Array 오브젝트에는 설정되지만 String 오브젝트에는 설정되지 않는 프로퍼티들
공통 내부 프로퍼티
•
모든 오브젝트에 설정되는 내부 프로퍼티(추가설명이 필요한 부분만)
◦
[[Prototype]] : Object또는 null을 가지며 오브젝트의 프로토타입인데, Math와 같이 Prototype이 없는 오브젝트도 있습니다.
◦
[[Class]] : 오브젝트 유형 구분으로 이것에 따라 오브젝트가 구분됩니다.
◦
[[Extensible]] : 오브젝트에 프로퍼티 추가 가능 여부
선택적 내부 프로퍼티
•
오브젝트에 따라 선택적 설정되는 내부 프로퍼티
5. 함수 정의 형태: 함수 정의, 함수 선언문, 함수 표현식
함수 정의 (Function Definition)
함수 코드가 실행될 수 있도록 JS문법에 맞게 함수를 작성하는 것
함수 정의 형태
•
함수 선언문(Function Declaration)
•
함수 표현식(Function Expression)
•
new Function(param, body) 문자열로 작성
함수 선언문
•
function getBook(title){함수 코드}
◦
function, 함수 이름, 블록{} 작성은 필수
◦
파라미터 함수 코드는 선택
•
엔진이 function 키워드를 만나면
◦
function 오브젝트를 생성하고
◦
함수 이름을 function 오브젝트 이름으로 사용
function book(one, two){
return one + ", "+ two;
};
console.log(book("JS", "DOM"));
JavaScript
복사
함수 표현식
•
var getBook = function(title){함수 코드}
◦
function 오브젝트를 생성하여 변수에 할당
◦
변수 이름이 function 오브젝트 이름
•
식별자 위치의 함수 이름은 생략 가능
◦
var name = function abc(){}에서 abc가 식별자 위치의 함수 이름
•
함수 표현식
var getBook = function (title){
return title;
};
getBook("JS책");
JavaScript
복사
•
식별자 위치의 함수 이름
var getBook = function inside(value){
if(value === 102){
return value;
};
console.log(value);
return inside(value + 1);
};
getBook(100);
JavaScript
복사
6. 엔진 해석 방법: 엔진 해석 순서, 함수 코드 작성 형태, 엔진 처리 상태
엔진 해석 순서
•
자바스크립트는 스크립팅 언어입니다.
스크립팅 언어는 작성된 코드를 위에서부터 한 줄씩 해석(환경 설정)하고 실행합니다.
하지만, 자바스크립트는 조금 다르게 해석합니다.
•
JS에서는 기준에 따라서는 중간에 있는 코드가 먼저 해석될 수도 있습니다.
◦
첫 번째, 함수 선언문을 순서대로 해석
→ function sports(){}
◦
두 번째, 표현식을 순서대로 해석
→ var value = 123;
→ var book = function (){};
함수 코드 작성 형태
1.
마지막 줄에서 book 함수를 호출합니다.
⇒ book();
2.
title 변수를 선언합니다.
⇒var title = "JS책"
3.
함수 선언문을 작성합니다.
⇒function getBook(){return title;};
4.
함수 표현식 작성
⇒var readBook = function(){}
function book(){
var title = "JS책";
function getBook(){
return title;
};
var readBook = function(){};
getBook();
};
book();
JavaScript
복사
엔진 처리 상태
1.
마지막 줄에서 book()함수를 호출하면 debugger에서 실행이 멈춥니다.
2.
title, readBook 값은 undefined이 출력될 것입니다.
3.
getBook은 function 오브젝트가 출력될 것입니다.
•
getBook이 function 오브젝트라는 것은 function getBook(){} 을 해석한 것입니다.
4.
title, readBook에 설정된 undefined도 일종의 값입니다.
이는 값이 있다는 것은 엔진이 해석했다는 것을 의미하며 해석하지 않을경우 title, readBook은 값이 표시되지 않습니다.(undefined도 안나온다는 의미)
function book(){
console.log(title);
console.log(readBook);
console.log(getBook);
debugger;
var title = "JS책";
function getBook(){
return title;
};
var readBook = function(){};
getBook();
};
book()
JavaScript
복사
7. 함수 코드 해석 순서
함수 코드 해석 순서
1.
함수 선언문 해석
•
function getBook(){};
2.
변수 초기화
•
var title = undefined;
•
var readBook = undefined;
3.
코드 실행
•
var title = "JS책";
•
var readBook = function(){};
•
getBook();
function book(){
var title = "JS책";
function getBook(){
return title;
};
var readBook = function(){};
getBook();
};
book();
JavaScript
복사
함수 선언문 해석
1.
마지막 줄에서 book()함수를 호출합니다.
2.
엔진 제어가 book함수의 첫 번째 줄로 이동합니다.
a.
이때 debugger를 실행하지 않습니다.
3.
함수(book) 안에서 위에서 아래로 내려가며 함수선언문을 찾으며 getBook이 함수 선언문이므로 function 오브젝트를 생성합니다.
4.
더 이상 함수 선언문이 없으므로 다시 함수의 첫 번째 줄로 이동합니다.
function book(){//---(2)
debugger;//---(4)
var title = "JS책";
function getBook(){//---(3)
return title;
};
var readBook = function(){};
getBook();
};
book();// --- (1)
JavaScript
복사
변수 초기화
1.
debugger를 실행하지 않습니다.
2.
var title = "JS책";
a.
title 변수에 undefined를 할당합니다.
b.
"JS"책을 할당하지 않습니다.
3.
getBook은 함수 선언문 해석에서 초기화가 되었기에 넘어갑니다.
4.
var readBook = function(){};
a.
readBook 변수에 undefined를 할당합니다.
b.
함수 표현식은 변수를 선언만 합니다.
5.
다시 함수의 첫 번째 줄로 이동합니다.
function book(){
debugger;//---(1) ---(5)
var title = "JS책";//---(2)
function getBook(){//---(3)
return title;
};
var readBook = function(){};//---(4)
getBook();
};
book();
JavaScript
복사
코드 실행
1.
debugger를 실행하며, 실행이 멈춥니다.
2.
var title = "JS책";
•
title 변수에 "JS책"을 할당합니다.
3.
function getBook(){return title}
•
실행이 아닌 선언이므로 다음줄로 이동합니다.
4.
var readBook = function(){};
•
function 오브젝트를 생성하여 readBook변수에 할당합니다.
•
readBook이 function 오브젝트가 되므로 이제 readBook함수를 호출할 수 있습니다.
5.
getBook()함수를 호출합니다.
•
지금까지와 같은 순서와 방법으로 getBook()함수의 함수와 변수를 초기화하고 코드를 실행합니다.
function book(){
debugger;//---(1)
var title = "JS책";//---(2)
function getBook(){
return title;//---(3)
};
var readBook = function(){};//---(4)
getBook();//---(5)
};
book();
JavaScript
복사
8. 호이스팅, 함수 앞에서 호출
호이스팅: 함수 앞에서 호출
•
함수 선언문은 초기화 단계에서 function 오브젝트를 생성하기에 어디서든 함수 호출이 가능합니다.
•
함수 앞에서 호출 가능 예제
var result = book();
console.log(result);
function book(){
return "호이스팅";
};//호이스팅
JavaScript
복사
⇒ 얼핏보면 첫 번째 줄에서 book() 함수를 호출하는데 book()함수는 더 아래에 정의되어있어서 위에서 아래로 내려가면서 해석을 한다는 말대로면 수행이 안되야하는데, 실제로 실행을 해보면 제대로 호이스팅 이라는 출력값을 확인할 수 있습니다.
이를 호이스팅(Hoisting) 이라하는데 용어보다는 개념으로 접근할 필요가 있습니다.
•
초기화 단계에서 값이 있을경우 초기화 하지 않습니다.
var result = book();
console.log(result);
function book(){
return "호이스팅";
};
book = function(){//---(1)
return "함수 표현식";
}
JavaScript
복사
⇒ (1): 이미 function book(){ return "호이스팅"}으로 book이라는 property name으로 선언이 되어있기 때문에 해당 함수표현식은 할당되지 않습니다. 그렇기 때문에 book()함수를 호출하면 (1) 항목의 "함수 표현식" 이라는 반환값이아닌 그 위에 함수 선언문에 설정된 "호이스팅" 이 반환됩니다.
예제
함수 표현식과 함수 선언문을 이해하기위해 4개의 코드를 실행해 결과값을 확인해봅니다.
1.
함수 선언문, 함수 호출(), 함수 선언문
function book(){
function getBook(){
return "책1";
};
console.log(getBook());
function getBook() {
return "책2";
}
};
book();
JavaScript
복사
⇒실행결과: '책2'
3. 함수 선언문, 함수 호출(), 함수 표현식
function book(){
function getBook(){
return "책1";
};
console.log(getBook());
var getBook = function () {
return "책2"
};
};
book();
JavaScript
복사
⇒실행결과: '책1'
2. 함수 표현식, 함수 호출(), 함수 표현식
function book() {
var getBook = function () {
return "책1"
};
console.log(getBook());
getBook = function () {
return "책2"
};
};
book();
JavaScript
복사
⇒실행결과: '책1'
4. 함수 표현식, 함수 호출(), 함수 선언문
function book() {
var getBook = function () {
return "책1"
};
console.log(getBook());
function getBook() {
return "책2";
}
};
book();
JavaScript
복사
⇒실행결과: '책1'