2016-10-31 10 views
3

JavaScript에서 in 연산자는 개체에 지정된 속성이 있는지 확인합니다. 그러나 객체의 자체 속성뿐만 아니라 프로토 타입 체인도 검사하지 않습니다. 따라서 어떤 경우에는 예상대로 작동하지 않을 수 있습니다. 그 객체가 in 연산자를 사용하여 키와 같은 특정 방법이있는 경우hasOwnProperty() 대신 in 연산자를 사용해야하는 경우가 있습니까?

const someArrayMethods = { 
    indexOf: true, 
    map: true, 
}; 

우리는 확인할 수 있습니다

의 우리가 객체 someArrayMethods (분명히)를 포함하는 키와 같은 일부 배열 방법이 어떤 이유로 그런 말을 보자 :

console.log('indexOf' in someArrayMethods); // true 
console.log('every' in someArrayMethods); // false 

toString 속성을 확인하려고하면 어떻게됩니까?

console.log('toString' in someArrayMethods); // true 

서프라이즈! 이 개체는 프로토 타입 체인에 toString method이 있으므로 개체에 자체 toString 속성이 없더라도 in 연산자는 true을 반환합니다.

그리고 여기서 hasOwnProperty()이 구해줍니다! 한 가지 차이점을 제외하면 in 연산자와 거의 같습니다. 프로토 타입 체인을 검사하지 않습니다. 이전 예제를 다시 작성할 수 있습니다.

console.log(someArrayMethods.hasOwnProperty('toString')); // false 

이제 예상대로 작동합니다. 불행하게도 hasOwnProperty()도 하나의 경우에 실패 할 수 있습니다. 우리 자신의 재산이있는 물건을 가지고 있다면 hasOwnProperty? 이 예제 참조 :

const someObject = { 
    hasOwnProperty() { 
    return false; 
    }, 
    theAnswer: 42, 
}; 

// Does `someObject` has own property `theAnswer`? 
console.log(someObject.hasOwnProperty('theAnswer')); // false 
// Well, it seems it doesn't... 

대신 someObject.hasOwnProperty를 사용,이 문제를 해결하기를, 우리는 Object.prototype에서 직접 그 방법을 참조 할 수 있습니다 :

const hasOwn = Object.prototype.hasOwnProperty; 
console.log(hasOwn.call(someObject, 'theAnswer')); // true 

이는 경우 확인을위한 가장 합리적인 접근 방식을 것 같다 객체에는 몇 가지 속성이 있습니다. 그럼에도 불구하고 in 연산자가 유용 할 수있는 경우가 있습니까? 어떤 클래스의 인스턴스에 어떤 메소드가 있는지 확인하는 데 사용할 수는 있지만이 경우 해당 오브젝트가 해당 클래스의 인스턴스인지 단순히 확인하는 것이 더 좋지 않습니까? 보조 노트로


또 다른 옵션은 ECMAScript를 2016 Array.prototype.includes()Object.keys()을 사용하는 것입니다

console.log(Object.keys(someObject).includes('theAnswer')); // true 
+0

var p = new Proxy({}, {has: function() { console.log('Hooray!'); return true; }}); p.hasOwnProperty('foo'); // :( 'foo' in p; // Hooray! :)

이 기능은 일부 속성이 무엇인가를 허용합니다. 이렇게하면 데이터 모양과 구현 세부 사항을 구분할 수 있습니다. – zerkms

답변

2

특징 검출의 in 운영자는로드할지 여부를 평가하기위한 이상적인 사용 등

현대 DOM API를 사용하기위한 조건을 테스트/정밀 자바 스크립트 polyfill을 실행합니다.예컨대

:

// this works wonderfully 
if (!('addEventListener' in window)) { 
    // polyfill addEventListener 
} 

비교 :

// this doesn't work at all 
if (!window.hasOwnProperty('addEventListener')) { 
    // polyfill addEventListener 
} 

the Polyfill.io service 따라서 그 형상 검출 시험을 사용하는 이유.

4

당신은 당신의 자신의 질문에 대답합니다. in은 프로토 타입 체인에서도 검색 할 때 유용합니다. 이 프로토 타입 체인을 확인하기 때문에 로딩 polyfills에 대한

+1

amdouglas의 답변과 같이 구체적인 사용 사례를 찾고 있습니다. –

4

in은 조작자이므로 하이재킹 될 수 없습니다. 스크립트가 변경되었거나 그림자가 없다는 것에 의존 할 필요가 없습니다. Object, Object.prototype, Object.prototype.hasOwnProperty, Object.prototype.hasOwnProperty.call.

그리고 개체에 속성이 있는지를 빠르게 알 수 있습니다. 예를 들어, obj.foo이 반환 할 수 있다면 "bar"foo 속성이 상속 되더라도, 에 해당 속성이 있는지 여부를 미리 알 수있는 것이 좋습니다. 자신 또는 상속 된 속성입니다.

물론 HasOwnProperty 만있는 경우 체인의 끝까지 [[GetPrototypeOf]]를 계속 호출하여 각 개체를 확인할 수 있습니다. 하지만 이는 코드 작성이 번거롭고 기본 in보다 느리고 아마 ES5 이전에는 불가능합니다.

또한 근본적인 차이가 있습니다. in 연산자는 [[HasProperty]] 내부 메소드를 사용하고 HasOwnProperty는 [[GetOwnProperty]]를 사용합니다. [[GetOwnProperty]]와 [[GetPrototypeOf]]를 반복하면 비정상적인 객체의 경우 [[HasProperty]]와 다른 결과가 발생할 수 있습니다.

그래서 예 : in 연산자는 개체의 내부 [[HasProperty]] 메서드를 호출 할 때 유용합니다. 사실, Reflect.has을 제외하고는, 그것을하는 유일한 방법입니다. 이 프로토 타입 체인에 속성이 정의되어 사업 안하지만 그냥 사용할 수 있음 - 대부분의 경우