ฉันจะตรวจสอบว่าวัตถุมีคุณสมบัติเฉพาะใน JavaScript ได้อย่างไร


1486

ฉันจะตรวจสอบว่าวัตถุมีคุณสมบัติเฉพาะใน JavaScript ได้อย่างไร

พิจารณา:

x = {'key': 1};
if ( x.hasOwnProperty('key') ) {
    //Do this
}

นั่นเป็นวิธีที่ดีที่สุดที่จะทำหรือไม่?


21
ฉันเขียนการทดสอบ jsperf พร้อมคำตอบของทุกคนเพื่อดูว่าเร็วที่สุด: jsperf.com/dictionary-contain-key
styfle

('propertyName' ใน Object)? 'property is there': 'property is not there'
Mohan Ram

1
@styfle ขอบคุณสำหรับการทดสอบ jsperf inและวิธีการhasOwnPropertyออกมาช้ากว่าคนอื่นสำหรับฉัน (ช้าลง 98%) ผมไม่แปลกใจเกี่ยวกับการเป็นช้า แต่ฉันประหลาดใจเกี่ยวกับ hasOwnPropertyin
evanrmurphy

คำตอบ:


1424

ฉันสับสนมากกับคำตอบที่ได้รับ - ส่วนใหญ่ไม่ถูกต้อง แน่นอนคุณสามารถมีคุณสมบัติของวัตถุที่มีค่าไม่ได้กำหนดเป็นโมฆะหรือเท็จ ดังนั้นเพียงแค่ลดการตรวจสอบคุณสมบัติไปที่typeof this[property]หรือยิ่งแย่ลงx.keyจะให้ผลลัพธ์ที่ทำให้เข้าใจผิดอย่างสมบูรณ์

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

หากสิ่งที่คุณกำลังมองหาคือถ้าวัตถุมีคุณสมบัติที่สามารถทำซ้ำได้ (เมื่อคุณวนซ้ำคุณสมบัติของวัตถุนั้นจะปรากฏขึ้น) จากนั้นทำ: prop in objectจะให้ผลที่คุณต้องการ

เนื่องจากการใช้hasOwnPropertyอาจเป็นสิ่งที่คุณต้องการและการพิจารณาว่าคุณอาจต้องการวิธีสำรองฉันจึงเสนอวิธีแก้ไขปัญหาต่อไปนี้แก่คุณ:

var obj = {
    a: undefined,
    b: null,
    c: false
};

// a, b, c all found
for ( var prop in obj ) {
    document.writeln( "Object1: " + prop );
}

function Class(){
    this.a = undefined;
    this.b = null;
    this.c = false;
}

Class.prototype = {
    a: undefined,
    b: true,
    c: true,
    d: true,
    e: true
};

var obj2 = new Class();

// a, b, c, d, e found
for ( var prop in obj2 ) {
    document.writeln( "Object2: " + prop );
}

function hasOwnProperty(obj, prop) {
    var proto = obj.__proto__ || obj.constructor.prototype;
    return (prop in obj) &&
        (!(prop in proto) || proto[prop] !== obj[prop]);
}

if ( Object.prototype.hasOwnProperty ) {
    var hasOwnProperty = function(obj, prop) {
        return obj.hasOwnProperty(prop);
    }
}

// a, b, c found in modern browsers
// b, c found in Safari 2.0.1 and older
for ( var prop in obj2 ) {
    if ( hasOwnProperty(obj2, prop) ) {
        document.writeln( "Object2 w/ hasOwn: " + prop );
    }
}

ด้านบนคือการทำงานข้ามเบราว์เซอร์วิธีแก้ปัญหาhasOwnPropertyด้วยข้อแม้หนึ่งข้อ: มันไม่สามารถแยกแยะระหว่างกรณีที่มีคุณสมบัติที่เหมือนกันอยู่บนต้นแบบและบนอินสแตนซ์ - เพียงแค่สมมติว่ามันมาจากต้นแบบ คุณสามารถเปลี่ยนเป็นผ่อนปรนหรือเข้มงวดมากขึ้นตามสถานการณ์ของคุณ แต่อย่างน้อยที่สุดสิ่งนี้ควรมีประโยชน์มากกว่า


5
@grantwparks หากคุณกำลังสร้างปลั๊กอินตัวเลื่อนแบบง่ายและต้องการตรวจสอบว่ามีรายการตัวเลือกอยู่จริงนี่อาจเป็นสิ่งที่จำเป็นมากกว่า var w = opts.w || 100;คุณก็สามารถทำสิ่งที่ชอบ แต่ถ้าคุณเข้าห้องสมุดบางอย่างคุณอาจต้องไปไกลกว่านั้นในบางส่วน
Halil Özgür

