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



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 프로퍼티에 연결됩니다. 이렇게 자바스크립트에서 함수를 생성할 때 해당 함수와 연결되는 디폴트 프로토타입 객체를 다른 일반 객체로 변경할 수 있습니다.

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


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







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



This 바인딩


자바스크립트에서 함수를 호출할 때 기존 매개변수로 전달되는 인자값에 더해, arguments 객체 및 this 인자가 함수 내부로 암묵적으로 전달됩니다. 여기서 this는 함수가 호출되는 방식(호출 패턴)에 따라 다른 객체를 참조하게(this 바인딩) 됩니다.

지금부터 여러가지 호출 패턴에 따른 this 바인딩에 대하여 나열해 보겠습니다.



1.객체의 메서드 호출할 때 This 바인딩


객체의 메서드를 호출할 때에는 해당 메서드를 호출한 객체로 바인딩 됩니다. 


var person ={
    name : 'song',
    sayName : function(){
        console.log(this.name);
    }
}


위와 같은예제에서 person.sayName();을 호출하면 결과는 'song'이 로그에 찍히게 됩니다. 즉, 자신을 호출한 객체가 this에 바인딩 되었습니다.




2.함수를 호출할 때 this 바인딩


자바스크립트에서 함수를 호출하면, 해당 함수 내부 코드에서 사용된 this는 전역 객체에 바인딩됩니다.(window)

*브라우저에서 전역객체란 window 객체, node.js에서는 global 객체.


var name = 'sooooong';

var sayName =function(){
  console.log(this.name);
}


위와 같은예제에서 sayName();을 호출하면 결과는 'sooooong'이 로그에 찍히게 됩니다. 즉 window.name이 this.name이 되는겁니다.


이러한 함수 호출에서의 this 바인딩 특성은 내부 함수를 호출했을 때에도 동일합니다. 때문에 내부 함수에서 this를 사용할 때 주의해야합니다.

var age = 40;
var person ={
    name : 'song',
    age : 29,
    sayName : function(){
        console.log(this.name);
    },
    sayAge : function(){
     console.log(this.age);

     sayAge2:fucntion(){
      console.log(this.age + 1);
     }
      sayAge2();
    }
}

위와 같은예제에서 person.sayAge();을 호출하면 결과는

29

30

이 아닌

29

41

이 나오게 됩니다. 이유는 sayAge의 내부함수인 sayAge2에서의 this는 window객체이기 때문입니다. 때문에 window.age인 40이 참조되게 되는 것입니다.


이렇게 되는 이유는 자바스크립트에서는 내부 함수 호출 패턴을 정의해 놓지 않기 때문입니다. 내부 함수도 결국 함수이므로 함수 호출 패턴 규칙에 따라서 window에 this가 binding됩니다.


때문에 이러한 자바스크립트의 한계를 극복하려면 부모함수의 this를 내부 함수가 접근 가능한 다른 변수에 저장하는 방법을 사용해야합니다.



var age = 40;
var person ={
    var that = this;
    name : 'song',
    age : 29,
    sayName : function(){
        console.log(this.name);
    },
    sayAge : function(){
     console.log(that.age);

     sayAge2:fucntion(){
      console.log(this.age + 1);
     }
      sayAge2();
    }
}

위와 같이 this를 that에 저장하면 원래 의도했던 29, 30이라는 결과를 얻을수있습니다.

자바스크립트에서는 이러한 this 바인딩의 한계를 극복하기위해 this 바인딩을 명시적으로 할 수 있는 call과 apply라는 메서드를 제공합니다.



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


자바스크립트의 생성자 함수는 말 그대로 자바스크립트의 객체를 생성합니다. 하지만 c++과 같이 그 형식이 정해지지는 않았고, 기존 함수에 new 연산자를 붙여서 호출하면 해당 함수는 생성자 함수로 동작합니다. 다만 특정 함수가 생성자 함수로 정의되어 있음을 알리려고 첫 글자를 대문자로 하는 것을 권하고 있습니다.


