Object
Object
객체의 가장 기본적인 형태를 가지고 있는 객체이다. 즉 아무것도 상속받지 않는 순수한 객체로 자바스크립트에서는 값을 저장하는 기본적인 단위로 사용한다.
// 값만 저장
// grades는 Object 객체이다.
var grades = {'bak':10, 'kim':18, 'lee':11}
또한 모든 객체는 Object 객체를 상속 받기 때문에 모든 객체는 Object 객체의 프로퍼티를 가지고 있다.
따라서 Object 객체를 확장하면 모든 객체가 접근할 수 있는 API를 만들 수 있게 된다.
Object를 확장하여 사용하기 위해서는 Object에 대한 정보가 필요하기 때문에 우선 API를 살펴본다.
옆의 메뉴를 보면 많은 메서드가 보인다. 여기서 Object에서 바로 접근하여 사용하는 메서드와 Object.prototype에 접근하여 사용하는 메서드가 따로 있다.
두가지 다른 방식의 사용법을 살펴본다.
Object.keys()
객체의 키값을 반환하는 메서드이다.
var arr = ["a", "b", "c"];
console.log('Object.keys(arr)', Object.keys(arr));
// Object.keys(arr) ["0", "1", "2"]
// 배열안의 값들이 가지고있는 키, 인덱스 값을 반환했다.
var o = {"name":"bak", "age":13, "city":"busan"}
Object.keys(o);
// ["name", "age", "city"]
// 키 값들만 배열로 만들어서 반환한다.
Object.prototype.toString()
객체가 담고있는 값을 사람이 알아볼 수 있게 반환한다.
var o = new Object()
console.log('o.toString()', o.toString());
// o.toString() [object Object] , 객체의 상태를 문자로 출력
var a = new Array(1, 2, 3);
console.log('a.toString()', a.toString());
// "1,2,3" , 배열이 가지고 있는 값만을 출력
keys의 경우 Object가 가지고있는 프로퍼티를 사용하는 것으로 Object의 식별자로 메서드에 접근해 인자를 넣어 값을 반환받ㅇ르 수 있다.
생성자 함수를 이용해서 객체를 만들고(상속) 그 객체는 prototype이라는 특수한 프로퍼티에 저장된 객체가 원형이 된다. 이렇게 만들어진 객체로 toString를 사용할 수 있다.
Object 확장
모든 객체에서 사용할 수 있는 기능을 구현해본다.
어떤 기능을 구현할 것인가?
구현할 기능의 원리와 구조보다 어떻게 사용할 것인가를 먼저 생각해보는것도 좋은 방법이다.
// 객체
var o = {'name':'egoing', 'city':'seoul'}
console.log(o.contain('egoing'));
// contain은 객체안에서 값을 찾아 true, false를 반환한다.
// 배열
var a = ['egoing', 'leezche', 'grapittie'];
console.log(a.contain('leezche'));
// 배열에서도 사용가능한 기능
모든 객체에서 사용가능한 contain을 만든다.
// contain 구현
// 상속받는 모든 객체에서 사용할 수 있도록 prototype으로 생성
// 찾고자 하는것을 표현할 때 바늘 needle이란 단어를 자주 사용한다.
Object.prototype.contain = function(needle) {
// 메서드 안에서의 this는 이 메서드를 호출할 때 결정
// 호출하는 객체에서 검색하게된다.
for (var name in this) {
if (this[name] === needle) {
return true;
}
}
return false;
}
var o = {'name':'egoing', 'city':'seoul'}
console.log(o.contain('egoing'));
// true
var a = ['egoing', 'leezche', 'grapittie'];
console.log(a.contain('seoul'));
// false
확장의 위험
위에서 처럼 확장하게되면 모든 객체에 영향을 미치기 때문에 그만큼 위험이 따르게 된다.
위 코드가 정의된 상태에서 다음과 같은 상황이 발생한다.
o
// {name: "egoing", city: "seoul"}
a
// ["egoing", "leezche", "grapittie"]
// 문제점
for (var name in o) {
console.log(o[name])
}
// egoing
// seoul
/*
ƒ (needle) {
// 메서드 안에서의 this는 이 메서드를 호출할 때 결정
// 호출하는 객체에서 검색하게된다.
for (var name in this) {
if (this[name] === needle) {
return true;
}
}
return false;
}
*/
for in을 통해서 o의 값을 출력하려 했지만 정의했던 함수까지 출력이 된다. 즉 객체 o는 Object로 안에는 contain이라는 메서드도 포함하고 있기 때문에 모든 프로퍼티를 출력할 때 같이 나오게 된다.
이 문제를 해결하는 방법은
for (var name in a) {
// a가 직접 가지고있는 프로퍼티인지 검사해서 true, false 반환
if (a.hasOwnProperty(name)) {
console.log(name)
}
}
Object에 어떠한 프로퍼티를 추가하여 사용하는 방법은 모든 객체에 일괄적으로 적용시킬 수 있기 때문에 편리하지만 모든 객체에 영향을 끼치게 되는 것이므로 자신이 하고자 하는일을 명확하게 파악하고 어떤 결과가 나올지 예상이 가능할 때 올바른 사용이 가능한 부분이다.