@ kralco626: ใช่ทุกวันนี้ฉันรู้สึกว่ามันปลอดภัยที่จะไปกับ hasOwnProperty () - แต่สำหรับโซลูชันข้ามเบราว์เซอร์ที่ปลอดภัยอย่างแท้จริงไปกับ John's
จาค็อบ

สิ่งที่เกี่ยวกับการเปลี่ยนเป็นโมฆะชั่วคราว__proto__ ? Simple impl: function hasOwnProperty(obj, prop) { var temp = obj.__proto__; obj.__proto__ = null; var ret = prop in obj; obj.__proto__ = temp; return ret; }( obj.constructor.prototypeควรเพิ่มCase ด้วย)
ค่าเฉลี่ย Joe

2
@Kasztan __proto__ไม่ได้มาตรฐานและไม่สามารถใช้งานได้ในเบราว์เซอร์รุ่นเก่า และถึงแม้จะมีการเพิ่มObject.getPrototypeOfมาตรฐานล่าสุดกล่าวว่าคุณยังไม่สามารถเปลี่ยนต้นแบบของวัตถุที่มีอยู่ได้
Matt Browne

13
for(prop in object)ห่วง iterates คุณสมบัติเฉพาะนับ อย่างไรก็ตามprop in objectตรวจสอบว่าobjectมีคุณสมบัติpropบางแห่งในห่วงโซ่ต้นแบบไม่ขึ้นอยู่กับว่ามันนับได้หรือไม่
Oriol

283

ด้วยUnderscore.jsหรือ ( ดียิ่งขึ้น ) lodash:

_.has(x, 'key');

สายใดObject.prototype.hasOwnPropertyแต่ (ก) สั้นกว่าที่จะพิมพ์และ (b) ใช้ "การอ้างอิงที่ปลอดภัยถึงhasOwnProperty" (นั่นคือทำงานได้แม้ว่าhasOwnPropertyจะถูกเขียนทับ)

โดยเฉพาะอย่างยิ่ง lodash กำหนด_.hasเป็น:

   function has(object, key) {
      return object ? hasOwnProperty.call(object, key) : false;
   }
   // hasOwnProperty = Object.prototype.hasOwnProperty

52
ฉันเดาว่าเป็นเพราะ "เพิ่มห้องสมุดนี้" เป็นคำตอบที่ได้รับความนิยมน้อยมากแม้ว่าคำถามจะเกี่ยวกับการจัดการ DOM ที่ซับซ้อนและคำตอบคือ "go use jQuery"
Winfield Trail

11
ฉันเห็นจุดของคุณ @ เจ้าของแล้วขอบคุณ หากมีใครไม่ชอบที่จะรวมทั้ง lodash ไลบรารี่ทั้งหมดก็สามารถคอมไพล์ย่อยหรือnpm install lodash.hasแสดงโมดูล npm ที่มีเพียงhasฟังก์ชั่นที่คอมไพล์ลงไปที่ 175 ไบต์เมื่อลดขนาดลง นอกจากนี้ยังเป็นเรื่องที่ชาญฉลาดที่จะตรวจสอบlodash.has/index.jsเพื่อดูว่าห้องสมุดที่ได้รับความนิยมและน่าเชื่อถือนั้นทำงานอย่างไร
Brian M. Hunt

9
และlodashเวอร์ชันของใช้งานได้กับ: .has(undefined, 'someKey') => falseในขณะที่underscoreส่งคืนundefined
Brad Parks

13
สำหรับทุกคนที่กำลังพูดถึงเรื่องการเพิ่มlodashว่าเป็นการพึ่งพา "แต่อีกอย่าง": มันเป็นเรื่องธรรมดา (ถ้าไม่ใช่เรื่องธรรมดาที่สุด) สำหรับห้องสมุดประเภทนี้ ขอให้สนุกคิดค้นล้อใหม่
Priidu Neemre

11
แม้ว่าคุณต้องการที่จะบูรณาการล้อการตรวจสอบล้อที่มีอยู่ไม่ได้เป็นความคิดที่ดี
AturSams

147

เกี่ยวกับอะไร

var x = {'key': 1};

if ('key' in x) {
    console.log('has');
}

13
เพียงแค่ต้องทราบมันทำงานกับ 'วัตถุ' ในความรู้สึกแคบดังนั้นประกาศเป็น {} หรือสร้างขึ้นโดยใช้ตัวสร้างมันไม่ยอมรับอาร์เรย์หรือดั้งเดิม ไม่ใช่ว่า OP ต้องการมัน แต่มีคำตอบอื่น ๆ ที่นำเสนอเทคนิคที่กว้างกว่า (ทำงานกับอาร์เรย์, สตริง ฯลฯ )
Danubian Sailor

@ РСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴขอบคุณสำหรับการชี้ให้เห็นว่า (คำตอบที่ได้รับการยอมรับไม่ได้ไปลงรายละเอียดเกี่ยวกับเหตุผลที่คนเราควรจะใช้inประกอบการหรือไม่นอกจากนี้ยังทราบว่า. inผู้ประกอบการได้รับการสนับสนุนเบราว์เซอร์ที่ดีเยี่ยมIE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+ stackoverflow.com/questions/2920765/...
Adrien Be

2
ผู้ประกอบการinยังตรวจสอบกับคุณสมบัติต้นแบบในขณะที่hasOwnPropertyซ้ำคุณสมบัติที่ผู้ใช้กำหนดเท่านั้น การอ้างอิง: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

2
'key' in x ทำทำงานร่วมกับอาร์เรย์ หลักฐาน: stackoverflow.com/questions/33592385/ …
CosmoMyzrailGorynych

ดูเหมือนว่าตัวเลือกที่ดีที่สุดและสั้นที่สุด
user365314

132

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


โปรดจำไว้ว่าundefined(น่าเสียดาย) ไม่ใช่คำสงวนใน JavaScript หากคุณไม่ได้ใช้โหมดเข้มงวด ดังนั้นบางคน (คนอื่นอย่างเห็นได้ชัด) อาจมีความคิดที่ยิ่งใหญ่ในการกำหนดมันใหม่ทำลายรหัสของคุณ

วิธีการที่แข็งแกร่งมากขึ้นจึงเป็นดังต่อไปนี้:

if (typeof(x.attribute) !== 'undefined')

ด้านพลิกวิธีนี้มาก verbose และช้าลง : - /

ทางเลือกที่เหมือนกันคือเพื่อให้แน่ใจว่าundefinedเป็นจริงไม่ได้กำหนดเช่นโดยการใส่รหัสลงในฟังก์ชั่นที่รับพารามิเตอร์เพิ่มเติมที่เรียกว่าundefinedที่ไม่ได้ส่งผ่านค่า เพื่อให้แน่ใจว่ามันไม่ผ่านค่าคุณสามารถเรียกมันด้วยตัวเองได้ทันทีเช่น:

(function (undefined) {
     your code 
    if (x.attribute !== undefined)
         mode code 
})();

6
เพียงแค่อยากรู้อยากเห็นเนื่องจากvoid 0มีการกำหนดให้กลับมาเป็นที่ยอมรับundefinedหนึ่งจะทำx.attribute !== void 0อย่างไร
Brian M. Hunt

1
ไบรอัน: ฉันไม่ใช่ผู้เชี่ยวชาญ แต่ก็แน่ใจว่าดูเหมือนจะเป็นวิธีที่ฉลาดในการทำให้ถูกต้อง
Christopher Smith เมื่อ

37
หาก 'คนอื่น' ที่มีชื่อเสียงได้นิยามใหม่ว่าอะไรคือ undefined คือฉันคิดว่าแนวทางที่ดีที่สุดของการกระทำคือการเขียนรหัสนั้นใหม่
Oskar Holmkratz

3
สิ่งที่ดีที่สุดที่จะมี var ที่ไม่ได้กำหนดคือทำงานภายในการปิดและมีลายเซ็นของฟังก์ชั่นที่ไม่มีใครเทียบ:(function (undefined) { // undefined is actually undefined here })();
bgusach

1
@evanrmurphy อย่าใช้สิ่งนั้นมันล้าสมัยอย่างจริงจัง (ดูหมายเหตุตอนต้นคำตอบของฉัน)
Konrad Rudolph

55
if (x.key !== undefined)

ดูเหมือนว่าArmin Ronacherจะเอาชนะฉันไปแล้ว แต่:

Object.prototype.hasOwnProperty = function(property) {
    return this[property] !== undefined;
};

x = {'key': 1};

if (x.hasOwnProperty('key')) {
    alert('have key!');
}

if (!x.hasOwnProperty('bar')) {
    alert('no bar!');
}

ปลอดภัย แต่การแก้ปัญหาช้าลงเป็นแหลมออกโดยคอนราดรูดอล์ฟและArmin Ronacherจะเป็น:

Object.prototype.hasOwnProperty = function(property) {
    return typeof this[property] !== 'undefined';
};

2
ฉันไม่คิดว่ามันดีพอ x.hasOwnProperty('toString') === true;
Joe Simmons

ไม่ขอให้ไม่เห็นด้วย แต่ให้เข้าใจ มีจุดใดที่ x.hasOwnProperty จะส่งคืนสิ่งใดนอกจากบูลีนจริงหรือเท็จ? มิฉะนั้นรหัสที่โพสต์ควรจะทำงานทุกครั้ง ฉันคิดว่าบางทีถ้าวิธีการนั้นถูกแทนที่ แต่แล้วการพึ่งพาผลลัพธ์จะไม่น่าเชื่อถือเว้นแต่คุณจะรู้วิธีการเอาชนะ
enobrev

1
ฉันคิดว่าเรามีการสื่อสารผิดพลาด ฉันหมายความว่าการใช้วิธีการของคุณมันจะบอกว่า 'toString' เป็นทรัพย์สินของตัวเอง แต่ไม่ใช่
Joe Simmons

3
Object.prototypeมีในตัวถูกต้องhasOwnPropertyแล้ว เขียนทับด้วยการใช้งานที่ไม่ถูกต้อง (1. คุณสมบัติสามารถมีค่าundefinedได้ 2. สิ่งนี้จะให้ผลบวกเป็นเท็จสำหรับคุณสมบัติที่สืบทอดมา) เป็นเพียงแนวคิดที่ไม่ดี คำตอบที่ไม่ถูกต้องสามารถและควรจะถูกลบ ฉันไม่รู้ว่าคุณสามารถทำสิ่งนั้นได้ใน Sep '08 เมื่อคุณเห็นคำตอบของ Resigหรือไม่ดังนั้นการแสดงความคิดเห็นเพื่อแนะนำให้ทำตอนนี้
TJ Crowder

36

คุณสามารถใช้inโอเปอเรเตอร์เพื่อตรวจสอบว่ามีทรัพย์สินอยู่บนวัตถุหรือไม่:

x = {'key': 1};
alert("key" in x);

คุณยังสามารถวนลูปผ่านคุณสมบัติทั้งหมดของวัตถุโดยใช้for - inลูปแล้วตรวจสอบคุณสมบัติเฉพาะ:

for (prop in x) {
    if (prop == "key") {
        //Do something
    }
}

คุณต้องพิจารณาว่าคุณสมบัติของวัตถุนี้นับได้หรือไม่เพราะคุณสมบัติที่ไม่นับจะไม่ปรากฏในfor-inลูป นอกจากนี้หากคุณสมบัติที่นับได้เป็นเงาของคุณสมบัติที่ไม่นับของต้นแบบมันจะไม่ปรากฏในInternet Explorer 8และรุ่นก่อนหน้า

หากคุณต้องการรายการคุณสมบัติทั้งหมดของอินสแตนซ์ไม่ว่าจะนับได้หรือไม่คุณสามารถใช้

Object.getOwnPropertyNames(x);

สิ่งนี้จะส่งคืนอาร์เรย์ของชื่อของคุณสมบัติทั้งหมดที่มีอยู่บนวัตถุ

สุดท้ายคุณสามารถใช้ตัวดำเนินการ typeof เพื่อตรวจสอบชนิดข้อมูลของคุณสมบัติวัตถุโดยตรง

if (typeof x.key == "undefined") {
    alert("undefined");
}

ถ้าไม่มีคุณสมบัติบนวัตถุมันจะส่งคืนสตริงที่ไม่ได้กำหนด มิฉะนั้นจะส่งคืนประเภทคุณสมบัติที่เหมาะสม อย่างไรก็ตามโปรดทราบว่านี่ไม่ใช่วิธีที่ถูกต้องในการตรวจสอบว่าวัตถุมีคุณสมบัติหรือไม่เพราะคุณสามารถมีคุณสมบัติที่ตั้งค่าเป็นไม่ได้กำหนดซึ่งในกรณีนี้การใช้typeof x.keyจะยังคงเป็นจริง (แม้ว่ากุญแจจะยังคงอยู่ ในวัตถุ)

อัปเดต: คุณสามารถตรวจสอบว่ามีอสังหาริมทรัพย์อยู่หรือไม่โดยเปรียบเทียบกับคุณสมบัติจาวาสคริปต์ที่ไม่ได้กำหนด

if (x.key === undefined) {
    alert("undefined");
}

สิ่งนี้จะทำงานได้หากไม่มีการตั้งค่าคีย์เป็นพิเศษundefinedบนวัตถุ x


ส่วนอัพเดทของคุณไม่ถูกต้อง กรุณาดูที่นี่: jsfiddle.net/sbgg04yg
หมายเลข 945

อัปเดตเพื่อแสดงสถานการณ์ที่เปรียบเทียบกับคุณสมบัติที่ไม่ได้กำหนดของ JavaScript อาจล้มเหลว
goonerify

31

มาตัดความสับสนบางส่วนที่นี่ อันดับแรกให้ลดความซับซ้อนโดยสมมติว่าhasOwnPropertyมีอยู่แล้ว นี่เป็นความจริงของเบราว์เซอร์ส่วนใหญ่ที่ใช้งานอยู่

hasOwnPropertyผลตอบแทนจริงถ้าชื่อแอตทริบิวต์ที่ถูกส่งผ่านไปมันถูกเพิ่มไปยังวัตถุ undefinedมันเป็นทั้งเป็นอิสระจากค่าที่แท้จริงที่ได้รับมอบหมายไปซึ่งอาจจะตรง

ดังนั้น:

var o = {}
o.x = undefined

var a = o.hasOwnProperty('x')  // a is true
var b = o.x === undefined // b is also true

อย่างไรก็ตาม:

var o = {}

var a = o.hasOwnProperty('x')  // a is now false
var b = o.x === undefined // b is still true

ปัญหาคือสิ่งที่เกิดขึ้นเมื่อวัตถุในห่วงโซ่ต้นแบบมีคุณสมบัติที่มีค่าไม่ได้กำหนด? จะเป็นเท็จสำหรับมันและเพื่อจะhasOwnProperty !== undefinedแต่for..inจะยังคงแสดงไว้ในการแจงนับ

บรรทัดล่างคือไม่มีทางข้ามเบราว์เซอร์ (เนื่องจาก Internet Explorer ไม่เปิดเผย__prototype__) เพื่อตรวจสอบว่าตัวระบุเฉพาะไม่ได้แนบกับวัตถุหรืออะไรก็ตามในห่วงโซ่ต้นแบบ


24

หากคุณกำลังค้นหาสถานที่ให้บริการแล้ว "ไม่" คุณต้องการ:

if ('prop' in obj) { }

โดยทั่วไปคุณไม่ควรสนใจว่าทรัพย์สินนั้นมาจากต้นแบบหรือวัตถุ

อย่างไรก็ตามเนื่องจากคุณใช้ 'คีย์' ในโค้ดตัวอย่างของคุณดูเหมือนว่าคุณกำลังถือวัตถุเป็นแฮชซึ่งในกรณีนี้คำตอบของคุณจะสมเหตุสมผล คีย์แฮชทั้งหมดจะเป็นคุณสมบัติในวัตถุและคุณหลีกเลี่ยงคุณสมบัติพิเศษที่มีส่วนร่วมโดยต้นแบบ

คำตอบของ John Resig นั้นครอบคลุมมาก แต่ฉันคิดว่ามันไม่ชัดเจน โดยเฉพาะเมื่อใช้ "" prop "ใน obj"


1
โปรดทราบว่าinโอเปอเรเตอร์มีการรองรับเบราว์เซอร์ที่ยอดเยี่ยมIE 5.5+, Chrome 1.0+, Firefox 1.0+, Safari 3.0+ stackoverflow.com/questions/2920765/…
เอเดรียนเป็น

ตามที่ระบุไว้ในความคิดเห็นอื่นเกี่ยวกับการใช้inโอเปอเรเตอร์: "ใช้ได้กับ 'ออบเจ็กต์' ในความหมายที่แคบดังนั้นประกาศเป็น {} หรือสร้างโดยใช้ constructor มันไม่ยอมรับอาร์เรย์หรือ primitives ไม่ใช่ OP ต้องการ คำตอบอื่น ๆ นำเสนอเทคนิคที่กว้างกว่า (ทำงานกับอาร์เรย์สตริง ฯลฯ ) "
Adrien Be

1
แสดงความคิดเห็นสาเหตุที่ฉันถูก downvoted สองครั้งโดยไม่แสดงความคิดเห็น แต่ฉันก็ยังชอบคำตอบของฉัน บางทีใครก็ตามที่ต้องการคำตอบที่ 'ครอบคลุม' สำหรับทุกวิธีในการทดสอบสำหรับคุณสมบัติทุกประเภท .. แต่คำตอบของฉันคือแนวความคิดและสำหรับที่รวบรัด Re: Adrien Be คุณสมบัติที่นับไม่ถ้วนเป็นคุณสมบัติที่ไม่ได้มีไว้สำหรับขอบเขตผู้ใช้ทั่วไปดังนั้นแนวคิด 'ใน' ไม่เป็นไร;)
เจอราร์ด ONeill

16

สำหรับการทดสอบวัตถุง่าย ๆ ให้ใช้: if (obj[x] !== undefined)

หากคุณไม่ทราบว่าเป็นวัตถุประเภทใดให้ใช้: if (obj.hasOwnProperty(x))

ตัวเลือกอื่น ๆ ทั้งหมดจะช้าลง ..

รายละเอียด

การประเมินประสิทธิภาพรอบ 100,000,000 รอบภายใต้ Nodejs ถึง 5 ตัวเลือกที่ผู้อื่นแนะนำที่นี่:

function hasKey1(k,o) { return (x in obj); }
function hasKey2(k,o) { return (obj[x]); }
function hasKey3(k,o) { return (obj[x] !== undefined); }
function hasKey4(k,o) { return (typeof(obj[x]) !== 'undefined'); }
function hasKey5(k,o) { return (obj.hasOwnProperty(x)); }

การประเมินบอกเราว่าถ้าเราไม่ต้องการตรวจสอบห่วงโซ่ต้นแบบของวัตถุรวมถึงตัววัตถุเองเราไม่ควรใช้รูปแบบทั่วไป: if (X in Obj)... มันอยู่ระหว่าง 2 ถึง 6 เท่าช้ากว่าขึ้นอยู่กับกรณีการใช้งาน

hasKey1 execution time: 4s 510.427785ms
hasKey2 execution time: 0s 904.374806ms
hasKey3 execution time: 0s 760.336193ms
hasKey4 execution time: 0s 935.19901ms
hasKey5 execution time: 2s 148.189608ms

บรรทัดล่างถ้า Obj ของคุณไม่จำเป็นต้องเป็นวัตถุอย่างง่ายและคุณต้องการหลีกเลี่ยงการตรวจสอบห่วงโซ่ต้นแบบของวัตถุและเพื่อให้แน่ใจว่า Obj เป็นเจ้าของโดยตรงให้ใช้ 'if (obj.hasOwnProperty (x)) ... '

มิฉะนั้นเมื่อใช้วัตถุอย่างง่ายและไม่ต้องกังวลกับห่วงโซ่ต้นแบบของวัตถุการใช้if (typeof(obj[x]) !== 'undefined')...เป็นวิธีที่ปลอดภัยและเร็วที่สุด

หากคุณใช้วัตถุอย่างง่ายเป็นตารางแฮชและไม่ทำอะไรประหลาดฉันจะใช้if (obj[x])...เมื่อฉันพบว่าสามารถอ่านได้มากขึ้น

มีความสุข.


15

ใช่มันคือ :) ฉันคิดว่าคุณสามารถทำเช่นObject.prototype.hasOwnProperty.call(x, 'key')นี้ได้เช่นกันหากxมีทรัพย์สินชื่อhasOwnProperty:)