new 연산자로 자바스크립트 함수를 생성자로 호출하면, 다음과 같은 순서로 동작합니다. 


1) 빈 객체 생성 및 this 바인딩

먼저 빈 객체가 생성되고, 이 객체가 생성자 함수가 새로 생성하는 객체입니다. 이 객체는 this로 바인딩됩니다. 따라서 이후 생성자 함수의 코드 내부에서 사용된 this는 이 빈 객체를 가리킵니다.


엄밀히 말해서 빈 객체는 아니고 자신을 생성한 생성자 함수의 prototoype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정합니다.


2) this를 통한 프로퍼티 설정

이후에는 함수 코드 내부에서 this를 사용해서, 앞에서 생성된 빈 객체에 동적으로 프로퍼티나 메서드를 생성할 수 있습니다.


3) 생성된 객체 리턴

특별하게 정의된 리턴문이 없는 경우 this로 바인딩된 새로 생성한 객체가 리턴됩니다. 만약 명시적으로 다른 객체를 리턴하도록 했다면 다른 객체가 리턴됩니다.


var Person = function(name){
     this.name = name;
};
var song = new Person('song');
console.log(song.name);


이렇게 생성자를 이용해 객체를 생성하는 방식과 리터럴을 이용해 생성하는 방식의 차이는 프로토타입 객체(_proto_)에 있습니다.

위에 예제에서의 song객체의 프로토타입 객체는 Person이고 리터럴로 동일한 song 객체를 만들면 그 song객체의 프로토타입 객체는 Object입니다.


이는 자바스크립트 객체 생성 규칙 때문입니다. 자바스크립트 객체는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체를 자신의 프로토타입 객체로 설정합니다.


객체 리터럴 방식에서는 객체 생성자 함수가 Object이고, 생성자 함수 방식의 경우는 생성자 함수 자체가 프로토타입 객체입니다.



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


자바스크립트에서는 this를 특정 객체에 명시적으로 바인딩시키는 방법도 제공합니다. 이를 가능하게 하는 것이 함수 객체의 기본 프로퍼티인 apply와 call메서드입니다. 


이 메서드들은 모든 함수의 부모 객체인 Function.prototype 객체의 메서드이므로, 모든 함수는 다음과 같이 apply를 호출할 수 있습니다.


function.apply(thisArg, argArray);


call과 apply는 기능은 같고 단지 넘겨받는 인자의 형식만 다릅니다.


apply() 메서드를 호출하는 주체는 함수고, 특정 this를 바인딩할 뿐 본질적인 기능은 함수 호출입니다. sayName(); 은 

sayName.apply(); 와 같습니다.


apply의 첫 번째 인자인 thisArg는 apply() 메서드를 호출한 함수 내부에서 사용한 this에 바인딩할 객체입니다.

즉, 첫 번째 인자로 넘긴 객체가 this에 명시적으로 바인딩됩니다.


두 번째 인자인 argArray는 함수를 호출할 때 넘길 인자들의 배열입니다.


call()은 apply()와 기능은 같지만, apply에서 두 번째 인자로 배열 형태로 넘기는 것을 각각 하나의 인자로 넘기는 차이가 있습니다. 


Person.apply(song, ['song', 29]);

Person.call(song, 'song', 29);


call()과 apply() 함수의 대표적인 용도는 유사 배열 객체에서 배열 표준 메서드를 사용할 때 입니다.




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



1.함수 생성


자바스크립트에서 함수를 생성하는 방법은 3가지가 있습니다

1)함수 리터럴

아래 코드에서 add에 해당하는 함수 이름은 생략 가능합니다.


function add(x, y){

return x + y;

}


2)함수 선언문

함수명이 반드시 정의되어 있어야 합니다.


function add(x, y){

return x + y;

}


3)함수 표현식(추천!! 이유는 2번 함수 호이스팅에서 설명하겠습니다.)

아래와 같이 함수에 이름을 만들지 않고 변수에 할당하는 방식을 익명 함수 표현식이라 합니다.

