[JS] 객체, 프로토타입, 기본 타입에 기능 추가
JS에서 단순 데이터 타입인 숫자, 문자열 등을 제외하면 배열, 함수, 정규표현식 등이 모두 객체로 이루어져 있다.
숫자, 문자열 등은 메소드가 있기 때문에 유사 객체라고 할 수 있지만 이들은 immutable이다.
JS에서 객체는 변형 가능한 속성들의 집합이라고 할 수 있으며 이름과 값이 있는 속성들을 포함하는 컨테이너다.
JS에는 객체 하나에 있는 속성들을 다른 객체에 상속하게 해주는 프로토타입(prototype) 연결 특성이 있다. 프로토타입을 잘 활용하면, 객체를 초기화 하는 시간과 메모리 사용을 줄일 수 있다.
JS에서는 클래스가 따로 없고, ``js new``와 ``Constructor``를 사용할 수는 있지만, 프로토타입과 클로저를 활용한 함수형 패턴으로 객체를 정의한다.
2017/05/31 - [Web/Front-end] - [JS] 함수 #2. Call pattern, 생성자 대안(함수형 패턴), 상속
객체 리터럴
객체 리터럴은 ``js {name:value}``형식으로 객체를 지정하는 것을 말한다.
```js
const foo = {
"": 5,
a_s: "valid name",
"a-s": "unvalid name",
value : 0,
reiter: {
a: 33
},
add_value: function() { // arrow function을 쓰면 value가 증가하지 않는다!
this.value += 1;
}
get value() { // getter
return this.value;
}
};
```
참조와 복사
객체는 참조 방식으로 전달된다. 절대 복사되지 않는다.
단, 문자열과 함수형 변수(``js typeof === 'function'``)는 복사된다.
프로토타입(prototype)
모든 객체는 속성을 상속하는 프로토타입 객체에 연결돼 있다.
객체가 객체 리터럴로 생성되는 경우 JS 표준 객체인 ``js Object``의 ``js Object.prototype`` 객체에 연결된다.
( 속성 ``prototype``도 객체다. / ``js Object.prototype``은 최상위 ``prototype``이다.)
그러나 실제로 출력해보면, 함수형 변수는 ``prototype``이 있는 반면 객체 리터럴은 없는 것으로 나오므로 주의.
```js
var func_obj = function () { };
alert(func_obj.prototype); // [object Object]
var obj_literal = { };
alert(obj_literal.prototype); // undefined
```
Object.create()
객체를 생성할 때는 해당 객체의 프로토타입이 될 객체를 선택할 수 있다.
``js Object.create()`` 메소드에 객체를 넘기면 해당 객체를 프로토타입으로 하는 새로운 객체를 생성해 반환해준다.
```js
var foo = {
aa: "asd"
};
var foo_v2 = Object.create(foo);
```
``js foo_v2.aa``는 기본값으로 ``js "asd"``를 가지고 있으며, 이를 수정, 삭제하더라도, ``js foo.aa``는 수정되지 않는다.
즉, 프로토타입은 수정이나 삭제와 무관하고 객체의 속성을 읽을 때만 사용한다.
객체에 있는 특정 속성에 접근하려고 할 때, 해당 속성이 객체에 없는 경우 프로토타입에서 찾아본다. 이러한 시도는 prototype chain을 따라 가장 마지막에 있는 ``js Object.prototype``까지 계속해서 이어진다.
속성에 접근할 때 프로토타입 체인 탐색이 일어나므로 프로토타입 객체에 새로운 속성이 추가되면 해당 객체를 프로토타입으로 하는 객체들에 이 속성이 바로 추가된다.
리플렉션 ( reflection )
객체의 특정 속성이 객체의 속성인지, 프로토타입의 속성인지 확인하고 싶은 경우
```js
if (typeof foo_v2.aa !== 'function')
```
``hasOwnProperty``는 프로토타입 체인을 탐색하지 않으며 ``js true/false``를 반환한다.
```js
if (foo_v2.hasOwnProperty('aa'))
```
``js typeof``는 프로토타입 체인을 탐색하며 ``type``을 반환하기 때문에 특정 ``type``(e.g. !== function)을 가려내는데 유용하다.
delete
객체의 속성을 삭제할 수 있다.
``js delete foo_v2.aa``
이 역시 프로토타입 객체에 영향을 주지는 않기 때문에 ``aa``에 접근하면 프로토타입의 ``aa``가 나타난다.
즉, 프로토타입의 속성은 삭제되지 않는다.
기본 타입에 기능 추가
``js Object.prototype``에 메소드를 추가하면 모든 객체에서 그 메소드를 사용할 수 있다.
함수, 배열, 문자열, 숫자, 정규 표현식, 불리언 모두 이런식으로 기능을 추가할 수 있다.
``js Function.prototype``에 메소드를 추가하는 기능의 ``method``라는 메소드를 추가하면, 이를 이용해 간단히 메소드를 추가할 수 있다.
```js
Function.prototype.method = function (name, func){
if(!this.prototype[name]){
this.prototype[name] = func;
}
return this;
};
```
JS에는 따로 구분된 정수형이 없어서 때때로 숫자형에서 정수 부분만 추출해야 하는 경우가 있다.
이를 ``js Number.method``에 ``integer``라는 메소드를 추가해서 해결할 수 있다.
메소드 호출 패턴이기 때문에, ``this``는 해당 메소드를 호출한 객체가 된다.
```js
Number.method('integer', function ( ) {
return Math[this < 0 ? 'ceiling' : 'floor'](this);
});
alert(13.2.integer());
```
문자열의 양 끝에 있는 빈칸을 지우는 메소드는 이런 식으로 추가한다.
```js
String.method('trim', function ( ) {
return this.replace(/^\s+|\s+$/g, '');
});
```
'JS Stack > JS' 카테고리의 다른 글
[JS] 함수 #2. Call pattern, 생성자 대안(함수형 패턴), 상속 (0) | 2017.05.31 |
---|---|
[JS] 함수 #1. 유효범위(scope), callback, 클로저(closure), 접근 제어 (0) | 2017.05.31 |
[Regex] JS (0) | 2017.05.28 |
[JS] TIP (0) | 2017.05.25 |
[JS] 리터럴, 자료형, 반복문 (0) | 2017.03.01 |