แต่นั่นเป็นการทดสอบคุณสมบัติของตัวเอง หากคุณต้องการที่จะตรวจสอบว่ามีทรัพย์สินที่อาจจะมีการ inhered typeof x.foo != 'undefined'คุณสามารถใช้


14
if (typeof x.key != "undefined") {

}

เพราะ

if (x.key)

ล้มเหลวหากx.keyแก้ไขเป็นfalse(ตัวอย่างเช่นx.key = "")


จะไม่ถูกต้อง ลองวัตถุต่อไปconst x = {key: undefined};ซึ่งจะกลับเท็จกับการแก้ปัญหานี้ในขณะที่และx.hasOwnProperty('key')); // true Reflect.has(x, 'key')); // trueสถานที่ให้บริการที่มีอยู่จริง undefinedแต่มีค่าเป็น
เหี่ยว


10

ตกลงดูเหมือนว่าฉันมีคำตอบที่ถูกต้องเว้นแต่ว่าคุณไม่ต้องการคุณสมบัติที่สืบทอดมา:

if (x.hasOwnProperty('key'))

นี่คือตัวเลือกอื่น ๆ เพื่อรวมคุณสมบัติที่สืบทอด:

if (x.key) // Quick and dirty, but it does the same thing as below.

if (x.key !== undefined)

