Object

2 minute read


Object

객체의 가장 기본적인 형태를 가지고 있는 객체이다. 즉 아무것도 상속받지 않는 순수한 객체로 자바스크립트에서는 값을 저장하는 기본적인 단위로 사용한다.

// 값만 저장
// grades는 Object 객체이다.  
var grades = {'bak':10, 'kim':18, 'lee':11}

또한 모든 객체는 Object 객체를 상속 받기 때문에 모든 객체는 Object 객체의 프로퍼티를 가지고 있다.

따라서 Object 객체를 확장하면 모든 객체가 접근할 수 있는 API를 만들 수 있게 된다.

Object를 확장하여 사용하기 위해서는 Object에 대한 정보가 필요하기 때문에 우선 API를 살펴본다.

Javascript Reference - Object

옆의 메뉴를 보면 많은 메서드가 보인다. 여기서 Object에서 바로 접근하여 사용하는 메서드와 Object.prototype에 접근하여 사용하는 메서드가 따로 있다.

javascript_object

두가지 다른 방식의 사용법을 살펴본다.

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에 어떠한 프로퍼티를 추가하여 사용하는 방법은 모든 객체에 일괄적으로 적용시킬 수 있기 때문에 편리하지만 모든 객체에 영향을 끼치게 되는 것이므로 자신이 하고자 하는일을 명확하게 파악하고 어떤 결과가 나올지 예상이 가능할 때 올바른 사용이 가능한 부분이다.