2016-10-31 21 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演算子とほとんど同じですが、1つの違いがあります。プロトタイプチェーンをチェックしません。前の例を書き換えることができます:

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

これは期待どおりに動作します。残念ながら、hasOwnProperty()も1つのケースで失敗する可能性があります。もし私たちが自分の財産のオブジェクトを持っていたら、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

機能は、いくつかのプロパティで何かを受け入れる場合 - それはプロトタイプチェーン内のプロパティが定義されている事業であってもよいが、それだけで利用可能だということではないはずです。こうすることで、実装の詳細からデータシェイプを分離できます。 – zerkms

答えて

2

特徴検出、in演算子を使用してなど

を現代のDOM APIを使用するための試験条件は、プロトタイプチェーンをチェックするので、あなたは正確にJavaScriptのポリフィルを実行/ロードするかどうかを評価するための理想的です。例えば

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

したがってthe Polyfill.io serviceその特徴検出試験のためにそれを使用する理由:に比べ

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

4

あなたはあなた自身の質問に答えます。 inは、プロトタイプチェーンでも検索したいときに便利です。ロードpolyfillsため

+1

amdouglasの回答のように、特定のユースケースを探しています。 –

4

inはオペレータであり、ハイジャックすることはできません。あなたは、スクリプトが変更されていたり、影がついていることに頼る必要はありません。ObjectObject.prototypeObject.prototype.hasOwnPropertyObject.prototype.hasOwnProperty.call

オブジェクトに何らかのプロパティがあるかどうかを知るための簡単な方法です。 obj.fooが返品できる場合は、 "bar"fooプロパティが継承されていても、にその属性があるかどうかを事前に知ることができます。

確かに、HasOwnPropertyがあれば、チェーンの終わりまで[(GetPrototypeOf])を呼び出して(通常は)各オブジェクトをチェックすることができます。しかし、それはおそらくネイティブのinより遅く、おそらくES5の前ではコード化するのが面倒です。

また、基本的な違いがあります。 in演算子は[[HasProperty]]内部メソッドを使用し、HasOwnPropertyは[[GetOwnProperty]]を使用します。 [[GetOwnProperty]]と[[GetPrototypeOf]]を反復すると、非普通のオブジェクトに対して[[HasProperty]]とは異なる結果が生成されることがあります。

はい:in演算子は、オブジェクトの内部[[HasProperty]]メソッドを呼び出すときに便利です。実際には、Reflect.hasを除いて、それを行う唯一の正しい方法です。多くの場合

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

関連する問題