다음 두 문장은 같은 결과를 낳습니까? 다른 방법을 선호하는 이유가 있습니까?
if (key in object)
if (object.hasOwnProperty(key))
답변
조심하십시오-동일한 결과를 얻지 못합니다.
in
또한 프로토 타입 체인 어딘가에 true
있으면 이름 을 반환 하지만 (이름이 이미 알려 주듯이) 해당 개체에서 직접 사용할 수있는 경우 에만 (속성 “소유”) 반환 합니다 .key
Object.hasOwnProperty
true
key
답변
다른 예를 들어 설명하려고합니다. 두 가지 속성을 가진 다음 객체가 있다고 가정 해보십시오.
function TestObj(){
this.name = 'Dragon';
}
TestObj.prototype.gender = 'male';
TestObj의 인스턴스를 만들어 봅시다 :
var o = new TestObj();
객체 인스턴스를 살펴 보자.
console.log(o.hasOwnProperty('name')); // true
console.log('name' in o); // true
console.log(o.hasOwnProperty('gender')); // false
console.log('gender' in o); // true
결론:
-
in 연산자는 객체가 직접 또는 프로토 타입에서 속성에 액세스 할 수있는 경우 항상 true를 반환합니다.
-
hasOwnProperty () 속성이 인스턴스에 있지만 프로토 타입에는없는 경우에만 true를 반환합니다.
프로토 타입에 일부 속성이 논리적으로 존재하는지 확인하려면 다음과 같이 말합니다.
console.log(('name' in o) && !o.hasOwnProperty('name')); //false
console.log(('gender' in o) && !o.hasOwnProperty('gender')); //true - it's in prototype
드디어:
따라서이 두 가지 조건은 …
if (key in object)
if (object.hasOwnProperty(key))
… 동일한 결과를 만들어 내면 대답은 분명합니다.
답변
in
상속 된 속성도 확인합니다 hasOwnProperty
.
답변
요약 hasOwnProperty()
하면 프로토 타입을 보지 않고 프로토 타입을 in
보지 않습니다.
O’Reilly 고성능 자바 스크립트 에서 발췌 :
hasOwnProperty () 메소드를 사용하고 멤버 이름을 전달하여 오브젝트에 지정된 이름의 인스턴스 멤버가 있는지 여부를 판별 할 수 있습니다. 객체가 주어진 이름으로 속성에 액세스 할 수 있는지 확인하려면 in 연산자를 사용할 수 있습니다. 예를 들면 다음과 같습니다.
var book = {
title: "High Performance JavaScript",
publisher: "Yahoo! Press"
};
alert(book.hasOwnProperty("title")); //true
alert(book.hasOwnProperty("toString")); //false
alert("title" in book); //true
alert("toString" in book); //true
이 코드에서 hasOwnProperty ()는 title이 객체 인스턴스이므로 “title”이 전달되면 true를 반환합니다. “toString”이 인스턴스에 없기 때문에 전달되면 메소드는 false를 리턴합니다. 각 속성 이름을 in 연산자와 함께 사용하면 인스턴스와 프로토 타입을 검색하기 때문에 결과가 모두 참입니다.
답변
정말 좋은 답변이 있습니다. 객체를 반복하면서 “hasOwnProperty”를 확인할 필요가없는 무언가를 제공하고 싶습니다.
객체를 만들 때 일반적으로 사람들은 다음과 같은 방식으로 객체를 만듭니다.
const someMap = {}
// equivalent to: Object.create(Object.prototype)
// someMap.constructor will yield -> function Object() { [native code] }
이제 “someMap”을 반복하려면 다음과 같이해야합니다.
const key
for(key in someMap ){
if (someMap.hasOwnProperty(key)) {
// Do something
}
}
상속 된 속성에 대한 반복을 피하기 위해 그렇게하고 있습니다.
“맵”(즉, 키-값 쌍)으로 만 사용될 간단한 객체를 만들려면 다음과 같이 할 수 있습니다.
const newMap = Object.create(null);
// Now, newMap won't have prototype at all.
// newMap.constructor will yield -> undefined
이제 다음과 같이 반복하는 것이 안전합니다.
for(key in cleanMap){
console.log(key + " -> " + newMap [key]);
// No need to add extra checks, as the object will always be clean
}
나는이 멋진 팁을 여기서 배웠습니다.
답변
다른 형식 (in에서 호출)은 객체의 속성 이름 (또는 키)을 열거합니다. 각 반복에서 오브젝트의 다른 특성 이름 문자열이 변수에 지정됩니다. 일반적으로 object.hasOwnProperty (variable)을 테스트하여 속성 이름이 실제로 객체의 멤버인지 아니면 프로토 타입 체인에서 찾은지를 확인해야합니다.
for (myvar in obj) {
if (obj.hasOwnProperty(myvar)) { ... } }
(Crockford의 Javascript : 좋은 부분에서 )
답변
첫 번째 버전은 더 짧습니다 (특히 변수의 이름이 바뀌는 축소 코드에서)
a in b
vs
b.hasOwnProperty(a)
어쨌든 @AndreMeinhold가 말했듯이 항상 동일한 결과를 생성하지는 않습니다.
