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


173

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

 if (key in object)

 if (object.hasOwnProperty(key))

답변:


181

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

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


3
정확히 무엇을 의미합니까 in will also return true if key gets found somewhere in the prototype chain. 예를 들어 줄 수 있습니까? 감사.
Lorraine Bernard

44
@Lor : ({foo:"bar"}).hasOwnProperty("toString")vs"toString" in ({foo:"bar"})
게으름을

68

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

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))

... 동일한 결과를 만들어 내면 대답은 분명합니다.



25

요약 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 연산자와 함께 사용하면 인스턴스와 프로토 타입을 검색하기 때문에 결과가 모두 참입니다.


5

정말 좋은 답변이 있습니다. 객체를 반복하면서 "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
}

나는이 멋진 팁을 여기서 배웠습니다.



2

다른 형식 (in에서 호출)은 객체의 속성 이름 (또는 키)을 열거합니다. 각 반복에서 오브젝트의 다른 특성 이름 문자열이 변수에 지정됩니다. 일반적으로 object.hasOwnProperty (variable)을 테스트하여 속성 이름이 실제로 객체의 멤버인지 아니면 프로토 타입 체인에서 찾은지를 확인해야합니다.

 for (myvar in obj) {
     if (obj.hasOwnProperty(myvar)) { ... } }

(Crockford의 Javascript : 좋은 부분에서 )


5
in운영자는 다릅니다 for-in문.
나는 게으른 증오

실제로 둘 다 키워드의 사용법이 다릅니다
Jahan

4
예, in키워드입니다. 그러나 OP는 in운영자 로서 특정 용도에 대해 묻고 있습니다. 귀하의 답변은 for-in명세서의 일부로 다른 사용법을 다룹니다 .
나는 게으른 증오

-3

첫 번째 버전은 더 짧습니다 (특히 변수의 이름이 바뀌는 축소 코드에서)

a in b

vs

b.hasOwnProperty(a)

어쨌든 @AndreMeinhold가 말했듯이 항상 동일한 결과를 생성하지는 않습니다.


1
이것을 주석으로 사용하는 것이 좋을 것입니다. :-)
Hlawuleka MAS
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.