4
Caveat x.hasOwnProperty ('key') สามารถเป็นจริงได้ในขณะที่ x.key! == undefined ไม่เป็นความจริง
AnthonyWJones

4
สำหรับวิธีการจะไม่ถูกต้อง var x = { key: false };x.key
Mark K Cowan

2
ถ้า (x.key) ไม่ถูกต้องราวกับว่า x = {key: 0} มันจะไม่ผ่านการตรวจสอบ
59

10

อย่าทำเช่นนี้object.hasOwnProperty(key))มันแย่มากเพราะวิธีการเหล่านี้อาจมีเงาในคุณสมบัติของวัตถุที่สงสัย - พิจารณา{ hasOwnProperty: false }- หรือวัตถุอาจเป็นวัตถุ(Object.create(null))ว่าง

วิธีที่ดีที่สุดคือการทำObject.prototype.hasOwnProperty.call(object, key)หรือ:

const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
/* or */
import has from 'has'; // https://www.npmjs.com/package/has
// ...
console.log(has.call(object, key));

3
ฉันเห็นด้วยกับวิธีนี้และควรเป็นคำตอบที่ยอมรับเพราะเป็นวิธีที่ปลอดภัยที่สุดในขณะที่ยังคงประสิทธิภาพ! eslint.org/docs/rules/no-prototype-builtinsพูดว่า "ตัวอย่างเช่นมันจะไม่ปลอดภัยสำหรับเว็บเซิร์ฟเวอร์ที่จะแยกวิเคราะห์อินพุต JSON จากลูกค้าและการเรียก hasOwnProperty โดยตรงบนวัตถุที่เกิดขึ้นเพราะลูกค้าที่เป็นอันตรายสามารถส่งค่า JSON ชอบ {"hasOwnProperty": 1} และทำให้เซิร์ฟเวอร์ขัดข้อง "
Arman

