실행 컨텍스트와 클로저

실행 컨텍스트 개념

실행 가능한 자바스크립트 코드 블록(대부분 함수)가 실행 되는 환경 . ECMAScript에ㅓ는 실행 컨텍스트가 형성되는 경우를 세가지로 규정하고 있다.
1. 전역 코드
2. eval() 함수로 실행되는 코드
3. 함수안의 코드를 실행할 경우
현재 실행되는 컨텍스트에서 이 컨텍스트와 관련 없는 실행 코드가 실행되면, 새로운 컨텍스트가 생성되어 스택에 들어가고 제어권이 그 컨텍스트로 이동한다.

실행 컨텍스트 생성 과정

function execute(param1 , param2) {
var a = 1, b = 2;
function func(){
return a+b;
}
return param1 + param2 + func();
}
 
자바스크립트에서는 함수를 실행하여 실행 컨텍스트가 생성되면 자바스크립트 엔진은 다음과 같은 정해진 순서대로 실행한다.
 

1.활성객체 생성

실행 컨텍스트가 생성되면 자바스크립트 엔진은 해당 컨텍스트에서 실행에 필요한 여러 가지 정보를 담을 객체를 생성하는데, 이를 활성 객체라고 한다. 이 객체에 앞으로 사용하게 될 매개변수나 사용자가 정의한 변수 및 객체를 저장하고 , 새로 만들어진 컨텍스트로 접근(엔진 내부에서) 가능하게 되어 있다.


2.arguments 객체 생성

앞서 만들어진 활성 객체는 argument 프로퍼티로 이 arguments 객체를 참조한다.

3.스코프 정보 생성

현재 컨텍스트의 유효 범위를 나타내는 ㅡ코프 정보를 생성한다. 이 스코프 정보는 현재 실행 중인 실행 컨텍스트 안에서 연결 리스트와 유사한 형식으로 만들어 진다. 이 리스트에서 찾지 못한 변수는 결국 정의되지 않는 변수에 접근하는 것으로 판단하여 에러를 검출한다. 이 리스트를 스코프 체인이라고 하며, [scope] 프로퍼티로 참조된다. 현재 생성된 활성 객체가 스코프 체인의 최상단에 추가된다.

4.변수 생성

실행 컨텍스트 내부에서 사용되는 지역 변수의 생성이 이루어진다. execute() 함수 안에 정의 된 변수 a,b 와 함수 func가 생성된다. 여기서 주의할 점은 이 과정에서는 변수나 내부 함수를 단지 메모리에 생성만 하고 , 초기화는 각 변수나 함수에 해당하는 표현식이 실행되기 전까지는 이루어지지 않는다는 점이다.

5.this 바인딩

마지막 단계에서는 this 키워드를 사용하는 값이 할당된다. this는 함수 호출방식에 따라 다르게 바인딩 된다.

6.코드 실행

이렇게 하나의 실행 컨텍스트가 생성되고, 변수 객체가 만들어진 후에, 코드에 있는 여러 가지 표현식 실행이 이루어진다. 이렇게 실행되면서 변수의 초기화 및 연산, 또 다른 함수 실행 등이 이루어진다.



스코프 체인

자바를 예로 들 경우 { } 안의 변수를 선언하고 , { } 안의 코드실행을 마치면 { } 안의 변수들은 사라져 버린다. 하지만 자바스크립트에서는 오직 함수만이 유효 범위의 한 단위가 된다. 이 유효범위를 나타내는 스코프가 [scope] 프로퍼티로 각 함수 객체 내에서 연결리스트 형식으로 관리하는데 이를 스코프 체인이라고 한다. 실행 컨텍스트의 변수 객체가 구성요소인 리스트와 같다.

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

전역 실행 컨텍스트의 스코프 체인

var var1 = 1;
var var2 = 2;
console.log(var1);
console.log(var2);


위의 코드는 전역 코드이다. 이 코드를 실행하면 먼저 전역 실행 컨텍스트가 생성되고, 변수객체가 만들어진다. 이 변수 객체의 스코프 체인은 어떻게될까..? 현재 전역 실행 컨텍스트 단 하나만 실행되고 있어 참조할 상위 컨텍스트가 없다. 자신이 최상위에 위치하는 변수 객체인 것이다. 따라서, 이 변수 객체의 스코프 체인은 자기 자신만을 가진다. 변수 객체가 곧 전역 객체가 되는 것이다.


