if(オブジェクト内のキー)またはif(object.hasOwnProperty(key)


173

次の2つのステートメントは同じ出力を生成しますか?ある方法を他の方法よりも好む理由はありますか?

 if (key in object)

 if (object.hasOwnProperty(key))

回答:


181

注意してください-同じ結果は得られません。

inプロトタイプチェーンのどこかで見つかったtrue場合も返されますkeyが、(名前がすでに教えているように)、そのオブジェクトで直接利用できる場合にのみ返されます(プロパティを「所有」している)。Object.hasOwnPropertytruekey


3
正確にはどういう意味ですかin will also return true if key gets found somewhere in the prototype chain。あなたは例を書くことができますか?ありがとう。
ロレーヌバーナード

44
@Lor:({foo:"bar"}).hasOwnProperty("toString")vs"toString" in ({foo:"bar"})
私はレイジーが嫌いです

68

別の例で説明しようと思います。次の2つのプロパティを持つオブジェクトがあるとします。

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

最後に:

したがって、これらの2つの条件についての記述について...

if (key in object)
if (object.hasOwnProperty(key))

...同じ結果が得られますが、答えは明白です。


28

inは継承されたプロパティもチェックしますが、これはには当てはまりませんhasOwnProperty


25

要約すると、hasOwnProperty()はプロトタイプをin調べている間、プロトタイプを調べません。

O'Reilly High Performance Javascriptから取得

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

このコードでは、titleがオブジェクトインスタンスであるため、「title」が渡されると、hasOwnProperty()はtrueを返します。インスタンスに存在しないため、「toString」が渡されると、メソッドはfalseを返します。各プロパティ名をin演算子で使用すると、インスタンスとプロトタイプが検索されるため、結果は両方ともtrueになります。


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

もう1つの形式(呼び出される)は、オブジェクトのプロパティ名(またはキー)を列挙します。各反復で、オブジェクトの別のプロパティ名文字列が変数に割り当てられます。通常、object.hasOwnProperty(variable)をテストして、プロパティ名が本当にオブジェクトのメンバーであるか、プロトタイプチェーンで検出されたかを判断する必要があります。

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

(クロックフォードのJavascriptから:良い部分


5
inオペレータはより異なっているfor-in声明。
私はレイジーが嫌いだ

実際には、どちらもキーワードの使用方法が異なります
Jahan

4
はい、inキーワードです。しかし、OPはinオペレーターとして特定の使用法について尋ねています。あなたの答えはfor-inステートメントの一部として他の使用法を扱います。
私はレイジーが嫌いだ

-3

最初のバージョンは短くなっています(特に、変数の名前が変更された縮小コードでは)

a in b

b.hasOwnProperty(a)

とにかく、@ AndreMeinholdが言ったように、それらは常に同じ結果を生成するわけではありません。


1
コメントとしてこれを持っていた方がいいでしょう。:-)
Hlawuleka MAS 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.