7

Object.keysอีกวิธีหนึ่งที่ค่อนข้างง่ายคือการใช้ นี่จะคืนค่าarrayซึ่งหมายความว่าคุณจะได้รับคุณสมบัติทั้งหมดของอาร์เรย์

var noInfo = {};
var info = {something: 'data'};

Object.keys(noInfo).length //returns 0 or false
Object.keys(info).length //returns 1 or true

แม้ว่าเราจะอยู่ในโลกที่มีการสนับสนุนเบราว์เซอร์ที่ยอดเยี่ยม เพราะคำถามนี้เก่ามากฉันคิดว่าฉันจะเพิ่มสิ่งนี้: มันปลอดภัยที่จะใช้ตั้งแต่JS v1.8.5


ถูกต้อง แต่ถ้าคุณต้องการทราบว่าข้อมูลมีคุณสมบัติที่มีชื่อบางอย่างหรือไม่? ซึ่งคิดว่าเป็นสิ่งที่ OP กำลังมองหา
Victorio Berra

2
จากนั้นคุณจะทำObject.keys(info).indexOf('someotherthing') !== -1
hippietrail

7

hasOwnProperty "สามารถใช้เพื่อตรวจสอบว่าวัตถุมีคุณสมบัติที่ระบุเป็นคุณสมบัติโดยตรงของวัตถุนั้นหรือไม่ซึ่งแตกต่างจากตัวดำเนินการในวิธีนี้จะไม่ตรวจสอบโซ่ต้นแบบของวัตถุ"