함수를 호출한 경우 생성되는 실행 컨텍스트의 스코프 체인

ex1)
var value = "value1";
function printFunc(){
var value = "value2";

function printValue(){
return value;
}

console.log(printValue());
}

위의 예제의 결과는 어떻게 될까..?
1.전역객체에서 printFunc 실행 컨텍스트를 생성하고 printFunc실행 컨텍스트는 전역객체의 스코프체인 위에 새로운 변수객체를 추가한다.
[printFunc 변수객체 - 전역객체] 

2.printFunc 함수에서는 printValue함수를 정의하고 printValue를 실행한다. 함수를 실행하였으므로 printValue 실행 컨텍스트가 실행되며 , 새로운 변수객체가 스코프 체인에 추가된다.
[printValue 변수객체 - printFunc 변수객체 - 전역객체]

3.printValue 변수객체에는 value 변수값이 없으므로 다음 printFunc 변수객체를 참조하여 value값을 출력한다.
4. 최종 출력값은 value2이다


ex2)

var value = "value1";


function printValue(){

return value;

}


function printFunc(func) {

var value = "value2";

console.log(func());

}


printFunc(printValue)

위의 예제의 출력값은 어떻게 될까..?

1. 전역객체에서 printValue 와 printFunc 함수를 정의한 뒤 printFunc를 실행할 때 printValue함수의 참조값을 전달하였다. printFunc함수가 실행되었으므로 printFunc실행 컨텍스트가 실행되며 , 새로운 변수객체가 스코프체인에 추가 된다.

[printFunc 변수객체 - 전역객체 ]


2.printFunc 함수에서는 전달받은 printValue함수를 실행시키므로 printValue실행 컨텍스트가 실행되며 새로운 변수객체를 기존 스코프체인 최상단에 추가한다. 그렇다면 printValue가 참조하는 스코프 체인은 어떤 상태일까? [ printValue - printFunc - 전역객체 ] 라고 생각할 수 있겠지만 [ printValue - 전역객체]가 옳다. 각 함수 객체가 처음 생성될 당시 실행 컨텍스트가 무엇인지 생각해본다면 , printValue는 전역객체 스코프에서 생성되었으므로 전역객체 상단에 변수객체를 추가한다.


3.최종출력값은 value1이다.


글로 표현하기 어려운 예제인것 같다.. 중요한 것은 스코프체인을 추가할 때 [기존 스코프체인] 에 현재 변수객체를 추가하는 것인데 , [기존 스코프체인] 이란 함수가 정의될 때 위치인 것을 생각해야하는 것 같다.




클로저

이미 생명 주기가 끝난 외부 함수의 변수를 참조하는 함수를 클로저라고 한다. 클로저로 참조되는 외부 함수의 변수를 자유 변수라고 한다.


function outerFunc(arg1, arg2){
var local = 8;
function innerFunc(innerArg){
console.log( (arg1 + arg2) / (innerArg + local)  );
}
return innerFunc;
}

var exam1 = outerFunc(2,4);
exam1(2);

이때 outerFunc가 실행되면서 생성되는 변수 객체가 스코프 체인에 들어가게 되고, 이 스코프 체인은 innerFunc의 스코프 체인으로 참조된다. 즉 outerFunc() 함수가 종료되었지만, 여전히 내부 함수(innerFunc()) 의 [scope] 으로 참조되므로 가비지 컬렉션의 대상이 되지 않고 여전히 접근 가능하게 살아있다.



함수와 프로토타입 체이닝

함수정의

자바스크립트에서는 함수를 생성하는 방법은 3가지가 있다. 함수 선언문 , 함수 표현식 , Function() 생성자 함수 방법이 있다.

함수 선언문 방식

함수 선언문 방식으로 정의된 함수의 경우는 반드시 함수명이 정의되어 있어야 한다.
function add( a , b) {
return a+b;
}

함수 표현식 방식

자바스크립트에서는 함수도 하나의 값처럼 취급된다. 따라서 함수도 숫자나 문자열처럼 변수에 할당하는 것이 가능하다. 생성된 함수를 변수에 할당하여 함수를 생성하는 것을 함수 표현식이라고 한다. 함수표현식에서 함수이름은 선택이지만 , 함수이름을 사용하면 함수 내부에서 재귀함수 처리가 있다.


