in
키워드 (자체 속성과 프로토타입 체인 속성 모두에서 포함 여부 확인)in
키워드는 객체에 해당 속성이 존재하는지 확인할 때 사용한다. 이때 해당 속성이 객체 자체에 있든, 객체의 프로토타입 체인에 있든 상관없이 검사한다.
const obj = { a: 1 };
console.log('a' in obj); // true (a는 obj 객체 자체 속성)
console.log('toString' in obj); // true (toString은 프로토타입 체인에 존재하는 속성)
hasOwnProperty
메서드 (자체 속성에서만 포함 여부 확인)hasOwnProperty
는 객체의 자신의 속성만을 검사한다. (프로토타입 체인은 검사하지 않는다.)
const obj = { a: 1 };
console.log(obj.hasOwnProperty('a')); // true
console.log(obj.hasOwnProperty('toString')); // false (프로토타입에 존재)
하지만 다음과 같이 프로토타입 체인에 이미 존재하는 속성을 다시 정의할 경우 속성이 덮어쓰기 된다. 이러한 현상을 ‘쉐도잉’이라고 한다.
const obj = {
// 언제나 true 를 반환하도록 재정의 (쉐도잉)
hasOwnProperty(){
return true;
}
}
console.log(obj.hasOwnProperty('toString')); // true
위 코드에서 obj
객체 자체에는 toString
이 없으므로 false
가 출력되어야 하지만 hasOwnProperty
가 항상 true
를 반환하도록 재정의되었기 때문에 true
가 출력된다.
이는 다음과 같은 버그를 초래할 수 있다.
만약 클라이언트가 서버에게 JSON 형태의 데이터를 전달하고, parse 된 JSON 객체를 참조한다고 가정해보자.
{ "hasOwnProperty": 1 }
const json = `{"hasOwnProperty": 1, "id" : 1}`
const parse = JSON.parse(json);
parse.hasOwnProperty("id") // TypeError: parse.hasOwnProperty is not a function
위 코드를 보면 쉐도잉이 발생해 parse 객체의 hasOwnProperty 메서드를 사용할 수 없는 것을 확인할 수 있다.
위와 같은 상황을 방지하고 싶다면, hasOwnProperty
를 사용하는 대신 Object.prototype.hasOwnProperty.call()
메서드를 사용하자.
const json = `{"hasOwnProperty": 1, "id" : 1}`
const parse = JSON.parse(json);
Object.prototype.hasOwnProperty.call(parse, 'id'); // true
Object.prototype.hasOwnProperty.call(parse, 'toString'); // false
Function
객체의 메서드인 call
메서드를 사용하면 첫 번째 인자를 this
로 하고, 나머지 인자에 함수에 전달할 인자들을 전달하여 함수를 호출할 수 있다.
위 코드에서는 parse
를 this
로 하여 hasOwnProperty
를 호출하는 것이고 인자로 id
와 toString
을 넘겨 parse
에 id
와 toString
속성이 존재하는지 확인하고 있다.
Object.hasOwn
(ES2022+)Object.hasOwn
은 hasOwnProperty
와 동일하게 객체 자신의 속성만 검사한다. 하지만, Object.hasOwn
은 정적 메서드로 인스턴스에 바인딩되지 않고 클래스에 바인딩 되기 때문에 쉐도잉으로부터 안전하다.
const obj = {
// 언제나 true 를 반환하도록 재정의 (쉐도잉)
hasOwnProperty() {
return true;
},
};
console.log(Object.hasOwn(obj, "toString")); // false
Object.hasOwn
메서드는 ES2022에 도입된 기능이므로 브라우저 호환성을 고려해서 사용해야 한다.