참고 자료 https://opentutorials.org/course/743/6578
Object가 객체를 의미하는데 'Object 객체'는 뭘까?
자바스크립트에서 Object 객체는 자바스크립트의 모든 객체들의 최상위 부모 객체를 의미한다.
자바에서는 Object 클래스가 최상위 클래스였는데... 자바스크립트는 알아갈수록 자바와 비슷한 면이 많이 보인다.
Object 객체 사용시 동작원리
Object 객체의 메서드의 종류에는 두가지가 있다.
(MDN 에서 확인 가능하다. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
위의 예시와 같이 Object.메서드(), Object.prototype.메서드() 이렇게 종류가 나뉜다.
위의 예시들 중 Object.keys(), Object.prototype.toString() 문법을 살펴보자.
<script>
//Object.keys()
let arr = ["a", "b", "c"];
console.log('Object.keys(arr):', Object.keys(arr))
// Object.keys() 는 매개변수로 전달된 객체의 key값만을(value제외) 뽑아낸다.
// 배열도 객체에 해당하고 따라서 Object.keys(arr)의 결과는 배열의 key값인 인덱스 0, 1, 2 가 출력된다.
//-----------------------------------------------------------
//Object.prototype.toString()
let o = new Object();
console.log('o.toString()', o.toString());
// [object Object] 라는 값이 String 타입으로 반환된다. 해당 객체가 Object라는 것.
</script>
가장 먼저 보이는 둘의 차이점은 .keys() 는 Object 객체의 property인 keys 메서드를 호출하여 매개변수로 객체를 전달해(Object.keys(arr)) 사용했다는 점,
.prototype.toString()은 Object객체의 property 메서드에 매개변수로 출력할 객체를 전달하는 것이 아니라 하위객체(Object 객체의 인스턴스를 선언한 변수 o)에서 Object의 prototype을 상속받아 (o.toString()) 사용했다는 점이다.
우선 Object.keys() 예제에서
let o = new Object(); 이 부분을 보면 Object는 생성자 함수임을 알 수 있다.
또, 자바스크립트에서 함수는 객체이기 때문에 property(속성)를 가질 수 있다.
즉, Object라는 생성자 함수 안에 있는 property인 keys 메서드를 호출하여 사용하는 것이다.
Object.prototype.toString() 은 위의 설명을 참고하여 볼 수 있다.
Object객체의 toString() 메서드는
최상위 객체 Object의 property인 prototype의 property, 즉, toString() 메서드를 호출하는 것이 동작 원리이다.
Object 확장
Object 객체는 최상위 부모 객체이기 때문에 Object가 갖고 있는 property들은 자식 객체들이 모두 사용 가능하다.
따라서 모든 객체에서 사용되길 원하는 기능이 있을 경우 Object 객체를 확장, 즉, Object 객체에 원하는 기능을 property로 추가하는 것으로 가능하다.
예를 들어 매개변수로 전달된 값이 객체에 들어있는지 여부를 boolean 타입으로 반환하는 contain 함수를 모든 객체에서 사용할 수 있도록 만들고 싶은 경우 contain 함수를 Object객체에 property로 추가하면 된다.
<script>
Object.prototype.contain = function(needle){
for(let name in this) {
if(this[name] === needle){
return true;
}
}
return false;
}
</script>
하지만 Object를 확장하여 사용하는 것은 좋지 않다.
Object 객체는 모든 객체 (하위 객체들) 에 영향을 미치기 때문이다.
극단적인 예로 위처럼 contain 함수를 임의로 Object 객체에 추가했을 시 for~in 반복문으로 어떤 객체를 출력하면 Object의 property인 contain 메서드 값 까지 출력되어버린다.
ex)
<script>
Object.prototype.contain = function(neddle) {
for(var name in this){
if(this[name] === neddle){
return true;
}
}
return false;
}
var o = {'name':'egoing', 'city':'seoul'}
console.log(o.contain('egoing'));
var a = ['egoing','leezche','grapittie'];
console.log(a.contain('leezche'));
for(var name in o){
console.log(name);
}
// name의 value, contain의 value가 출력된다.
</script>
하지만 꼭 이렇게 Object를 확장하여 사용하고 싶다면 방법이 없는 것은 아니다.
<script>
for(var name in o){
if(o.hasOwnProperty(name))
console.log(name);
}
// name 을 자기자신의 직접 property로 가지는 o 객체의 name 값만 출력된다.
</script>
위처럼 객체가 직접 가지는 property만을 걸러내는 hasOwnProperty 메서드를 사용하면 Object에 확장시킨 값은 제외된 원하는 값을 얻을 수 있다.