함수 내부에서 재귀적으로 호출할 필요가 있을 때에는 함수에 이름을 붙여주면 됩니다.

여기서 add는 함수 이름이 아닌 익명함수를 참조하는 변수입니다. //함수변수


var add = function (x, y){

return x + y;

};


함수 표현식으로 함수를 생성하는 경우에는 세미콜론을 필수로 사용해야합니다.

이유는 다음과 같은 오류가 발생할 수 있기 때문입니다.


var func = function() {
return 42;
}
(function(){
return 24;
})();


위와 같은 코드가 있을 때 func 함수 표현문 끝에 세미콜론이 없기 때문에 자바스크립트 엔진은 중괄호에서 끝났다고 인식하지 못하고 ()로 감싸진 익명함수 생성 리터럴을 무시하고 ()로 func를 실행하게됩니다.

때문에 그 뒤에 있는 ()는 func의 리턴 값인 42()와 같이 인식하게 되어 오류가 발생합니다.




2.함수 호이스팅


앞에서 함수를 생성하는 여러가지 방법에 대해서 나왔는데 이들 사이에는 동작 방식이 약간 차이가 있습니다.

그중의 하나가 바로 함수 호이스팅(Function Hoisting)입니다. 


add(3, 5);

function add(x, y){
return x + y;
};

add(3, 4);


맨 위에 add(3, 5); 같은 경우에는 아직 함수가 선언되지 않았는대도 불구하고 호출이 가능합니다. 

함수가 위치한 위치에 상관없이 함수 선언문 형태로 정의한 함수의 유효 범위는 코드의 맨 처음부터 시작한다. 

이것을 함수 호이스팅이라고 합니다.


함수 표현식으로 함수를 생성하면 이러한 함수 호이스팅이 일어나지 않는다. 


3.함수도 객체다.


자바스크립트에서는 함수를 일급객체라고 부른다.


1) 프로퍼티를 가질 수 있다.


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

- 리터럴에 의해 생성

- 변수나 배열의 요소, 객체의 프로퍼티 등에 할당 가능

- 함수의 인자로 전달 가능

- 함수의 리턴값으로 리턴 가능

- 동적으로 프로퍼티를 생성 및 할당 가능

*위와 같은 자바스크립트 함수의 특성들을 가지고 있는 객체를 일급객체라고 한다.


3) 함수 객체의 기본 프로퍼티

함수는 객체이므로 함수 객체만의 표준 프로퍼티가 정의되어 있습니다.

대표적으로 arguments, caller, length, name, apply, call, bind이 있습니다.

이들 프로퍼티들은 Function.prototype 객체로 부터 받은 것입니다.


- arguemnts

함수로 전달된 인자값들

- length

인자의 수

- caller

자신을 호출한 함수

- name

함수의 이름

- prototype

prototype 프로퍼티는 _proto_와 다릅니다.

* _proto_ : 자신의 부모 역할을 하는 프로토타입 객체를 가리킨다.


prototype 프로퍼티는 함수가 생성될 때 만들어지며 단지 constructor 프로퍼티 하나만 있는 객체를 가리킵니다.

그리고 prototype 프로퍼티가 가리키는 프로토타입 객체의 constructor 프로퍼티는 자신과 연결된 함수를 가리킵니다.


즉, 자바스크립트에서는 함수를 생성할 때, 함수 자신과 연결된 프로토타입 객체를 동시에 생성하며

이 둘은 prototype 과 constructor라는 프로퍼티로 서로를 가리킵니다.




그러니까 예를들어 func 함수는 생성될 때 프로토타입 객체가 동시에 생성되고 이 객체를 prototype 프로퍼티로 참조합니다. 이 프로토타입 객체는 constructor라는 프로퍼티를 가지고 있고, 이 또한 객체이므로 _proto_ 프로퍼티도 가지고 있습니다.




prototype 프로퍼티가 가리키고 있는 func의 프로토타입객체는 constructor 프로퍼티로 func 함수를 가리킵니다.