var factorialVar = function factorial(n) {

if ( n == 1 )

return 1;

return n * factorial(n-1) ;


하지만 책을보면서 이해가 안된 부분이 있는데 return n*facitoral(n-1) 대신에 n * factorialVar(n-1)을 해도 재귀호출이 되는데 굳이 저렇게 해야 하는 가 싶음.. 혹시 아시는 분이 계시다면 알려주신다면 베리베리 감사할듯합니다 ㅎ..


Function() 생성자 함수를 이용한 방식

일반적으로 자주 사용되지 않으므로 간단히 알아보도록 하겠다..
var add = new Function('x','y','return x+y') ;

함수 호이스팅

함수 선언문 형태로 정의한 함수의 유효 범위는 코드의 맨 처음부터 시작한다는 것이 함수 호이스팅이다. 이러한 함수 호이스팅은 함수를 사용하기 전에 반드시 선언해야 한다는 규칙을 무시하므로 코드의 구조를 엉성하게 만들 수도 있다고 지적하며, 함수 표현식 사용을 권장하고 있다.

add(2,3) // 5  --> 함수 호이스팅때문에 함수를 정의하기도 전에 호출했지만 에러가 발생하지 않음.
function add(a,b){
return a+b;
}
add(3,4) // 7


함수 객체

자바스크립트에서는 함수도 객체다

자바스크립트에서는 함수도 객체다. 즉 함수의 기본 기능인 코드 실행뿐만 아니라, 함수 자체가 일반 객체처럼 프로퍼티들을 가질 수 있다는 점이다.

function add(x,y){

return x+y

}


add.result = add(2,3);

add.status = "ok";


console.log(add.result) // 5

console.log(add.status) // ok

자바스크립트에서는 함수도 값으로 취급된다.

자바스크립트에서는 함수도 객체 이므로 , 이는 함수도 일반 객체처럼 취급될 수 있다는 것이다. 때문에 자바스크립트는 다음과 같은 동작이 가능하다.
1.리터럴에 의한 생성
2.변수나 배열의 요소,객체의 프로퍼티 등에 할당
3.함수의 인자로 전달가능
4.함수의 리턴값으로 리턴 가능
5.동적으로 프로퍼티를 생성 및 할당 가능
위와 같은 특징을 가지는 객체를 일급 객체라고 부르며 , 자바스크립트의 함수는 일급 객체이다.

함수 객체의 기본 프로퍼티

자바스크립트 함수 역시 객체지만 , 일반 객체와는 다르게 추가로 함수 객체만의 표준 프로퍼티가 존재한다.
ECMAScript 명세서에서는 모든 함수가 length와 prototype 프로퍼티를 가져야 한다고 기술하고 있다. 이에 대한 설명은 좀 더 뒤에서 설명하도록 하고,
함수의 name 프로퍼티는 함수의 이름 , caller 프로퍼티는 자신을 호출한 함수를 , arguments 프로퍼티는 함수를 호출할 때 전달 된 인자값을 나타낸다.

 함수 객체의 부모 역할을 하는 프로토타입 객체를 Funtion.prototype 객체라고 명명하고 있으며 , 이것 역시 함수 객체이다.  Function.Prototype역시 함수라면 proto 프로퍼티를 자기 자신을 참조하는 것인가? 생각할 수 있지만 ECMAScript 명세서에서는 Function.prototype의 proto는 예외적으로 Object로 한다고 기술되어 있다.

 length 프로퍼티

함수 객체의 length 프로퍼티는 모든 함수가 가져야하는 프로퍼티이며 , 함수가 정상실행 될 때 기대되는 인자의 개수를 나타낸다. ( 함수에 정의한 인자갯수)

prototype 프로퍼티

모든 함수가 가져야 하는 프로퍼티이며 , 프로토타입 객체를 가리킨다. 앞 서 설명하였던 객체의 [[Prototype]]과 프로토타입을 가리킨다는 공통점은 있지만 관점의 차이가 있다.
 [[Prototype]] 은 객체 입장에서 자신의 부모 역할을 하는 프로토타입객체를 가리키지만 함수의 prototype 프로퍼티는 함수 자신이 생성자함수로 역할을 할 때 생성되는 객체의 부모 역할을 하는 프로토타입 객체를 가리킨다. 
 prototype 프로퍼티는 함수가 생성 될 때 만들어지며, 다음 그림과 같이 단지 constructor 프로퍼티 하나만 있는 객체를 가리킨다. 



함수의 다양한 형태

콜백함수

콜백함수는 코드를 통해 명시적으로 호출하는 함수가 아니라, 개발자는 단지 함수를 등록하기만 하고, 어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 시스템에서 호출되는 함수를 말한다. 대표적인 예로는 자바스크립트에서의 이벤트 핸들러이다. 
window.onload = function() { alert("load"} } 라는 콜백함수를 등록해 놓으면 document가 로딩완료되면 load라는 팝업이 뜬다.

즉시 실행함수

함수를 정의함과 동시에 실행되는 함수를 즉시실행함수라고 한다. 
( function(num) { alert(num) ; } )(10) ; 
이라는 즉시실행 함수를 정의하면 10이라는 숫자가 팝업으로 뜬다.
 이렇게 함수가 선언되자마자 실행되게 만든 즉시 실행 함수의 경우, 같은 함수를 다시 호출할 수 없다. 따라서 즉시 실행 함수의 이러한 특징을 이용한다면 최초 한 번의 실행만을 필요로 하는 초기화 코드 부분 등에 사용할 수 있다. 보통 라이브러리 코드들은 즉시실행함수 형태로 감싸진 형태이다.
 왜 즉시실행 함수 형태로 라이브러리를 지원할까? 그 이유는 변수 유효 범위특성 떄문인데 , 자바스크립트에서는 함수 유효 범위를 지원한다. 따라서 라이브러리 함수들을 즉시실행함수 내부에 정의를 하게 되면 전역스페이스를 더럽히지 않고 , 다른 라이브러리들과의 이름충돌을 피할 수 있기 때문이다.

내부함수

함수 내부에 정의된 함수를 내부 함수라고 부른다. 내부 함수는 자바스크립트의 기능을 보다 강력하게 해주는 클로저를 생성하거나 부모 함수 코드에서 외부에서으 ㅣ접근을 막고 독립적인 헬퍼 함수를 구현하는 용도로 사용한다. 
 내부함서에서는 자신을 둘러싼 부모 함수의 접근이 가능하며 , 그 이유는 자바스크립트의 스코프 체이닝 때문이다. 뒤에서 자세히 설명하도록 하겠다. 또한 내부함수는 일반적으로 자신이 정의된 부모 함수 내에서만 호출이 가능하다. 
 하지만 함수 외부에서도 특정 함수 스코프 안에 선언된 내부 함수를 호출할 수 있다. 가령 부모 함수 내부에서 내부 함수를 외부로 리턴하면, 부모 함수밖에서도 내부 함수를 호출하는 것이 가능하다. 이와 같이 실행이 끝난 부모 함수 스코프의 변수를 참조하는 변수를 클로저라고 한다.

함수 호출과 this

argument객체

자바스크립트에서는 함수를 호출할 때 함수 형식에 맞춰 인자를 넘기지 않더라도 에러가 발생하지 않는다. 이러한 특성 때문에 함수 코드를 작성할 때, 런타임 시에 호출된 인자의 개수를 확인하고 이에 따라 동작을 다르게 해줘야 할 경우가 있다. 이를 가능케 하는 게 바로 arguments 객체다. 
 arguments객체는 함수를 호출할 때 넘긴 인자들이 배열 형태로 저장 된 객체를 말한다. 이 객체는 유사배열객체이다. 


함수 호출과 this 바인딩

자바스크립트에서는 함수를 호출할 때 기존 매개변수로 전달되는 인자값에 더해, 앞서 설명한 argument 객체 및 this 인자가 함수 내부로 암묵적으로 전달된다. 자바스크립트의 여러 가지 함수가 호출되는 방식에 따라 this 바인딩이 다르다.


객체의 메서드를 호출할 때 this 바인딩

메서드 내부 코드에서 사용된 this는 해당 메서드를 호출한 객체로 바인딩 된다.

함수를 호출할 때 this 바인딩

함수를 호출할 때 해당 함수 내부 코드에서 사용된 this는 전역 객체에 바인딩된다. 브라우저에서 자바스크립트를 실행하는 경우 전역 객체는 window객체가 된다. 

생성자 함수를 호출할 때 this 바인딩

기존함수에 new 연산자를 붙여서 호출하면 해당 함수는 생성자 함수로 동작한다. 이는 반대로 생각하면 일반 함수에 new를 붙여 호출하면 원치 않는 생성자 함수처럼 동작할 수 있다. 

동작방식
1. 빈 객체 생성 및 this 바인딩.
빈객체를 생성 한 뒤 this를 빈 객체로 바인딩한다. 엄밀히 말하자면 빈 객체는 아니며 , 생성자 함수가 생성한 빈 객체는 자신을 생성한 생성자 함수의 prototype프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정한다.
2. this를 통한 프로퍼티 생성
this를 빈 객체로 바인딩하고 , 생성 된 객체에 프로퍼티를 설정한다.
3.생성 된 객체 리턴.
리턴문이 없을 경우 , 새로 생성 된 객체가 리턴되며 , 임의의 객체를 리턴할 경우 임의의 객체라 리턴된다. 기본형을 리턴하여도 this로 설정된 빈 객체가 리턴도니다.

객체 리터럴 방식과 생성자 함수를 통한 객체생성 방식의 차이

1. 객체 리터럴 방식으로 생성된 객체는 같은 형태의 객체를 재 생성 할 수 없지만 , 생성자 함수로 생성 된 객체는 같은 형태의 객체를 재생성할 수 있다.
2. 프로토 타입 객체가 다르다. 객체리터럴 방식으로 생성 된 객체의 프로토타입은 Object.prototype을 가리키며 , 생성자 함수로 생성 된 객체는 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정한다. 

call 과 apply 메서드를 이용한 명시적인 this 바인딩.

자바스크립트는 이러한 내부적인 this 바인딩 이외에도 this를 특정 객체에 apply , call 메서드를 이용하여 명시적으로 바인딩 시키는 방법이 있다.. 
call과 appley는 기능자체는 동일하며 , 호출하는 방법에 차이가 있다.
 apply 메서드는 첫 번째 인자에 바인딩 시킬 객체를 전달하고 , 두 번째 인자에는 함수에 전달할 매개변수를 배열 형태로 전달한다. call은 apply와 달리 매개변수를 배열형태가 아닌 개별로 전달한다. 

함수리턴

1. 일반 함수나 메서드는 리턴값을 지정하지 않을 경우, undefined 값이 리턴된다.
2.생성자 함수에서 리턴값을 지정하지 않을 경우 생성 된 객체가 리턴된다.

프로토타입 체이닝

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

객체  리터럴 방식으로 생성된 객체의 프로토타입 체이닝

객체 리터럴로 생성한 객체는 Object() 라는 내장 생성자 함수로 생성된 것이다. Object() 라는 생성자 함수도 함수 객체이므로 prototype이라는 프로퍼티 속성이 있다. 따라서 앞선 규칙에 따라 객체 리터럴로 방식으로 생성된 객체는 Object.prototype을 프로토타입 객체로 연결한다.

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


생성자 함수로 생성된 객체의 프로토타입 체이닝

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


자바스크립트 데이터 타입과 연산자

자바스크립트의 값들은 크게 기본 타입과 참조 타입으로 나뉜다.

자바스크립트 기본 타입

자바스크립트에서 기본타입( 그 자체가 값을 나타냄) 은 숫자 , 문자열 , boolean 과 null , undefined 타입이 있다. 자바스크립트는 느슨한 타입 체크 언어다. 따라서 변수에 어떤 형태의 데이터를 저장하느냐에 따라 해당 변수의 타입이 결정된다.

숫자

자바스크립트에서는 모든 숫자를 64비트 부동 소수점 형태로 저장. 나누기 연산에 주의해야함 . 소수 부분을 버린 정수 부분만을 구하고 싶다면 Math.floor() 메서드를 사용하면 된다.

문자열

자바스크립트에서는 문자하나만을 위한 char형과 같은 타입은 존재하지 않으므로 길이가 1인 문자열 형태로 문자를 표현한다.

한번 정의 된 문자열은 변하지 않는다. 


var str = "test"

str[0] = "T" ;

console.log(str) // test 출력


예제와 같이 한번 정의된 문자열은 읽기만 가능하지 수정은 불가능하다.

불린 값

자바스크립트는 true와 false값을 나타내는 불린 타입을 가진다.

null과 undefined

이 두 타입은 모두 값이 비어있음을 나타낸다. 자바스크립트 환경 내에서 기본적으로 값이 할당되지 않는 변수는 undefined 타입이며 그 값 역시 undefined이다. 


var a ; // undefined 타입

console.log(a) // undefined출력.


null 타입의 변수는 개발자가 명시적으로 값이 비어있음을 나타내는 데 사용한다.

여기서 주의할 점은 null타입의 변수를 typeof로 확인해보면 object 로 출력이 된다. 때문에 값이 null인지 확인할 때에는 typeof 연산자를 사용하면 안되고

일치연산자(===)를 사용해서 값을 직접 확인해야 한다. 


자바스크립트 참조 타입(객체)

자바스크립트에서 객체는 기본타입을 제외한 모든 값이다. 객체는 단순히 " 이름 : 값 " 형태의 프로퍼티들을 저장하는 컨테이너이다.

객체 생성

자바스크립트에서 객체를 생성하는 방법은 크게 세 가지가 있다. 

1. Object() 객체 생성자 함수를 이용하는 방법

2. 객체 리터럴 ( 표기법 ) 을 이용하는 방법

3. 생성자 함수를 이용하는 방법


Object() 생성자 함수 이용

var obj = new Object() ;

객체 리터럴 방식 이용

var obj = {

name : 'troh',

age : 27

};

생성자 함수 이용

4장에서 자세히..

객체 프로퍼티 읽기/쓰기/갱신

프로퍼티에 접근하기 위해서는 마침표(.) 표기법 , 대괄호[] 표기법을 사용하면 된다. 프로퍼티가 표현식이거나( + , - 등등 포함) 예약어(var 등등..)일 경우는 대괄호 표기법만을 사용해야 한다.

for in 문과 객체 프로퍼티 출력

for in 문을 이용하면 객체에 모든 프로퍼티에 대해 루프를 수행할 수 있다.  

객체 프로퍼티 삭제

delete 연산자를 이용하여 객체의 프로퍼티를 삭제할 수 있지만 , 객체 자체를 삭제하지는 못한다.

참조 타입의 특성

객체의 모든 연산이 실제 값이 아닌 참조값으로 처리 된다. 객체를 비교할 때에도 객체의 프로퍼티를 비교하는 것이 아닌 참조값을 비교하며 , 객체 타입에 따라 함수 호출방식도 다르다. 함수를 호출할 떄 기본타입의 값을 전달할 경우 값이 복사 ( call by value ) 되어 전달되지만 참조타입의 값이 전달될 경우에는 객체의 참조값이 전달(call by reference) 된다. 

프로토타입

자바스크립트의 모든 객체는 자신의 부모 역할을 하는 객체와 연결되어 있다. 이러한 부모 객체를 프로토타입 객체 or 프로토타입 이라고한다.

ECMAScript 명세서에는 자바스크립트의 모든 객체는 자신의 프로토타입을 가리키는[[prototype]]라는 숨겨진 프로퍼티를 가진다고 설명하고 있는데 크롬 브라우저에서는 __proto__가 바로 [[prototype]]프로퍼티를 의미한다. 

배열

배열은 자바스크립트 객체의 특별한 형태다.

배열의 생성 및 요소생성

배열의 생성은 배열 리터럴( [] )을 이용하여 생성할 수 있다. 객체가 동적으로 프로퍼티를 생성할 수 있듯이 배열도 동적으로 배열 원소를 아무 인덱스 위치에나 추가할 수 있다. 
모든 배열은 length 프로퍼티를 가지는데 배열의 원소 개소를 나타내는 프로퍼티이지만 , 실제로 배열에 존재하는 원소 개수와 일치하는 것은 아니다.
var arr = [ ];
console.log(arr.length) // 0

arr[0] = 1;
arr[1] = 2;
arr[100] = 101;
console.log(arr.length) // ??
위의 예제의 length프로퍼티의 값(배열의길이)은 101이 출력되지만 실제 원소개수는 3개뿐이다.

배열과 객체

그렇다면 배열과 객체의 차이점은 무엇일까? 배열과 객체의 차이점은 크게 2가지가 있다.

1.length 프로퍼티의 존재 유무

 일반적인 객체는 length 프로퍼티가 존재하지 않지만 모든 배열은 length프로퍼티를 가지고 있다. 객체에다가 length프로퍼티를 추가한다면 어떻게 될까? 이처럼 length 프로퍼티를 가지는 객체를 유사배열객체라고 한다. 


2. 프로토타입

 객체의 프로토타입은 Object 를 가리키지만 배열의 프로토타입은 Array를 가리킨다. 그러므로 유사배열객체 일지라도 프로토타입이 다르므로 배열의 메소드를 이용할 수 없다. 뒤에 나올 apply 와 call을 이용하면 유사배열객체에서도 배열의 메소드를 이용할 수 있다.

배열의 프로퍼티 열거

배열도 프로퍼티를 추가할 수 있다. 객체의 프로퍼티 열거는 for in 문을 이용하여 열거 할 수 있다고 했는데 배열도 for in문을 이용하여 프로퍼티를 열거하면 원치않는 프로퍼티들도 함께 노출이 된다. 따라서 배열의 경우는 for문을 이용하여 프로퍼티를 열거해야 한다

var arr = [1,2,3];

for(int i=0; i<arr.length ; i++)

console.log(arr[i]);

배열 요소 삭제

배열도 객체이므로 delete 연산자를 이용하여 프로퍼티를 삭제할 수 있다. 하지만 delete 메소드는 실제 프로퍼티를 삭제하는 것이 아니고 undefined를 할당할 뿐이다. 그러므로 배열의 원소를 delete로 지워도 length프로퍼티는 변하지 않는다.
원소 자체를 삭제하기 위해서는 splice() 메소드를 이용해서 지울 수 있다.

동등(==)연산자와 일치(===)연산자

동등 연산자는 비교하려는 피연산자의 타입이 다를 경우에 타입 변환을 거친 후 비교하는 반면에 , 일치연산자는 피연산자의 타입이 다를 경우에 타입을 변경하지 않고 비교한다.

대부분의 자바스크립트 코딩가이드에서는 일치연산자를 사용하도록 권장하고 있다.



웹스톰 설치에 대한 챕터이므로 정리는 생략하도록 하겠다..

자바스크립트 기본개요

소개

자바스크립트는 웹 브라우저에서 동작하는 스크립트 언어이다. 현재는 브라우저 기반의 자바스크립트 라이브러리 뿐만 아니라 Node.js 와 같은 서버 기반의 자바스크립트 환경에서 동작할 수 있는 각종 라이브러리까지 쏟아져 나오고 있다. 이제는 자바스크립트만으로 웹 서버와 클라이언트인 웹 페이지 개발을 동시에 할 수 있는 수준에 이른 것이다.

웹 개발

현재 크롬이나 파이어폭스 등 웹 브라우저들이 나날이 발전하고 있으며, 그들이 새 버전을 내놓을 때마다 항상 강조하는 것이 자바스크립트 엔진의 성능 향상에 관한 것이다. 이는 웹 페이지를 개발하는 데 있어서 자바스크립트가 역할이 얼마나 큰지를 방증한다.

서버개발

Node.js의 출현으로 자바스크립트를 활용한 서버 개발도 활발이 이루어지고 있다.

애플리케이션 개발

웹이 하나의 플랫폼으로 진화하면서, 웹OS를 표방한 여러 가지 프로젝트가 진행되고 있다. 구글에선 크롬OS라는 브라우저 기반의 OS를 선보였고, 모바일에서도 HP에서 웹 OS라는 이름으로 모바일 기기에서 웹 기반의 각종 기술을 활용하고 있다.


자바스크립트 핵심 개념

객체

자바스크립트에서는 기본 데이터 타입인 boolean , string , number 와 특별한 값인 undefined , null을 제외한 모든 것은 객체이다. 기본 데이터 타입인 값들도 객체와 같이 다룰 수 있다.

함수

자바스크립트에서는 함수도 객체로 취급한다. 

프로토타입

모든 객체는 숨겨진 링크인 프로토타입을 가진다. 이 링크는 해당 객체를 생성한 생성자의 프로토타입 객체를 가리킨다. (생성자의 부모 객체) 이 링크를 ECMAScript에서는 [[prototype]] 이라고 표현한다 

실행 컨텍스트와 클로저

자바스크립트는 독특한 과정으로 실행 컨텍스트를 만들고 그 안에서 실행이 이루어진다. 이 실행 컨텍스트는 자신만의 유효범위를 갖는다. 뒤에서 더 자세하게 설명하도록 하겠다.

자바스크립트의 단점?

자바스크립트는 굉장히 유연한 언어이고 뛰어난 표현력을 가지고 있다. 하지만 이러한 특성때문에 종종 디버깅에 어려움을 겪기도 한다. 느슨한 타입 체크는 개발자에게 타입 체크에 대한 자유를 주지만, 컴파일 타임에서 잡지 못하는 오류는 고스란히 런타임 오류로 발견된다.



+ Recent posts