if (key in object) หรือ if (object.hasOwnProperty (key)


173

สองข้อความต่อไปนี้สร้างเอาต์พุตเดียวกันหรือไม่? มีเหตุผลใดที่จะชอบอีกทางหนึ่ง?

 if (key in object)

 if (object.hasOwnProperty(key))

คำตอบ:


181

ระวัง - พวกเขาจะไม่ให้ผลลัพธ์เดียวกัน

inนอกจากนี้ยังจะกลับมาtrueถ้าkeyได้รับที่ไหนสักแห่งที่พบในห่วงโซ่ต้นแบบในขณะที่Object.hasOwnProperty(เช่นชื่อที่มีอยู่แล้วบอกเรา) เพียงจะกลับมาtrueถ้าkeyมีอยู่ในวัตถุที่โดยตรง (ของ "เจ้าของ" ทรัพย์สิน)


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"})
I Hate Lazy

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

สรุป:

  • ในตัวดำเนินการส่งคืนจริงเสมอถ้าคุณสมบัติสามารถเข้าถึงได้โดยวัตถุโดยตรงหรือจากต้นแบบ

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

... สร้างผลลัพธ์เดียวกันคำตอบนั้นชัดเจนขึ้นอยู่กับ


28

inhasOwnPropertyนอกจากนี้ยังจะตรวจสอบคุณสมบัติได้รับมรดกซึ่งไม่ได้เป็นกรณีที่


25

โดยสรุปhasOwnProperty()ไม่ดูในต้นแบบขณะที่inดูในต้นแบบ

นำมาจากJavascript ประสิทธิภาพสูงของ 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 () จะคืนค่าจริงเมื่อมีการส่ง“ ชื่อเรื่อง” เนื่องจากชื่อเรื่องเป็นอินสแตนซ์ของวัตถุ เมธอดจะส่งคืนค่าเท็จเมื่อส่งผ่าน“ toString” เนื่องจากไม่มีอยู่ในอินสแตนซ์ เมื่อแต่ละชื่อคุณสมบัติถูกใช้กับตัวดำเนินการ 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
}

ฉันเรียนรู้เคล็ดลับที่ยอดเยี่ยมที่นี่


1
รายละเอียดเพิ่มเติมเขียน: ryanmorr.com/true-hash-maps-in-javascript
darcher

2

รูปแบบอื่น ๆ (เรียกว่าสำหรับ) ระบุชื่อคุณสมบัติ (หรือคีย์) ของวัตถุ ในแต่ละการวนซ้ำสตริงชื่อคุณสมบัติอื่นจากวัตถุถูกกำหนดให้กับตัวแปร โดยปกติแล้วมันเป็นสิ่งจำเป็นในการทดสอบ object.hasOwnProperty (ตัวแปร) เพื่อตรวจสอบว่าชื่อคุณสมบัติเป็นสมาชิกของวัตถุอย่างแท้จริงหรือถูกค้นพบแทนบนสายโซ่ต้นแบบ

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

(จากJavascriptของ Crockford : ส่วนที่ดี )


5
inผู้ประกอบการมีความแตกต่างกว่าfor-inคำสั่ง
ฉันเกลียด Lazy

จริงๆแล้วทั้งคู่เป็นคำที่แตกต่างกันในคำหลัก
Jahan

4
ใช่inเป็นคำหลัก แต่ OP กำลังถามเกี่ยวกับการใช้งานเฉพาะในฐานะinผู้ให้บริการ คำตอบของคุณเกี่ยวข้องกับการใช้งานอื่น ๆ ซึ่งเป็นส่วนหนึ่งของfor-inคำชี้แจง
ฉันเกลียด Lazy

-3

รุ่นแรกสั้นกว่า (โดยเฉพาะในรหัสย่อที่ตัวแปรจะถูกเปลี่ยนชื่อ)

a in b

VS

b.hasOwnProperty(a)

อย่างไรก็ตามตามที่ @AndreMeinhold กล่าวว่าพวกเขาไม่ได้ให้ผลลัพธ์ที่เหมือนกันเสมอไป


1
น่าจะดีกว่าถ้ามีความคิดเห็นนี้ :-)
Hlawuleka MAS
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.