ดังนั้นอาจเป็นไปได้สำหรับสิ่งที่ดูเหมือนกับคำถามของคุณคุณไม่ต้องการใช้ hasOwnProperty ซึ่งกำหนดว่าคุณสมบัติมีอยู่ตามที่แนบกับวัตถุโดยตรงหรือไม่

หากคุณต้องการตรวจสอบว่าทรัพย์สินมีอยู่ในห่วงโซ่ต้นแบบที่คุณต้องการใช้เป็นหลัก:

if( prop in object ){ // do something }

ฉันหวังว่านี่จะช่วยได้.


ฉันได้รับ "ไม่สามารถใช้ 'ใน' โอเปอเรเตอร์เพื่อค้นหา 'prop' ใน myObject"
Victorio Berra

3

ด้วยความเสี่ยงที่จะเกิดปัญหาการดาวน์สตรีมสูงนี่เป็นอีกทางเลือกสำหรับกรณีเฉพาะ :)

หากคุณต้องการทดสอบสมาชิกบนวัตถุและต้องการทราบว่ามีการตั้งค่าเป็นอย่างอื่นนอกเหนือจาก:

  • ''
  • เท็จ
  • โมฆะ
  • ไม่ได้กำหนด
  • 0 ...

จากนั้นคุณสามารถใช้:

var foo = {};
foo.bar = "Yes, this is a proper value!";
if (!!foo.bar) {
        // member is set, do something
}

กะทัดรัดและสะดวกสบาย
Frederik Witte

linter จะไม่ชอบสิ่งนี้: eslint.org/docs/rules/no-extra-boolean-cast
Wilt

2

โซลูชัน ECMA Script 6 พร้อมการสะท้อนกลับ สร้างเสื้อคลุมที่ชอบ:

