[javascript] if (객체 입력) 또는 if (object.hasOwnProperty (key)

다음 두 문장은 같은 결과를 낳습니까? 다른 방법을 선호하는 이유가 있습니까?

 if (key in object)

 if (object.hasOwnProperty(key))



답변

조심하십시오-동일한 결과를 얻지 못합니다.

in또한 프로토 타입 체인 어딘가에 true있으면 이름 을 반환 하지만 (이름이 이미 알려 주듯이) 해당 개체에서 직접 사용할 수있는 경우 에만 (속성 “소유”) 반환 합니다 .keyObject.hasOwnPropertytruekey


답변

다른 예를 들어 설명하려고합니다. 두 가지 속성을 가진 다음 객체가 있다고 가정 해보십시오.

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가 말했듯이 항상 동일한 결과를 생성하지는 않습니다.