in 연산자는 객체가 속한 프로토타입 체인 상에 존재하는 모든 프로토타입에서 프로퍼티가 존재하는지 확인한다.
const person = {
name: 'Lee',
address: 'Seoul'
};
console.log('name' in person); //true
console.log('toString' in person); //true
위 코드에서 toString이 person객체의 프로퍼티라고 나오는 이유는 프로토타입 체인을 통해 Object.prototype인 toString을 검색했기 때문이다.
반면에 hasOwnProperty는 인수로 전달한 키가 객체 고유의 프로퍼티 키인 경우에만 true를 반환하므로 toString을 전달하게되면 false가 나온다.
console.log(person.hasOwnProperty('toString')); // false
for...in 문은 프로퍼티를 열거하는 구문이다. 정확하게 표현하자면 다음과 같다.
for...in문은 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티 중에서 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 true인 프로퍼티를 순회하며 열거한다.
그렇기 때문에 만일 객체 고유의 프로퍼티를 열거하고 싶다면 hasOwnProperty를 사용해서 검증해야한다.
const person = {
name: 'Lee',
address: 'Seoul',
__proto__: { age: 20 }
};
for (const key in person) {
if(!person.hasOwnProperty(key)) continue;
console.log(key + ': ' + person[key]);
}
만일 객체 자신의 고유 프로퍼티만 열거하기 위해서는 Object.keys/values/entries 메서드를 사용하는 것이 좋다.