/**
Gets an argument from array or object.
The possible outcome:
- If the key exists the value is returned.
- If no key exists the default value is returned.
- If no default value is specified an empty string is returned.
@param obj    The object or array to be searched.
@param key    The name of the property or key.
@param defVal Optional default version of the command-line parameter [default ""]
@return The default value in case of an error else the found parameter.
*/
function getSafeReflectArg( obj, key, defVal) {
   "use strict";
   var retVal = (typeof defVal === 'undefined' ? "" : defVal);
   if ( Reflect.has( obj, key) ) {
       return Reflect.get( obj, key);
   }
   return retVal;
}  // getSafeReflectArg

นี่เป็นวิธีที่ดีที่สุดในการกำหนดเป้าหมาย> = ES6 หรือไม่
hippietrail

1
Imho มันเป็นคำตอบที่สั้นและง่ายที่สุด แต่อาจไม่ใช่วิธีการที่เร็วที่สุดในการเรียกใช้โค้ด แต่ความเร็วไม่ใช่ปัญหาอีกต่อไป
ทำร้าย

2

มีวิธีการ "hasOwnProperty" อยู่บนวัตถุ แต่ไม่แนะนำให้เรียกวิธีนี้โดยตรงเนื่องจากบางครั้งวัตถุอาจเป็นโมฆะหรือมีคุณสมบัติบางอย่างอยู่ในวัตถุเช่น: { hasOwnProperty: false }

วิธีที่ดีกว่านั้นก็คือ:

// good
var obj = {"bar": "here bar desc"}
console.log(Object.prototype.hasOwnProperty.call(obj, "bar"));

// best
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
console.log(has.call(obj, "bar"));


2

คุณสามารถใช้แนวทางต่อไปนี้ -

var obj = {a:1}
console.log('a' in obj)               //1
console.log(obj.hasOwnProperty('a'))  //2
console.log(Boolean(obj.a))         //3

ความแตกต่างระหว่างวิธีการดังต่อไปนี้มีดังนี้ -

  1. ในวิธีที่ 1 และ 3 เราไม่เพียง แต่ค้นหาในวัตถุ แต่ยังเป็นโซ่ต้นแบบของมันด้วย ถ้าวัตถุไม่มีคุณสมบัติ แต่มีคุณสมบัติอยู่ในห่วงโซ่ต้นแบบของมันมันจะเป็นจริง

 var obj = {
      a:2,
      __proto__ :{b:2}
    }

    console.log('b' in obj)
    console.log(Boolean(obj.b))

  1. วิธีที่สองจะตรวจสอบเฉพาะสำหรับคุณสมบัติของตัวเอง เช่น -

var obj = {
      a:2,
      __proto__ :{b:2}
    }

    console.log(obj.hasOwnProperty('b'))

  1. ความแตกต่างระหว่างที่ 1 และที่สามคือถ้ามีคุณสมบัติที่มีค่าไม่ได้กำหนดวิธีการที่ 3 จะให้เป็นเท็จในขณะที่ก่อนจะให้ความจริง

var obj = {
      b : undefined
    }
    console.log(Boolean(obj.b))
    console.log('b' in obj);


1

object.hasOwnProperty(property)คุณจำเป็นต้องใช้วิธีการ มันจะส่งกลับจริงถ้าวัตถุที่มีคุณสมบัติและเท็จถ้าวัตถุนั้น


-1

หากคีย์ที่คุณกำลังตรวจสอบเก็บอยู่ในตัวแปรคุณสามารถตรวจสอบได้ดังนี้:

x = {'key': 1};
y = 'key';
x[y];

แนวคิดนี้แตกต่างกันอย่างไรจากนั้นแค่ทดสอบ x ['key'] และมันแตกต่างจาก x.key อย่างไร นอกจากการเข้าถึงอาร์เรย์แน่นอน ..
เจอราร์ด ONeill

-1

ทำไมต้องทำสิ่งที่ซับซ้อนเกินเหตุเมื่อคุณสามารถ:

var isProperty =  (objectname.keyname || "") ? true : false;

ง่ายและชัดเจนสำหรับกรณีส่วนใหญ่ ...


สิ่งที่ง่ายที่สุดคือ var isProperty = !! objectname.keyname;
John

ถ้าวัตถุเป็นดังนี้const objectName = { keyname: false };ก็ควรกลับจริงเนื่องจากเป็นทรัพย์สินของkeyname objectnameแต่เนื่องจากค่าเป็นเท็จมันจะกลับเท็จด้วยตรรกะนี้
เหี่ยว
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.