이해하기 힘든 개념일 수 있습니다. 이후 프로토타입과 프로토타입 체이닝에 대해서 자세히 포스팅할 예정이니 이정도 책 내용 정도로만 이해하시고 넘어가시면 될 것 같습니다.



4.함수의 다양한 형태


1) 콜백함수

함수를 명시적으로 호출하는 것이 아니라 개발자는 함수를 등록하고, 특정 이벤트가 발생하거나 특정 시점에 도달하였을 때 시스템에서 호출하는 함수를 말합니다.


대표적인 콜백 함수의 사용 예가 자바스크립트에서의 이벤트 핸들러 처리입니다. 웹페이지가 로드 되거나, 키보드 입력되는 등 DOM이벤트가 발생할 경우 브라우저는 정의된 DOM 이벤트에 해당하는 이벤트 핸들러를 실행시킵니다. 개발자가 만약 해당하는 이벤트 핸들러에 콜백 함수를 등록했다면 이벤트가 발생할 때마다 브라우저에 의해 실행되게 됩니다.



2) 즉시 실행 함수

함수를 정의함과 동시에 바로 실행하는 함수를 즉시 실행 함수(immediate functions)라 합니다.

함수가 선언되자마자 실행되게 만든 즉시 실행 함수의 경우 같은 함수를 다시 호출할 수 없습니다. 따라서 최초 한 번의 실행만을 필요로 하는 초기화 코드에 사용할 수 있습니다.

예를 들어 아래와 같은 형태로 사용하실 수 있습니다.

(function(name){
//initialize 함수
console.log("Init");
InitFrame();
InitModel();
InitMain();
user.name = name;
})("song");

그리고 jQuery와 같은 자바스크립트 라이브러리나 프레임워크 소스들에서 사용되니 알아두면 좋습니다.

jQuery에서 즉시 실행 함수를 사용하는 이유는 함수 유효 범위 때문입니다.

*자바스크립트에서 변수는 전역 유효 범위를 가진다. 그러나 함수 내부의 변수(var)는 함수 유효 범위를 가진다.



따라서 라이브러리 코드를 즉시 실행 함수 내부에 정의해두면, 라이브러리 내의 변수들에 외부에서 접근할 수 없습니다. 따라서 즉시 실행 함수 내에 라이브러리 코드를 추가하면 전역 네임스페이스를 더럽히지 않고, 다른 라이브러리들이 동시에 로드 되더라도 라이브러리간 변수 이름 충돌을 방지할 수 있습니다.

3) 내부 함수

함수 내부에 정의된 함수를 내부 함수라고 부릅니다. 내부 함수는 클로저를 생성하거나 부모 함수 코드에서 외부에서의 접근을 막고 독립적인 헬퍼 함수를 구현하는 용도로 사용합니다.


내부 함수의 특징은 다음과 같습니다.

- 내부 함수에서는 자신을 둘러싼 부모 함수의 변수에 접근이 가능하다.

C++과 같은 언어를 사용하셨던 분들은 낯설게 느끼실 수 있습니다. 이러한 것이 가능한 이유는 자바스크립트의 스코프 체이닝 때문입니다.  


*클로저, 스코프 체이닝은 따로 포스팅하겠습니다. ^^



- 내부 함수는 일반적으로 자신이 정의된 부모 함수 내부에서만 호출이 가능하다.


5. 함수 리턴


1) 일반 함수나 메서드는 리턴값을 지정하지 않을 경우, undefined 값이 리턴된다.

2) 생성자 함수에서 리턴값을 지정하지 않을 경우 생성된 객체가 리턴된다.

3) 생성자 함수에서 리턴값을 명시적으로 특정 객체로 지정한 경우 지정된 객체가 리턴된다.

그러나 만약 객체가 아닌 value값을 리턴 하려한다면 무시하고 this로 바인딩된 객체가 리턴됩니다.


다음번 포스팅은 함수와 this에 대한 내용입니다.



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



배열(Array)

배열은 자바스크립트 객체의 특별한 형태다. C의 배열과 유사하지만 크기를 지정하지 않아도 되며, 어떠한 타입의 데이터를 저장하더라도 상관없다.




