Post

(JS) 객체, 프로토타입, 기본 타입에 기능 추가

JS에서 단순 데이터 타입인 숫자, 문자열 등을 제외하면 배열, 함수, 정규표현식 등이 모두 객체로 이루어져 있다. 숫자, 문자열 등은 메소드가 있기 때문에 유사 객체라고 할 수 있지만 이들은 immutable 이다.

JS에서 객체는 변형 가능한 속성들의 집합이라고 할 수 있으며 이름과 값이 있는 속성들을 포함하는 컨테이너다.

JS에는 객체 하나에 있는 속성들을 다른 객체에 상속하게 해주는 프로토타입(prototype) 연결 특성이 있다. 프로토타입을 잘 활용하면, 객체를 초기화 하는 시간과 메모리 사용을 줄일 수 있다.

JS에서는 클래스가 따로 없고, newConstructor를 사용할 수는 있지만, 프로토타입과 클로저를 활용한 함수형 패턴 으로 객체를 정의한다.

2017/05/31 - [Web/Front-end] - [JS] 함수 #2. Call pattern, 생성자 대안(함수형 패턴), 상속

객체 리터럴

객체 리터럴은 {name:value}형식으로 객체를 지정하는 것을 말한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
}
};
참조와 복사

객체는 참조 방식으로 전달된다. 절대 복사되지 않는다. 단, 문자열과 함수형 변수 (typeof === 'function')는 복사된다.

프로토타입(prototype)

모든 객체는 속성을 상속하는 프로토타입 객체에 연결돼 있다. 객체가 객체 리터럴로 생성되는 경우 JS 표준 객체인 ObjectObject.prototype 객체에 연결된다. ( 속성 prototype도 객체다. / Object.prototype은 최상위 prototype이다.)

그러나 실제로 출력해보면, 함수형 변수는 prototype이 있는 반면 객체 리터럴은 없는 것으로 나오므로 주의.

1
2
3
4
var func\_obj = function () { };
alert(func\_obj.prototype);     // [object Object]
var obj\_literal = { };
alert(obj\_literal.prototype);  // undefined
Object.create()

객체를 생성할 때는 해당 객체의 프로토타입이 될 객체를 선택할 수 있다. Object.create() 메소드에 객체를 넘기면 해당 객체를 프로토타입으로 하는 새로운 객체를 생성해 반환해준다.

1
2
3
4
var foo = {
aa: "asd"
};
var foo\_v2 = Object.create(foo);

foo_v2.aa는 기본값으로 "asd"를 가지고 있으며, 이를 수정, 삭제하더라도, foo.aa는 수정되지 않는다.

즉, 프로토타입은 수정이나 삭제와 무관하고 객체의 속성을 읽을 때만 사용한다.

객체에 있는 특정 속성에 접근하려고 할 때, 해당 속성이 객체에 없는 경우 프로토타입에서 찾아본다. 이러한 시도는 prototype chain을 따라 가장 마지막에 있는 Object.prototype까지 계속해서 이어진다.

속성에 접근할 때 프로토타입 체인 탐색이 일어나므로 프로토타입 객체에 새로운 속성이 추가되면 해당 객체를 프로토타입으로 하는 객체들에 이 속성이 바로 추가된다.

리플렉션 ( reflection )

객체의 특정 속성이 객체의 속성인지, 프로토타입의 속성인지 확인하고 싶은 경우

1
if (typeof foo\_v2.aa !== 'function')

hasOwnProperty는 프로토타입 체인을 탐색하지 않으며 true/false를 반환한다.

1
if (foo\_v2.hasOwnProperty('aa'))

typeof는 프로토타입 체인을 탐색하며 type을 반환하기 때문에 특정 type(e.g. !== function)을 가려내는데 유용하다.

delete

객체의 속성을 삭제할 수 있다. delete foo_v2.aa

이 역시 프로토타입 객체에 영향을 주지는 않기 때문에 aa에 접근하면 프로토타입의 aa가 나타난다. 즉, 프로토타입의 속성은 삭제되지 않는다.

기본 타입에 기능 추가

Object.prototype에 메소드를 추가하면 모든 객체에서 그 메소드를 사용할 수 있다. 함수, 배열, 문자열, 숫자, 정규 표현식, 불리언 모두 이런식으로 기능을 추가할 수 있다.

Function.prototype에 메소드를 추가하는 기능의 method라는 메소드를 추가하면, 이를 이용해 간단히 메소드를 추가할 수 있다.

1
2
3
4
5
6
7
8
9
Function.prototype.method = function (name, func){

if(!this.prototype[name]){

this.prototype[name] = func;

}
return this;
};

JS에는 따로 구분된 정수형이 없어서 때때로 숫자형에서 정수 부분만 추출해야 하는 경우가 있다. 이를 Number.methodinteger라는 메소드를 추가해서 해결할 수 있다. 메소드 호출 패턴이기 때문에, this는 해당 메소드를 호출한 객체가 된다.

1
2
3
4
5
6
7
Number.method('integer', function ( ) {

return Math[this < 0 ? 'ceiling' : 'floor'](this);
});


alert(13.2.integer());

문자열의 양 끝에 있는 빈칸을 지우는 메소드는 이런 식으로 추가한다.

1
2
3
4
String.method('trim', function ( ) {

return this.replace(/^\s+|\s+$/g, '');
});
This post is licensed under CC BY 4.0 by the author.