1. 배열 생성

배열의 생성은 두 가지 방법으로 할 수 있습니다.

일반적으로 배열 리터럴 방식으로 생성합니다.


1) 배열 리터럴

[] 대괄호 문법을 이용한 리터럴 방식으로 배열 생성


var str = 'test';
var colorArr = ['orange', 'yellow', blue];

2) 생성자 함수를 이용한 생성

호출할 때 인자가 1개이고, 숫자인 경우: 호출된 인자를 length로 갖는 빈 배열을 생성한다.

그 외의 경우: 호출된 인자를 요소로 갖는 배열 생성.

var colorArr = new Array(3);
colorArr.push('orange');
colorArr.push('yellow');
colorArr.push('blue');
//var colorArr = new Array('orange', 'yellow', 'blue');


2. length 프로퍼티

배열의 원소 개수를 나타낸다. 그러나 배열에 존재하는 실제 원소 개수와 일치하는 것은 아니다. 

배열 내에 가장 큰 인덱스에 1을 더한 값이다.


배열의 가장 큰 인덱스값이 변하면, length 값 또한 자동으로 그에 맞춰 변경된다.

var arr = []; arr[0] = 1; arr[100] = 2; console.log(arr.length); // 101


배열의 length 프로퍼티는 명시적으로 값을 지정할 수도 있습니다.

만약 현재 배열의 length보다 큰 값을 지정한다면 현재 length Index 이후 값들은 undefined로 채워지게 됩니다.


length는 배열 표준 메서드에 영향을 미친다.


배열 표준 메서드인 push 메서드는 length값을 기준으로 수행됩니다. 

만약 length가 5라면 length는 마지막 Index + 1이므로 push 메서드의 수행결과로 새롭게 추가될 원소의 자리는 배열[length]가 되게됩니다.

length 프로퍼티는 이렇게 배열 표준 메서드에 영향을 미칠 수 있는 프로퍼티이므로 중요합니다.


이렇게 중요한 length 프로퍼티가 객체에 프로퍼티로 존재하면 어떻게될까요?

자바스크립트에서는 이렇게 length 프로퍼티를 가진 객체를 유사 배열 객체라고 부릅니다. 


* 배열에 동적으로 프로퍼티가 추가되어도 length는 증가하지 않는다. 배열의 length 프로퍼티는 오직 배열 원소의 가장 큰 인덱스가 변했을 경우만 변경된다.




3. 배열과 객체

자바스크립트에서는 배열 역시 객체입니다. 


객체와 배열의 typeof 값은 둘 다 Object로 동일합니다. 


그치만 분명히 배열과 객체는 다릅니다.

- length 프로퍼티의 존재 여부

- 배열 표준 메서드 존재 여부


이러한 차이점이 생기는 이유는 

객체의 경우 프로토타입으로 Object.prototype 객체를 갖고,

배열의 경우 프로토타입으로 Array.prototype 객체를 갖게되기 때문입니다.


length, 배열 표준 메서드는 Array.prototype 객체가 가지고 있는 프로퍼티입니다.


3. 배열의 프로퍼티 열거


배열을 객체와 같이 for in 문으로 프로퍼티를 열거하면 의도치 않은 동작이 수행될 수 있습니다.


var arr = ['a', 'b' , 'c']; arr['name'] = 'song'; for(var prop in arr) { console.log(prop, arr[prop]); } //0 a //1 b //2 c //name song //....여러가지 배열 프로퍼티 for(var i = 0; i< arr.length; i++){ console.log(i, arr[i]) } //0 "a" //1 "b" //2 "c"

위와 같이 for in문을 사용하면 배열의 원소 뿐아니라 여러가지 프로퍼티들도 같이 출력되게 됩니다. 의도치 않은 동작이 수행될 수 있겠죠?

때문에 배열의 원소를 탐색할 때에는 for문을 사용하는 것이 좋습니다.


4. 배열의 요소 삭제


1) delete

delete 연산자는 length 값은 그대로 유지한채 삭제합니다. 즉, 배열의 원소값을 undefined로 바꿔줍니다.


2) splice

만약 배열의 요소를 완전히 삭제하고 싶다면 splice()메서드를 이용해서 배열의 요소를 삭제할 수 있습니다.


splice(start, deleteCount, item...)

- start: 배열에서 시작 인덱스

- deleteCount: 삭제할 요소의 수

- item: 삭제할 위치에 추가할 요소

 




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



참조 타입(객체)


자바스크립트에서 기본 타입을 제외한 모든 값은 객체다.

따라서 배열, 함수, 정규표현식 등도 결국 자바스크립트 객체로 표현된다.

자바스크립트에서 객체는 단순 key : value 형태의 프로퍼티들을 저장하는 컨터이너로써, Hash와 유사하다. 
프로퍼티에는 기본 타입, 참조 타입(객체), 함수등 모든 타입을 포함할 수 있다.



1. 객체 프로퍼티 접근


객체 프로퍼티를 읽고, 쓰고, 갱신하기 위해 접근하는 방법은 두 가지가 있습니다.


- 대괄호([]) 표기법

- 마침표(.) 표기법


일반적으로는 C++, Java등의 언어와 유사하게 마침표 표기법을 많이 사용하지만 대괄호 표기법만을 사용해야하는 경우가 있습니다.

1) 프로퍼티 이름이 표현식인 경우 // foo['full-name'] = 'foo song';

2) 프로퍼티 이름이 예약어인 경우 




2. for in 문


for in 문을 사용하면, 객체에 포함된 모든 프로퍼티에 대해 루프를 수행할 수 있습니다.

var objA = {

val : 40

};



var objB = objA;



console.log(objA.val); // 40

console.log(objB.val); // 40



objB.val = 50;



console.log(objA.val); // 50

console.log(objB.val); // 50
for in 문을 수행하면서 변수에 객체의 프로퍼티가 하나씩 String 타입으로 할당됩니다.



3. 객체 프로퍼티 삭제


자바스크립트에서는 객체의 프로퍼티를 delete 연산자를 이용해 즉시 삭제할 수 있습니다.


delete foo.name;


4. 참조 타입의 특성


자바스크립트에서 객체는 참조 타입입니다. 

말그대로 객체의 모든 연산이 실제 값이 아닌 참조값으로 처리되기 때문입니다.

var objA = {

val : 40

};



var objB = objA;



console.log(objA.val); // 40

console.log(objB.val); // 40



objB.val = 50;



console.log(objA.val); // 50

console.log(objB.val); // 50

objB의 프로퍼티를 수정해도 objA의 프로퍼티가 같이 수정됩니다. 따라서 두 객체는 같은 객체를 가리키고 있다는 것을 알 수 있습니다.


var objA = {}; 


위와 같이 객체를 생성되면 objA 자체의 값이 객체인 것이 아니라 생성된 객체를 가리키는 참조값을 저장하고 있는 것입니다.

 

객체비교도 마찬가지 입니다.

var objA = {

val : 40

};



var objB = {

val : 40

};



var objC = objB;



console.log(objA == objB); // false

console.log(objB == objC); // true

변수는 객체의 값이 아닌 객체의 참조값을 가지고 있기 때문에 모든 값이 동일한 objA와 objB는 다른 객체이고, 참조값이 같은 objB와 objC는 같습니다.


* 다음 포스팅에 깊은복사와 객체간 값 비교를 통해 비교하는 함수를 만들어 보도록 하겠습니다. 



4. 참조에 의한 호출 방식 (call by reference)


기본 타입과 참조 타입의 경우는 함수 호출 방식도 다릅니다. 기본 타입의 경우는 call by value/ 참조 타입은 call by reference 입니다.


call by value: 함수를 호출할 때 인자로 복사된 값을 전달한다. 즉, 함수내에서 매개변수의 값을 변경해도 실제 값은 변경되지 않는다.

call by reference: 함수를 호출할 때 인자로 객체의 참조값이 전달된다. 즉, 함수내에서 매개변수의 값을 변경하면 실제 값이 변경된다.


위에서 4. 참조 타입의 특성으로 보면 알 수 있듯이 참조 타입은 값 자체가 아닌 가리키고 있는 참조값입니다. 때문에 함수 내에서 인자로 받은 객체의 프로퍼티를 수정하면 원본 객체의 프로퍼티가 수정됩니다.


c++을 하셨던 분들은 포인터를 생각하시면 이해가 빠를듯 합니다. 변수에 할당된 것은 값이 아니고 주소이고, 그 주소에 있는 값을 변경하는 것이라고 생각하시면 됩니다.



5. 프로토타입


자바스크립트의 모든 객체는 자신의 부모 역할을 하는 객체와 연결되어 있습니다. 마치 객체지향의 상속과 유사하게 부모 객체의 프로퍼티를 자신의 것처럼 사용할 수 있습니다. 자바스크립트에서는 이러한 부모 객체를 프로토타입이라고 부릅니다. 


ECMAScript 명세서에는 자바스크립트의 모든 객체는 자신의 프로토타입을 가르키는 [[Prototype]]이라는 숨겨진 프로퍼티를 가진다고 설명합니다. 이를 크롬 브라우저에서는 _proto_라 되어있습니다.



foo 객체의 프로토타입 객체는 Object.prototype 객체입니다. (객체의 최상위 프로토타입) 따라서 foo 객체는 Object.prototype에 정의된 프로퍼티들을 사용할 수 있습니다.


자바스크립트에서 굉장히 중요한 개념입니다. 이후에 따로 프로토타입, 프로토타입 체이닝, 상속에 관하여 심도있게 포스팅을 작성해볼 예정입니다^^.





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




자바스크립트 데이터 타입


언어의 기본인 데이터 타입입니다.

자바스크립트의 데이터 타입은 크게 아래와 같이 분류할 수 있습니다.




기본 타입



1. Number


자바스크립트에서는 단 하나의 숫자형만 존재합니다. 모든 숫자를 64비트 부동 소수점 형태로 저장합니다.


2. String


문자열은 작은 따음표('), 큰 따옴표(")로 생성할 수 있습니다.


자바스크립트에서는 C++의 문자열 배열과 같이 문자열에 접근은할 수 있지만 수정은 할 수 없습니다. 

자바스크립트에서는 한 번 생성된 문자열은 읽기만 가능하지 수정은 불가능합니다.


var str = 'test';
str[0] = 'T';
console.log(str); //결과는 'test'


3. Boolean


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



4. null, undefined


이 두 타입은 모드 자바스크립트에서 '값이 비어있음'을 나타낸다. 

기본적으로 값이 할당되지 않은 상태의 변수는 undefined이다. 


undefined 타입 변수의 값 자체도 undefined 이다. 즉, undefined는 타입이자 값을 나타낸다.

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


null 타입 변수의 typeof의 결과는 object이다. 


때문에 함수내에서 예외처리시 if(typeof test === 'object')와 같은 형태로 사용하다가 null 타입 변수가 의도치 않게 통과될 수 있습니다. 주의하여야 합니다. 저도 종종 이러한 실수를 한 적이 있습니다.. 


null 타입 변수인지를 확인할 때에는 typeof 연산자가 아닌 값으로 확인해야 합니다.



Cascading?


: css 적용 우선순위

css는 한 가지의 속성값에 여러 가지의 값이 정의될 수 있습니다. 이 때 어떠한 값을 따라야 할 지 우선순위를 Cascading이라고 합니다.


기본적인 규칙은 더 구체적인 것/명시적인 것이 우선순위가 높습니다.


1. Style 속성

2. id 선택자

3. class 선택자

4. tag 선택자



'!important;'를 붙여서 절대적으로 우선순위를 높이는 방법도 있습니다.


좋은 방법은 아니므로 되도록 우선순위에 따라서 맞춰서 CSS를 작성하시는 편이 좋습니다.