ตรวจสอบว่าค่าเป็นวัตถุใน JavaScript


1364

คุณจะตรวจสอบว่าค่าเป็น Object ใน JavaScript ได้อย่างไร?


4
ตัวแปรคือตัวแปร มันอาจหมายถึงวัตถุ นอกจากนี้คุณอาจต้องการกำหนด "วัตถุ" - ตามคำตอบและความคิดเห็นที่แสดงมีคำจำกัดความที่ขัดแย้งต่าง ๆ (เช่นไม่ว่าnullจะเป็นวัตถุ)

8
OP, IMO คุณควรยอมรับคำตอบของ @ Daan เนื่องจากเป็นทางออกที่ดีที่สุดและควรอยู่เหนือคำตอบอื่น ๆ เพื่อให้เห็นเป็นอันดับแรก (ไม่เป็นความผิดต่อผู้อื่นที่มีคำตอบที่ดีเช่นกัน)
taffine

2
IMHO มันขึ้นอยู่กับสิ่งที่คุณ (คนที่กำลังหาคำตอบสำหรับคำถามนี้) พิจารณาวัตถุและทำไมคุณถึงตรวจสอบ คำถามนี้ให้คำตอบที่แตกต่างกันหากคุณพยายามที่จะแยกแยะอาร์เรย์ (นั่นคือวัตถุ) จากวัตถุอื่นหรือถ้าคุณพยายามที่จะแยกค่าสเกลาร์ออกจาก "เวกเตอร์" และไม่ว่าจะเป็นโมฆะ (นั่นคือวัตถุตามประเภทของ) หรือฟังก์ชั่น (นั่นคือวัตถุ) ควรได้รับการยกเว้นหรือไม่นั้นขึ้นอยู่กับเหตุผลที่คุณตรวจสอบมัน นั่นเป็นเหตุผลที่มีคำตอบมากมายและส่วนใหญ่ในบริบทนั้นถูกต้อง
FrancescoMM

const isEmpty = thing => {typeof things === "object"? ! สิ่ง | | ! Object.keys (สิ่ง) .length:! thing && thing! == 0};
Mayur S

1
มันจะดีถ้าคุณสามารถเริ่มต้นด้วยการพูดในสิ่งที่คุณหมายถึงโดย "เป็นวัตถุ" (หรือพูดอย่างชัดเจนว่าส่วนหนึ่งของคำตอบที่คุณต้องการคือการจำกัดความหมายที่เป็นที่นิยมต่าง ๆ ของ "is a object" และแยกความแตกต่างระหว่างพวกเขา) หากไม่มีสิ่งนั้นทุกคนต่างพูดกัน
Don Hatch

คำตอบ:


520

อัปเดต :

คำตอบนี้ไม่สมบูรณ์และให้ผลลัพธ์ที่ทำให้เข้าใจผิด ตัวอย่างเช่นnullยังถือว่าเป็นประเภทobjectใน JavaScript ไม่พูดถึงกรณีขอบอื่น ๆ ทำตามคำแนะนำดังต่อไปนี้และย้ายไปยังที่อื่น ๆ"upvoted ที่สุด (และถูกต้อง!) คำตอบ"


คำตอบเดิม :

ลองใช้และtypeof(var) / หรือvar instanceof something

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


208
typeof()เป็นผู้ประกอบการจึงไม่มีความจำเป็นในการ
Yoshi

67
ใช่ไม่ต้องการ ฉันชอบวิธีนี้มากกว่า
Michael Krelin - แฮกเกอร์

150
@ MichaelKrelin แฮ็กเกอร์: นั่นเป็นโชคร้ายเพราะมันสับสนผู้คน
RightSaidFred

11
@RightSaidFred ฉันไม่มีคำอธิบายใด ๆ แต่ฉันไม่อยากเพิ่มวงเล็บพิเศษในสำนวนเหล่านี้ :)
Michael Krelin - แฮกเกอร์

117
คำตอบนี้ไม่ถูกต้อง typeofผลตอบแทน 'วัตถุ' for null ซึ่งไม่ได้เป็นวัตถุและไม่ทำงานสำหรับวัตถุที่สร้างขึ้นโดยใช้instanceof Object.create(null)
Nikolai

1633

ถ้าtypeof yourVariable === 'object'มันเป็นวัตถุหรือเป็นโมฆะ หากคุณต้องการที่จะไม่รวม null typeof yourVariable === 'object' && yourVariable !== nullเพียงให้มัน


31
ฟังก์ชั่นเป็นวัตถุและควรรวมอยู่ในเช็คของคุณ
JS_Riddler

4
ในกรณีนี้จะyourVariable !== nullเป็นการปฏิบัติที่ดีกว่า
hippietrail

9
@RightSaidFred ดูเหมือนว่าtypeof null == 'object'จะไม่ได้รับการแก้ไขในES6 พวกเขากล่าวว่า:This proposal has been rejected. It was implemented in V8 but it turned out that it broke a lot of existing sites. In the spirit of One JavaScript this is not feasible.
Konstantin Smolyanin

2
@ หากคำตอบง่าย ๆ ก็คืออาร์เรย์นั้นถือว่าเป็นวัตถุ สำหรับคำตอบที่ละเอียดกว่านี้คุณจะต้องอ่านต่อไปtypeofเพราะมันมีบางกรณีที่ไม่จำเป็นต้องมีเหตุผลมากนัก typeofถ้าคุณกำลังพยายามที่จะแยกความแตกต่างระหว่างอาร์เรย์และวัตถุที่ไม่ได้อาร์เรย์แน่นอนแล้วคุณไม่ต้องการที่จะใช้
Matt Fenwick

8
@Tresdin วิธีที่ดีที่สุดคือเรียกใช้Object.prototype.toString.call(yourVar)เป็นyourVarสิ่งที่คุณต้องการตรวจสอบ ในกรณีของอาร์เรย์ให้Object.prototype.toString.call([1,2])ส่งคืน[object Array]
Jose Rui Santos

539

ให้กำหนด "วัตถุ" ใน Javascript ตามMDN เอกสารทุกค่าเป็นวัตถุหรือดั้งเดิม:

ดั้งเดิมค่าดั้งเดิม

ข้อมูลที่ไม่ใช่วัตถุและไม่มีวิธีการใด ๆ JavaScript มีประเภทข้อมูลดั้งเดิม 5 ประเภท: สตริง, ตัวเลข, บูลีน, null, ไม่ได้กำหนด

ดั้งเดิมคืออะไร

  • 3
  • 'abc'
  • true
  • null
  • undefined

วัตถุคืออะไร (เช่นไม่ใช่ดั้งเดิม)?

  • Object.prototype
  • ทุกอย่างสืบเชื้อสายมาจาก Object.prototype
    • Function.prototype
      • Object
      • Function
      • function C(){} - ฟังก์ชั่นที่ผู้ใช้กำหนด
    • C.prototype- คุณสมบัติต้นแบบของฟังก์ชันที่ผู้ใช้กำหนด: นี่ไม่ใช่ Cต้นแบบ
      • new C() - "new" -ing ฟังก์ชั่นที่ผู้ใช้กำหนด
    • Math
    • Array.prototype
      • อาร์เรย์
    • {"a": 1, "b": 2} - วัตถุที่สร้างขึ้นโดยใช้สัญพจน์ตามตัวอักษร
    • new Number(3) - ห่อรอบดั้งเดิม
    • ... สิ่งอื่น ๆ อีกมากมาย ...
  • Object.create(null)
  • ทุกอย่างสืบเชื้อสายมาจาก Object.create(null)

วิธีการตรวจสอบว่าค่าเป็นวัตถุ

instanceof ด้วยตัวเองจะไม่ทำงานเพราะมันขาดสองกรณี:

// oops:  isObject(Object.prototype) -> false
// oops:  isObject(Object.create(null)) -> false
function isObject(val) {
    return val instanceof Object; 
}

typeof x === 'object'จะไม่ทำงานเนื่องจากมีผลบวกปลอม ( null) และลบ (ฟังก์ชัน) ที่เป็นเท็จ:

// oops: isObject(Object) -> false
function isObject(val) {
    return (typeof val === 'object');
}

Object.prototype.toString.call จะไม่ทำงานเนื่องจากมีผลบวกเท็จสำหรับ primitives ทั้งหมด:

> Object.prototype.toString.call(3)
"[object Number]"

> Object.prototype.toString.call(new Number(3))
"[object Number]"

ดังนั้นฉันใช้:

function isObject(val) {
    if (val === null) { return false;}
    return ( (typeof val === 'function') || (typeof val === 'object') );
}

@ คำตอบของ Daan ก็ดูเหมือนว่าจะทำงาน:

function isObject(obj) {
  return obj === Object(obj);
}

เพราะตามเอกสาร MDN :

ตัวสร้างวัตถุสร้างวัตถุห่อหุ้มสำหรับค่าที่กำหนด หากค่าเป็นโมฆะหรือไม่ได้กำหนดมันจะสร้างและส่งคืนวัตถุเปล่ามิฉะนั้นจะส่งคืนวัตถุประเภทที่สอดคล้องกับค่าที่กำหนด หากค่าเป็นวัตถุอยู่แล้วมันจะคืนค่า


วิธีที่สามที่ดูเหมือนว่าจะทำงาน (ไม่แน่ใจว่ามัน 100%) คือการใช้งานObject.getPrototypeOfที่ผิดข้อยกเว้นถ้าอาร์กิวเมนต์ไม่ได้เป็นวัตถุ:

// these 5 examples throw exceptions
Object.getPrototypeOf(null)
Object.getPrototypeOf(undefined)
Object.getPrototypeOf(3)
Object.getPrototypeOf('abc')
Object.getPrototypeOf(true)

// these 5 examples don't throw exceptions
Object.getPrototypeOf(Object)
Object.getPrototypeOf(Object.prototype)
Object.getPrototypeOf(Object.create(null))
Object.getPrototypeOf([])
Object.getPrototypeOf({})

22
obj === Object(obj)ส่งกลับค่าtrueสำหรับอาร์เรย์
Onur Yıldırım

5
var x = []; console.log(x === Object(x)); // return true
แสงสว่างใน

6
@Illuminator อาร์เรย์เป็นวัตถุใน Javascript ตามที่ฉันพูดถึงในคำตอบของฉัน
Matt Fenwick

1
getPrototypeOfไม่ทำงานเช่นถูกเพิกถอนพร็อกซีซึ่งเป็นวัตถุ แต่โยน
Oriol

2
ทำไมจึงไม่({}).toString.apply(obj) === '[object Object]'แยกความแตกต่างระหว่างอาร์เรย์และวัตถุที่ไม่ใช่อาร์เรย์
MauricioJuanes

295

underscore.jsจัดเตรียมวิธีการต่อไปนี้เพื่อตรวจสอบว่ามีบางสิ่งเป็นวัตถุจริงๆหรือไม่:

_.isObject = function(obj) {
  return obj === Object(obj);
};

UPDATE

เนื่องจากข้อผิดพลาดก่อนหน้านี้ใน V8 และการเพิ่มประสิทธิภาพความเร็วไมโครขนาดเล็กวิธีการดังต่อไปนี้ตั้งแต่underscore.js 1.7.0 (สิงหาคม 2014):

_.isObject = function(obj) {
  var type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

57
ในจาวาสคริปต์อาเรย์ยังเป็นวัตถุดังนั้นเวลาส่วนใหญ่ที่คุณต้องการยกเว้นอาเรย์:return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
Daan

22
เหตุใดคุณจึงต้องยกเว้นอาร์เรย์ พวกเขาเป็นวัตถุที่เต็มเปี่ยม
นิโคไล

65
เนื่องจากเวลาส่วนใหญ่คุณต้องการแยกความแตกต่าง {} จาก [] เป็นอินพุทในฟังก์ชัน
Daan

5
@ Nickolai .. และการวนซ้ำผ่านวัตถุที่ซ้อนกัน
Ricky Boyce

6
คำตอบที่ดี จัดการnullเช่นกัน ควรเป็นคำตอบที่ยอมรับได้
tiffon

180

Object.prototype.toString.call(myVar) จะกลับมา:

  • "[object Object]" ถ้า myVar เป็นวัตถุ
  • "[object Array]" ถ้า myVar เป็นอาร์เรย์
  • เป็นต้น

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้และทำไมมันเป็นทางเลือกที่ดีที่จะ typeof, ตรวจสอบบทความนี้


12
ฉันเพิ่งรู้ว่า->typeof [] === 'object' trueนั่นคือสิ่งที่คุณต้องการวิธีนี้
Jondlm

3
@Christophe ไม่แยกแยะระหว่างวิทยาการและวัตถุ ->Object.prototype.toString.call(3) -> ""[object Number]"Object.prototype.toString.call(new Number(3))"[object Number]
แมตต์เฟนวิค

3
@ MattFenwick ฉันไม่คิดว่านี่เป็น "object" ชนิดใดที่ OP พยายามระบุ
Christophe

3
@ Christophe ทำไมคุณถึงคิดอย่างนั้น? IMHO ในกรณีที่ไม่มีคำจำกัดความอื่น ๆ ที่กำหนดโดย OP สำหรับ "วัตถุ" ดูเหมือนว่าสมเหตุสมผลที่สุดที่ฉันจะไปกับสิ่งที่ใช้อย่างสม่ำเสมอตลอดข้อกำหนด ECS
Matt Fenwick

getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
นาย Polywhirl

115

เพียงตรวจสอบกับ Object หรือ Array โดยไม่ต้องเรียกใช้ฟังก์ชันเพิ่มเติม (ความเร็ว) ในฐานะที่เป็นยังโพสต์ที่นี่

IsArray ()

isArray = function(a) {
    return (!!a) && (a.constructor === Array);
};
console.log(isArray(        )); // false
console.log(isArray(    null)); // false
console.log(isArray(    true)); // false
console.log(isArray(       1)); // false
console.log(isArray(   'str')); // false
console.log(isArray(      {})); // false
console.log(isArray(new Date)); // false
console.log(isArray(      [])); // true

isObject () - หมายเหตุ: ใช้สำหรับตัวอักษร Object เท่านั้นเนื่องจากจะส่งคืนค่าเท็จสำหรับวัตถุที่กำหนดเองเช่น Date ใหม่หรือ YourCustomObject ใหม่

isObject = function(a) {
    return (!!a) && (a.constructor === Object);
};
console.log(isObject(        )); // false
console.log(isObject(    null)); // false
console.log(isObject(    true)); // false
console.log(isObject(       1)); // false
console.log(isObject(   'str')); // false
console.log(isObject(      [])); // false
console.log(isObject(new Date)); // false
console.log(isObject(      {})); // true

isObjectใช้งานได้กับตัวอักษรวัตถุเท่านั้น ถ้าฉันสร้างประเภทที่กำหนดเองสร้างอินสแตนซ์ของประเภทและทดสอบมันจะกลับมาfalse
WickyNilliams

3
@zupa: ทำยังไง !!

4
@ 3000 ดีถ้าเราปล่อยส่วน (!! a) มันขัดข้องเพราะโมฆะและไม่ได้กำหนดไม่มีตัวสร้าง (!! a) กรองออก นั่นตอบคำถามของคุณหรือไม่
zupa

2
@zupa @ 3000 Boolean(a)นั้นยาวกว่า แต่ก็ใช้งานได้ง่ายกว่ามาก อย่าใช้new Boolean(a): ( นี่คือเหตุผล )!
JayVee

10
ประหลาดใจที่คำตอบที่ดีที่สุดคือจนถึงหน้า สิ่งนี้จะตอบคำถามโดยพื้นฐานแล้วสิ่งนี้จะแสดงใน JSON เป็นสิ่งที่เริ่มต้นด้วย{ตัวอักษร สำหรับกรณีอาร์เรย์ถ้าคุณไม่จำเป็นต้องรองรับ IE <9 คุณสามารถใช้Array.isArray()เพื่อตรวจสอบว่ามีบางสิ่งที่เป็นอาร์เรย์หรือไม่ มันผ่านกรณีทดสอบทั้งหมดที่คุณให้ไว้
Kip

81

ฉันชอบง่ายๆ

function isObject (item) {
  return (typeof item === "object" && !Array.isArray(item) && item !== null);
}

หากรายการวัตถุ JS และก็ไม่ได้เป็นอาร์เรย์ JS และก็ไม่ได้null... trueถ้าทั้งสามพิสูจน์ความจริงกลับมา หากเงื่อนไขข้อใดข้อหนึ่งในสามล้มเหลวการ&&ทดสอบจะลัดวงจรและfalseจะถูกส่งคืน การnullทดสอบสามารถละเว้นได้ถ้าต้องการ (ขึ้นอยู่กับวิธีที่คุณใช้null )

เอกสาร:

http://devdocs.io/javascript/operators/typeof

http://devdocs.io/javascript/global_objects/object

http://devdocs.io/javascript/global_objects/array/isarray

http://devdocs.io/javascript/global_objects/null


3
สิ่งที่เกี่ยวกับ console.log (isObject (ใหม่วันที่ ())) ทำไมวันที่ควรเป็นวัตถุ แต่อาร์เรย์ไม่ได้
schirrmacher

5
@macher เพราะnew Date()ส่งคืนวัตถุ อาร์เรย์มาจากมุมมองแบบลอจิคัลไม่ใช่วัตถุ - แม้ว่า JavaScript จะจัดการและรายงานเป็นเช่นนั้น อย่างไรก็ตามในทางปฏิบัติมันไม่มีประโยชน์ที่จะเห็นพวกเขาเท่ากันเพราะพวกเขาไม่ วัตถุนั้นไม่มีlengthแอ็ตทริบิวต์และไม่มีวิธีใดที่เหมือนกับ push () และบางครั้งคุณอาจต้องการให้ฟังก์ชั่นการโอเวอร์โหลดของพารามิเตอร์ที่คุณต้องการสร้างความแตกต่างระหว่างอาร์เรย์หรือวัตถุโดยเฉพาะอย่างยิ่งถ้าพารามิเตอร์อื่น ๆ ขึ้นอยู่กับที่ได้รับ
StanE

1
@ อาร์เรย์อาร์เรย์เป็นวัตถุแน่นอน ไม่แน่ใจว่าทำไมคุณคิดวัตถุไม่สามารถมีlengthคุณสมบัติหรือวิธีการเช่นpush, Object.create(Array.prototype)เป็น counterexample เล็กน้อยของวัตถุที่ไม่ใช่อาร์เรย์ซึ่งมีเหล่านี้ สิ่งที่ทำให้อาร์เรย์มีความพิเศษคือพวกมันเป็นวัตถุแปลกใหม่ที่มีวิธีการภายในที่จำเป็น [[DefineOwnProperty]] ที่กำหนดเอง แต่มันยังคงเป็นวัตถุ
Oriol

4
@Oriol ฉันไม่ได้เขียนว่าอาร์เรย์ไม่ใช่วัตถุหรือฉันเขียนว่าวัตถุไม่สามารถมีlengthคุณสมบัติได้ (ฉันหมายความว่าตัวอักษรของวัตถุไม่มีlengthแอตทริบิวต์ตามค่าเริ่มต้น) ฉันเขียนว่าอาร์เรย์ไม่ใช่วัตถุจากมุมมองเชิงตรรกะ ฉันกำลังพูดเกี่ยวกับตรรกะของโปรแกรม บางครั้งจำเป็นต้องตรวจสอบว่าอาร์เรย์เป็นอาร์เรย์ "ของจริง" หรือไม่และไม่ใช่วัตถุ "ของจริง" อย่างแน่นอน นั่นคือสิ่งที่Array.isArray()มีไว้เพื่อ ลองนึกภาพคุณมีฟังก์ชั่นที่รับวัตถุหรืออาเรย์ของวัตถุ การตรวจสอบคุณลักษณะหรือวิธีพิเศษเป็นวิธีที่สกปรก วิถีทางดั้งเดิมนั้นดีกว่าเสมอ
StanE

2
typeof nullคือไม่"object" "undefined"
2540625

80

ด้วยฟังก์ชั่นArray.isArray:

function isObject(o) {
  return o !== null && typeof o === 'object' && Array.isArray(o) === false;
}

ไม่มีฟังก์ชั่นArray.isArray:

ประหลาดใจเพียงวิธีการหลาย upvotes สำหรับคำตอบที่ผิด😮
เพียง1 คำตอบผ่านการทดสอบของฉัน !!! ที่นี่ฉันได้สร้างเวอร์ชันที่ง่ายของฉัน:

function isObject(o) {
  return o instanceof Object && o.constructor === Object;
}

สำหรับฉันมันชัดเจนและเรียบง่ายและใช้งานได้! นี่คือการทดสอบของฉัน:

console.log(isObject({}));             // Will return: true
console.log(isObject([]));             // Will return: false
console.log(isObject(null));           // Will return: false
console.log(isObject(/.*/));           // Will return: false
console.log(isObject(function () {})); // Will return: false

อีกครั้ง: คำตอบทั้งหมดไม่ผ่านการทดสอบนี้ !!! 🙈


ในกรณีที่คุณต้องตรวจสอบว่าวัตถุนั้นเป็นอินสแตนซ์ของคลาสเฉพาะคุณต้องตรวจสอบคอนสตรัคเตอร์กับคลาสเฉพาะของคุณเช่น:

function isDate(o) {
  return o instanceof Object && o.constructor === Date;
}

การทดสอบอย่างง่าย:

var d = new Date();
console.log(isObject(d)); // Will return: false
console.log(isDate(d));   // Will return: true

ดังนั้นคุณจะมีรหัสที่เข้มงวดและแข็งแกร่ง!


ในกรณีที่คุณจะไม่สร้างฟังก์ชั่นเช่นisDate, isError, isRegExpฯลฯ คุณอาจพิจารณาตัวเลือกที่จะใช้ฟังก์ชั่นทั่วไปนี้:

function isObject(o) {
  return o instanceof Object && typeof o.constructor === 'function';
}

มันจะไม่ทำงานอย่างถูกต้องสำหรับกรณีทดสอบทั้งหมดที่กล่าวถึงก่อนหน้านี้ แต่ก็ดีพอสำหรับวัตถุทั้งหมด (ธรรมดาหรือสร้าง)


isObjectจะไม่ทำงานในกรณีที่Object.create(null)มีการใช้งานภายในObject.createซึ่งอธิบายไว้ที่นี่แต่คุณสามารถใช้isObjectในการใช้งานที่ซับซ้อนมากขึ้น:

function isObject(o, strict = true) {
  if (o === null || o === undefined) {
    return false;
  }
  const instanceOfObject = o instanceof Object;
  const typeOfObject = typeof o === 'object';
  const constructorUndefined = o.constructor === undefined;
  const constructorObject = o.constructor === Object;
  const typeOfConstructorObject = typeof o.constructor === 'function';
  let r;
  if (strict === true) {
    r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
  } else {
    r = (constructorUndefined || typeOfConstructorObject);
  }
  return r;
};

มีแพคเกจที่สร้างไว้แล้วใน npm v1 ตามการใช้งานนี้! และใช้ได้กับกรณีทดสอบทั้งหมดที่อธิบายไว้ก่อนหน้า! 🙂


คำตอบที่ดีที่สุด! ใช้ได้กับหลายกรณีที่กล่าวถึงที่นี่
Prieston

เนื่องจากสิ่งนี้คืนค่าเท็จสำหรับ isObject (myDateObject) นี่ไม่ใช่คำตอบสำหรับคำถาม มันไม่ได้บอกว่าตัวแปรเป็นวัตถุเฉพาะในกรณีที่มันเป็นวัตถุของคลาสเฉพาะ คำถามที่นี่สำหรับฟังก์ชั่นทั่วไปที่ส่งกลับจริงสำหรับวัตถุใด ๆ
Yetanotherjosh

@ Yetanotherjosh มันเป็นคำตอบแน่นอน🤓คุณพูดถึงกรณีที่อธิบายไว้ในคำตอบและจุด - คุณต้องใช้isDateสำหรับวันของคุณ Object โดยมีวัตถุประสงค์เพื่อเขียนรหัสที่แข็งแกร่งมิฉะนั้นคุณจะมีisObjectวิธีเปราะ
V. Kovpak

@VladimirKovpak ใช้ในความคิดเห็นของผมก็ป่วยเลือกเพราะใช่คำตอบที่จะหารือเกี่ยวกับDate Dateแต่Dateเป็นเพียงหนึ่งในคลาสที่ไม่มีที่สิ้นสุดที่เป็นไปได้และจุดเก็บไว้สำหรับคลาสอื่น ๆ ตัวอย่าง: ผลตอบแทนclass Foo() { }; var x = new Foo(); isObject(x) falseฉันไม่ทราบว่ากรณีการใช้ OP คืออะไร แต่เป็นเรื่องง่ายที่จะเข้าใจสถานการณ์ที่ต้องรู้เกี่ยวกับคลาสที่เป็นไปได้ทั้งหมดและการตรวจสอบเฉพาะกับทุก ๆคลาสนั้นจะเป็นไปไม่ได้
Yetanotherjosh

@Yetanotherjosh ฉันได้อัปเดตคำตอบของฉันแล้ว และเพิ่มอีก 1 กรณี
V. Kovpak

40

โอ้พระเจ้า! ฉันคิดว่านี่อาจจะสั้นกว่าที่เคยให้ดู:

รหัสสั้นและสุดท้าย

function isObject(obj)
{
    return obj != null && obj.constructor.name === "Object"
}

console.log(isObject({})) // returns true
console.log(isObject([])) // returns false
console.log(isObject(null)) // returns false

อธิบาย

ประเภทผลตอบแทน

typeof วัตถุ JavaScript (รวมถึงnull) ผลตอบแทน"object"

console.log(typeof null, typeof [], typeof {})

ตรวจสอบการก่อสร้างของพวกเขา

การตรวจสอบconstructorคุณสมบัติส่งคืนฟังก์ชันพร้อมชื่อ

console.log(({}).constructor) // returns a function with name "Object"
console.log(([]).constructor) // returns a function with name "Array"
console.log((null).constructor) //throws an error because null does not actually have a property

แนะนำ Function.name

Function.nameส่งคืนชื่อแบบอ่านอย่างเดียวของฟังก์ชันหรือ"anonymous"การปิด

console.log(({}).constructor.name) // returns "Object"
console.log(([]).constructor.name) // returns "Array"
console.log((null).constructor.name) //throws an error because null does not actually have a property

หมายเหตุ:ตั้งแต่ปี 2018 Function.name อาจไม่ทำงานในIE https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility


3
ฉันชอบอันนี้สั้นและตรงประเด็นจริงๆ มันล้มเหลวเพียง 1 อย่างเท่าที่ฉันเห็น ถ้า obj = Object.create(null)และทำไมคุณถึงทำอย่างนั้นต่อไป ... ?
Julian Knight

29

ตกลงเราจะให้แนวคิดนี้ก่อนที่จะตอบคำถามของคุณในฟังก์ชั่น JavaScript ได้แก่ Object, null, Object, Arrays และ Date ดังนั้นอย่างที่คุณเห็นว่าไม่มีวิธีง่ายๆเช่น typeof obj === 'object' ดังนั้น ทุกอย่างที่กล่าวถึงข้างต้นจะกลับมาจริงแต่มีวิธีการตรวจสอบด้วยการเขียนฟังก์ชั่นหรือใช้กรอบจาวาสคริปต์ตกลง:

ตอนนี้จินตนาการว่าคุณมีวัตถุนี้ซึ่งเป็นวัตถุจริง (ไม่ใช่ null หรือฟังก์ชันหรืออาร์เรย์):

var obj = {obj1: 'obj1', obj2: 'obj2'};

JavaScript บริสุทธิ์:

//that's how it gets checked in angular framework
function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}

หรือ

//make sure the second object is capitalised 
function isObject(obj) {
   return Object.prototype.toString.call(obj) === '[object Object]';
}

หรือ

function isObject(obj) {
    return obj.constructor.toString().indexOf("Object") > -1;
}

หรือ

function isObject(obj) {
    return obj instanceof Object;
}

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

isObject(obj);

หากคุณใช้เฟรมเวิร์ก JavaScript พวกเขามักจะเตรียมฟังก์ชั่นเหล่านี้ให้คุณนี่คือบางส่วนของมัน:

jQuery:

 //It returns 'object' if real Object;
 jQuery.type(obj);

เชิงมุม:

angular.isObject(obj);

ขีดล่างและ Lodash:

//(NOTE: in Underscore and Lodash, functions, arrays return true as well but not null)
_.isObject(obj);

คุณต้องการตรวจสอบว่าไม่ใช่อาร์เรย์ ดังนั้นฟังก์ชัน isObject (obj) {return obj! == null && typeof obj === 'object' &&! Array.isArray (obj); }
Matt Goo

ฉันเห็นด้วยกับคุณ แต่เมื่อคุณเห็นในความคิดเห็นมันเป็นวิธีการทำใน angularJs และฉันพูดถึงมันในความคิดเห็นต่อหน้าฟังก์ชั่นพวกเขานับ Array เป็นวัตถุ ... ดูที่นี่สำหรับข้อมูลเพิ่มเติม: เอกสาร .angularjs.org / api / ng / function / angular.isObject
Alireza

24

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

function isAnyObject(value) {
    return value != null && (typeof value === 'object' || typeof value === 'function');
}

มันตัดวิทยาการ (ตัวเลขธรรมดา / NaN/ Infinityสตริงธรรมดาสัญลักษณ์true/ false, undefinedและnull) แต่ควรกลับจริงสำหรับทุกอย่างอื่น (รวมทั้งNumber, BooleanและStringวัตถุ) โปรดทราบว่า JS ไม่ได้กำหนดสิ่งที่ "โฮสต์" วัตถุเช่นwindowหรือconsoleควรกลับมาเมื่อใช้กับtypeofดังนั้นจึงเป็นเรื่องยากที่จะครอบคลุมกับการตรวจสอบเช่นนี้

หากคุณต้องการที่จะรู้ว่าสิ่งที่เป็นวัตถุ "ธรรมดา" คือมันถูกสร้างขึ้นเป็นตัวอักษร{}หรือด้วยObject.create(null)คุณอาจทำสิ่งนี้:

function isPlainObject(value) {
    if (Object.prototype.toString.call(value) !== '[object Object]') {
        return false;
    } else {
        var prototype = Object.getPrototypeOf(value);
        return prototype === null || prototype === Object.prototype;
    }
}

แก้ไข 2018 : เพราะSymbol.toStringTagขณะนี้ช่วยให้การปรับแต่งการส่งออกของObject.prototype.toString.call(...)ที่isPlainObjectฟังก์ชั่นดังกล่าวข้างต้นอาจกลับมาfalseในบางกรณีแม้เมื่อวัตถุเริ่มต้นชีวิตที่เป็นตัวอักษร เนื้อหาโดยการจัดระเบียบวัตถุที่มีแท็กสตริงที่กำหนดเองไม่ได้เป็นวัตถุธรรมดาอีกต่อไป แต่สิ่งนี้ได้ทำให้ความหมายของสิ่งที่วัตถุธรรมดาแม้แต่ใน Javascript


ทำไม typeof === 'function' จึงถือว่าเป็นวัตถุ ฟังก์ชั่นไม่ใช่วัตถุใช่มั้ย "new myFunc ()" จะกลายเป็นวัตถุใช่ แต่ฟังก์ชั่นธรรมดา?
StanE

ไม่ทุกฟังก์ชั่นเป็นวัตถุใน Javascript ไม่ว่ามันจะถูกสร้างอย่างไร คุณสามารถตั้งค่าคุณสมบัติเหล่านั้นได้ (เว้นแต่พวกเขาจะถูกตรึง) พวกมันคือinstanceof Objectตัวอักษรฟังก์ชั่นที่เหมือนกันสองตัวไม่เท่ากันอย่างเคร่งครัดพวกมันจะถูกส่งผ่านโดยการอ้างอิง ฯลฯ
last-child

21

พระเจ้าของฉันสับสนมากเกินไปในคำตอบอื่น ๆ

คำตอบสั้น ๆ

typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array)

ในการทดสอบนี้ให้เรียกใช้คำสั่งต่อไปนี้ในคอนโซล Chrome

กรณีที่ 1

var anyVar = {};
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // true

กรณีที่ 2

anyVar = [];
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // false

กรณีที่ 3

anyVar = null;
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array); // false

คำอธิบาย

โอเคมาทำลายมันกันเถอะ

typeof anyVar == 'object'ถูกส่งคืนจริงจากผู้สมัครสามคน - [], {} and null,

anyVar instanceof Object จำกัด ผู้สมัครเหล่านี้ให้เหลือสองคน - [], {}

!(anyVar instanceof Array) แคบลงเหลือเพียงอันเดียว - {}

ได้โปรดม้วนกลอง!

จากนี้คุณอาจได้เรียนรู้วิธีตรวจสอบ Array ใน Javascript แล้ว


2
จากบันทึกนี้จะส่งกลับfalse(ตามต้องการ) เมื่อanyVarเป็นฟังก์ชัน
เจมี่เบิร์ช

18

วิธีที่เหมาะสมที่สุดในการตรวจสอบประเภทของค่าดูเหมือนว่าtypeofผู้ประกอบการ ปัญหาเดียวก็คือว่ามันพังอย่างน่ากลัว:

  • มันกลับมา"object"เพื่อnullซึ่งเป็นประเภท Null
  • มันกลับมา "function"สำหรับวัตถุที่โทรได้ซึ่งอยู่ในประเภทวัตถุ
  • สามารถส่งคืนเกือบทุกสิ่งที่ต้องการสำหรับวัตถุที่ไม่สามารถเรียกได้ ยกตัวอย่างเช่น IE "unknown"ดูเหมือนจะชอบ ผลลัพธ์ที่ต้องห้ามเท่านั้นคือ"function"และประเภทดั้งเดิม

typeofมีความน่าเชื่อถือสำหรับสารที่ไม่เป็นnullพื้นฐานเท่านั้น ดังนั้นวิธีการตรวจสอบว่าค่าเป็นวัตถุจะต้องแน่ใจว่าสตริงที่ส่งคืนโดยtypeofไม่ตรงกับแบบดั้งเดิมและวัตถุนั้นไม่nullไม่สอดคล้องกับความดั้งเดิมและที่วัตถุไม่ได้อย่างไรก็ตามปัญหาคือมาตรฐานในอนาคตสามารถแนะนำประเภทดั้งเดิมใหม่และรหัสของเราจะถือว่าเป็นวัตถุ ชนิดใหม่ไม่ปรากฏบ่อยนัก แต่ตัวอย่างเช่น ECMAScript 6 แนะนำประเภทสัญลักษณ์

ดังนั้นแทนที่จะtypeofแนะนำวิธีการที่ผลลัพธ์แตกต่างกันไปขึ้นอยู่กับว่าค่านั้นเป็นวัตถุหรือไม่ ต่อไปนี้ตั้งใจจะเป็น

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

  • Object นวกรรมิก

    ตัวObjectสร้าง coerces อาร์กิวเมนต์ที่ส่งผ่านไปยังวัตถุ หากเป็นวัตถุอยู่แล้ววัตถุเดียวกันจะถูกส่งคืน

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

    ฟังก์ชันต่อไปนี้ต้องการ ECMAScript 3 ซึ่งแนะนำ===:

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return Object(value) === value;
    }

    ฉันชอบวิธีการนี้เพราะมันเรียบง่ายและอธิบายตัวเองได้และการตรวจสอบแบบอะนาล็อกก็ใช้ได้กับบูลีนตัวเลขและสายอักขระด้วย อย่างไรก็ตามโปรดทราบว่ามันขึ้นอยู่กับโลกที่Objectไม่ได้ถูกบังหรือเปลี่ยนแปลง

  • ก่อสร้าง

    เมื่อคุณสร้างอินสแตนซ์ Constructor มันสามารถคืนค่าที่แตกต่างจากอินสแตนซ์ที่เพิ่งสร้างขึ้น แต่ค่านั้นจะถูกละเว้นเว้นแต่ว่าเป็นวัตถุ

    ฟังก์ชันต่อไปนี้ต้องใช้ ECMAScript 3 ซึ่งอนุญาตให้ Constructor ส่งคืนวัตถุที่ไม่ใช่ ก่อนหน้า ECMAScript 3 ที่โยนข้อผิดพลาด แต่ไม่มีtryคำสั่งในตอนนั้น

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return new function() { return value; }() === value;
    }

    ในขณะที่เรียบง่ายน้อยกว่าตัวอย่างก่อนหน้านี้เล็กน้อยนี้ไม่ได้พึ่งพาทรัพย์สินทั่วโลกใด ๆ และดังนั้นจึงอาจปลอดภัยที่สุด

  • this ราคา

    ข้อกำหนดคุณสมบัติ ECMAScript แบบเก่าจำเป็นต้องให้thisค่าเป็นวัตถุ แนะนำ ECMAScript 3 Function.prototype.callซึ่งอนุญาตให้เรียกใช้ฟังก์ชันที่มีthisค่าตามอำเภอใจแต่ถูกบังคับให้ใช้กับวัตถุ

    ECMAScript 5 แนะนำโหมดเข้มงวดซึ่งนำการทำงานนี้ออก แต่ในโหมดเลอะเทอะเรายังคงสามารถ (แต่ไม่ควรเนื้อหา) พึ่งพา

    function isObject(value) { /* Requires ECMAScript 3 or later in sloppy mode */
      return function() { return this === value; }.call(value);
    }
  • [[Prototype]]

    วัตถุสามัญทั้งหมดมีสล็อตภายในที่เรียกว่า [[Prototype]] ซึ่งค่าจะเป็นตัวกำหนดว่าวัตถุอื่นจะสืบทอดมาจากไหน nullค่าที่สามารถเป็นวัตถุหรือ ดังนั้นคุณสามารถสร้างวัตถุที่สืบทอดมาจากค่าที่ต้องการและตรวจสอบว่ามันทำงาน

    ทั้งสองObject.createและObject.getPrototypeOfต้องการ ECMAScript 5

    function isObject(value) { /* Requires ECMAScript 5 or later */
      try {
        Object.create(value);
        return value !== null;
      } catch(err) {
        return false;
      }
    }
    function isObject(value) { /* Requires ECMAScript 5 or later */
      function Constructor() {}
      Constructor.prototype = value;
      return Object.getPrototypeOf(new Constructor()) === value;
    }
  • ECMAScript 6 วิธีใหม่บางอย่าง

    ECMAScript 6 แนะนำวิธีการทางอ้อมใหม่ ๆ ในการตรวจสอบคือค่าเป็นวัตถุ พวกเขาใช้วิธีการที่เห็นก่อนหน้านี้เพื่อส่งผ่านค่าไปยังโค้ดบางอย่างที่ต้องการวัตถุซึ่งอยู่ภายในtryคำสั่งเพื่อตรวจจับข้อผิดพลาด ตัวอย่างที่ซ่อนอยู่บางส่วนไม่คุ้มค่าที่จะแสดงความคิดเห็น


หมายเหตุ: ฉันตั้งใจข้ามบางวิธีเช่นObject.getPrototypeOf(value)(ES5) และReflectเมธอด (ES6) เพราะพวกเขาเรียกวิธีการภายในที่จำเป็นซึ่งอาจทำสิ่งที่น่ารังเกียจเช่นถ้าvalueเป็นพร็อกซี ด้วยเหตุผลด้านความปลอดภัยตัวอย่างของฉันอ้างอิงvalueโดยไม่ต้องเข้าถึงโดยตรง


2
"มีเพียงคำตอบและ Daan ของฉันเท่านั้นที่ถูกต้องทั้งหมด" เป็นการเกรงใจเล็กน้อยเนื่องจากฉันไม่เห็นด้วยกับประโยคสองประโยคแรกของคุณ
zzzzBov

1
@zzzzBov ดีฉันดูคำตอบทั้งหมดและพวกเขาไม่แน่ใจว่าจะคืนคำตอบที่ถูกต้องเสมอยกเว้นของฉันและ Daan ฉันสามารถให้ตัวอย่างที่ทำซ้ำได้กับคนส่วนใหญ่ คนอื่น ๆ แนะนำให้ตรวจสอบว่า typeof คืนค่า "function" หรือ "object" แต่ตามที่ฉันอธิบายไว้ spec อนุญาตให้ผลลัพธ์อื่นสำหรับวัตถุบางอย่าง คำตอบของ Matt Fenwick มีคำตอบที่ถูกต้องเช่นเดียวกับ Daan แต่ก็มีคำตอบที่ไม่ถูกต้องเช่นกัน
Oriol

1
ฉันไม่เห็นด้วยกับหลักฐานที่ว่าคำตอบของคุณคือ "ถูกต้องทั้งหมด" โดยยืนยันว่าคนอื่น "ไม่มั่นใจว่าจะได้คำตอบที่ถูกต้องเสมอ" ไม่ปฏิเสธตำแหน่งของฉันในทางใดทางหนึ่ง นอกจากนี้คำถามไม่ได้อ้างสิทธิ์ใด ๆ เกี่ยวกับสิ่งที่อินพุตควรสร้างเอาท์พุทใด
zzzzBov

1
@zzzzBov คำถามถามว่าจะตรวจสอบว่ามีวัตถุหรือไม่ ECMAScript จะกำหนดว่าวัตถุคืออะไรดังนั้นฉันจึงใช้คำจำกัดความนั้น ฉันไม่เห็นการตีความที่สมเหตุสมผลอื่น ๆ คำตอบที่ทำสิ่งอื่น ๆ (เช่นการยกเว้นอาร์เรย์) อาจมีประโยชน์ในบางสถานการณ์ แต่พวกเขาไม่ตรวจสอบว่ามีบางสิ่งเป็นวัตถุหรือไม่
Oriol


15

ลองสิ่งนี้

if (objectName instanceof Object == false) {
  alert('Not an object');
}
else {
  alert('An object');
}

14
ทำไมคุณถึงตรวจสอบบูลีน?
jkutianski

5
สิ่งนี้ขาดสองกรณี: Object.prototype instanceof Object-> false Object.create(null) instanceof Object-> เท็จ
Matt Fenwick

แล้วเดทล่ะ new Date() instanceof Object => จริง
mauron85

13

พร้อมใช้ฟังก์ชั่นสำหรับตรวจสอบ

function isObject(o) {
  return null != o && 
    typeof o === 'object' && 
    Object.prototype.toString.call(o) === '[object Object]';
}

function isDerivedObject(o) {
  return !isObject(o) && 
    null != o && 
    (typeof o === 'object' || typeof o === 'function') &&
    /^\[object /.test(Object.prototype.toString.call(o));
}

// Loose equality operator (==) is intentionally used to check
// for undefined too

// Also note that, even null is an object, within isDerivedObject
// function we skip that and always return false for null

คำอธิบาย

  • ใน Javascript, null, Object, Array, Dateและfunctions มีวัตถุทั้งหมด แม้ว่าจะnullมีการวางแผนบิต ดังนั้นจึงเป็นการดีกว่าที่จะตรวจสอบnullก่อนเพื่อตรวจสอบว่าไม่เป็นโมฆะ

  • ตรวจสอบการtypeof o === 'object'ค้ำประกันที่oเป็นวัตถุ หากไม่มีการตรวจสอบนี้Object.prototype.toStringจะไม่มีความหมายเนื่องจากจะส่งคืนวัตถุสำหรับทุกสิ่งแม้กระทั่งundefinedและnull! ตัวอย่างเช่น: toString(undefined)ส่งคืน[object Undefined]!

    หลังจากtypeof o === 'object'การตรวจสอบ toString.call (O) เป็นวิธีการที่ดีในการตรวจสอบว่าoเป็นวัตถุวัตถุที่ได้มาเช่นArray, หรือDatefunction

  • ในisDerivedObjectฟังก์ชั่นจะตรวจสอบว่าoเป็นฟังก์ชั่น เพราะฟังก์ชั่นก็เป็นวัตถุด้วย หากไม่ได้ทำเช่นนั้นฟังก์ชั่นจะกลับมาเป็นเท็จ ตัวอย่าง: isDerivedObject(function() {})จะกลับมาfalseแต่ตอนนี้มันกลับtrueมา

  • หนึ่งสามารถเปลี่ยนนิยามของสิ่งที่เป็นวัตถุ ดังนั้นหนึ่งสามารถเปลี่ยนฟังก์ชั่นเหล่านี้ตาม


การทดสอบ

function isObject(o) {
  return null != o && 
    typeof o === 'object' && 
    Object.prototype.toString.call(o) === '[object Object]';
}

function isDerivedObject(o) {
  return !isObject(o) && 
    null != o && 
    (typeof o === 'object' || typeof o === 'function') &&
    /^\[object /.test(Object.prototype.toString.call(o));
}

// TESTS

// is null an object?

console.log(
  'is null an object?', isObject(null)
);

console.log(
  'is null a derived object?', isDerivedObject(null)
);

// is 1234 an object?

console.log(
  'is 1234 an object?', isObject(1234)
);

console.log(
  'is 1234 a derived object?', isDerivedObject(1234)
);

// is new Number(1234) an object?

console.log(
  'is new Number(1234) an object?', isObject(new Number(1234))
);

console.log(
  'is new Number(1234) a derived object?', isDerivedObject(1234)
);

// is function object an object?

console.log(
  'is (new (function (){})) an object?', 
  isObject((new (function (){})))
);

console.log(
  'is (new (function (){})) a derived object?', 
  isObject((new (function (){})))
);

// is {} an object?

console.log(
  'is {} an object?', isObject({})
);

console.log(
  'is {} a derived object?', isDerivedObject({})
);

// is Array an object?

console.log(
  'is Array an object?',
  isObject([])
)

console.log(
  'is Array a derived object?',
  isDerivedObject([])
)

// is Date an object?

console.log(
  'is Date an object?', isObject(new Date())
);

console.log(
  'is Date a derived object?', isDerivedObject(new Date())
);

// is function an object?

console.log(
  'is function an object?', isObject(function(){})
);

console.log(
  'is function a derived object?', isDerivedObject(function(){})
);


13

หากคุณต้องการที่จะตรวจสอบว่าprototypeการobjectมา Objectแต่เพียงผู้เดียวจาก กรองString, Number, Array, Argumentsฯลฯ

function isObject (n) {
  return Object.prototype.toString.call(n) === '[object Object]';
}

หรือเป็นฟังก์ชั่นลูกศรนิพจน์เดียว (ES6 +)

const isObject = n => Object.prototype.toString.call(n) === '[object Object]'

1
นี่เป็นวิธีที่ดีที่สุด แต่ผมจะทำให้มันง่ายยิ่งขึ้นโดยในบรรทัดที่ 2:return Object.prototype.toString.call(n) === '[object Object]'
mesqueeb

1
นอกจากนี้คุณยังสามารถลบnullเช็คได้เนื่องจากObject.prototype.toString.call(null) === '[object Null]'
Gust van de Wal

12
var a = [1]
typeof a //"object"
a instanceof Object //true
a instanceof Array //true

var b ={a: 1}
b instanceof Object //true
b instanceof Array //false

var c = null
c instanceof Object //false
c instanceof Array //false

ฉันถูกขอให้ให้รายละเอียดเพิ่มเติม วิธีที่สะอาดและเข้าใจได้มากที่สุดในการตรวจสอบว่าตัวแปรของเราเป็นวัตถุtypeof myVarหรือไม่ มันจะส่งคืนสตริงที่มีประเภท (เช่น"object", "undefined")

น่าเสียดายที่ Array และ null มีประเภทobjectเช่นกัน ในการรับวัตถุจริงเท่านั้นไม่จำเป็นต้องตรวจสอบห่วงโซ่การสืบทอดโดยใช้instanceofโอเปอเรเตอร์ มันจะกำจัด null แต่ Array มี Object ในห่วงโซ่การสืบทอด

ดังนั้นทางออกคือ:

if (myVar instanceof Object && !(myVar instanceof Array)) {
  // code for objects
}

/./ instanceof Object //true
yckart

11

สายเล็กน้อย ... สำหรับ "วัตถุธรรมดา" (ฉันหมายถึงเช่น {'x': 5, 'y': 7}) ฉันมีตัวอย่างเล็ก ๆ นี้:

function isPlainObject(o) {
   return ((o === null) || Array.isArray(o) || typeof o == 'function') ?
           false
          :(typeof o == 'object');
}

มันสร้างผลลัพธ์ต่อไป:

console.debug(isPlainObject(isPlainObject)); //function, false
console.debug(isPlainObject({'x': 6, 'y': 16})); //literal object, true
console.debug(isPlainObject(5)); //number, false
console.debug(isPlainObject(undefined)); //undefined, false
console.debug(isPlainObject(null)); //null, false
console.debug(isPlainObject('a')); //string, false
console.debug(isPlainObject([])); //array?, false
console.debug(isPlainObject(true)); //bool, false
console.debug(isPlainObject(false)); //bool, false

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


ดังที่กล่าวไว้ในคำตอบก่อนหน้าแนวทางของคุณจะล้มเหลวในกรณีของวัตถุวันที่
Grzegorz Pawlik

9

lodash มีisPlainObjectซึ่งอาจเป็นสิ่งที่หลายคนที่มาที่หน้านี้กำลังมองหา มันจะส่งกลับเท็จเมื่อให้ฟังก์ชั่นหรืออาร์เรย์


ที่สมบูรณ์แบบ! ฉันรู้เกี่ยว_.isObjectกับสิ่งที่ตรงกับสิ่งที่ JS พิจารณาวัตถุ แต่สิ่งที่ฉันมักต้องการคือการแยกความแตกต่างระหว่างเช่นตัวอักษรของวัตถุและอาร์เรย์ซึ่งเป็นสิ่งที่_.isPlainObjectทำให้ฉันทำ
มะนาว

9

สิ่งนี้จะได้ผล มันเป็นฟังก์ชั่นที่คืนค่าจริงเท็จหรืออาจเป็นโมฆะ

const isObject = obj => obj && obj.constructor && obj.constructor === Object;

console.log(isObject({})); // true
console.log(isObject([])); // false
console.log(isObject(new Function)); // false
console.log(isObject(new Number(123))); // false
console.log(isObject(null)); // null


2
@SeregPie ในอนาคตคุณควรละเว้นจากการแก้ไขรหัสในคำตอบ ในฐานะที่เป็นคำตอบนี้ยืนเมื่อการทดสอบผมไม่ได้รับเป็นผลสำหรับการทดสอบขั้นสุดท้ายมากกว่าnull falseดูเมื่อใดที่ฉันควรแก้ไขโค้ด
Nick

9

เนื่องจากดูเหมือนว่ามีความสับสนมากมายเกี่ยวกับวิธีการจัดการปัญหานี้อย่างถูกต้องฉันจะปล่อยให้ 2 เซ็นต์ของฉัน (คำตอบนี้เป็นไปตามข้อมูลจำเพาะและสร้างผลลัพธ์ที่ถูกต้องภายใต้สถานการณ์ทั้งหมด):

การทดสอบพื้นฐาน: undefined null boolean string number

function isPrimitive(o){return typeof o!=='object'||null}

วัตถุนั้นไม่ใช่วัตถุดึกดำบรรพ์:

function isObject(o){return !isPrimitive(o)}

หรืออีกทางหนึ่ง:

function isObject(o){return o instanceof Object}
function isPrimitive(o){return !isObject(o)}

ทดสอบอาเรย์ใด ๆ :

const isArray=(function(){
    const arrayTypes=Object.create(null);
    arrayTypes['Array']=true;
    arrayTypes['Int8Array']=true;
    arrayTypes['Uint8Array']=true;
    arrayTypes['Uint8ClampedArray']=true;
    arrayTypes['Int16Array']=true;
    arrayTypes['Uint16Array']=true;
    arrayTypes['Int32Array']=true;
    arrayTypes['Uint32Array']=true;
    arrayTypes['BigInt64Array']=true;
    arrayTypes['BigUint64Array']=true;
    arrayTypes['Float32Array']=true;
    arrayTypes['Float64Array']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!!arrayTypes[o.constructor.name];
    }
}());

ทดสอบวัตถุที่ไม่รวม: Date RegExp Boolean Number String FunctionArray ใด ๆ

const isObjectStrict=(function(){
    const nativeTypes=Object.create(null);
    nativeTypes['Date']=true;
    nativeTypes['RegExp']=true;
    nativeTypes['Boolean']=true;
    nativeTypes['Number']=true;
    nativeTypes['String']=true;
    nativeTypes['Function']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!isArray(o)&&!nativeTypes[o.constructor.name];
    }
}());

8

เมื่อทุกอย่างล้มเหลวฉันใช้สิ่งนี้:

var isObject = function(item) {
   return item.constructor.name === "Object";
}; 

1
ทำไมการเปรียบเทียบสตริงทำไมไม่ง่ายitem.constructor === Object?
K3 --- rnc

nullโยนข้อยกเว้นUncaught TypeError: Cannot read property 'constructor' of null(…)
Vitim.us

@ rounce ฉันตั้งใจจะสนับสนุน IE เวอร์ชันเก่ากว่าทำไมมันไม่ทำงานใน IE? เพราะindexOfหรือเพราะconstructor.name?
Jankapunkt

8

Ramdaห้องสมุดทำงานมีฟังก์ชั่นที่ยอดเยี่ยมสำหรับการตรวจสอบประเภท JavaScript

ถอดความฟังก์ชั่นเต็มรูปแบบ :

function type(val) {
  return val === null      ? 'Null'      :
         val === undefined ? 'Undefined' :
         Object.prototype.toString.call(val).slice(8, -1);
}

ฉันต้องหัวเราะเมื่อรู้ว่าวิธีแก้ปัญหานั้นง่ายและสวยงามเพียงใด

ตัวอย่างการใช้งานจากเอกสารประกอบของ Ramda :

R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type('s'); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(() => {}); //=> "Function"
R.type(undefined); //=> "Undefined"

8

หลังจากที่ได้อ่านและพยายามออกจำนวนมากของการใช้งานที่ผมได้สังเกตเห็นว่าคนน้อยมากที่พยายามที่จะตรวจสอบค่าเช่นJSON, Math, documentหรือวัตถุที่มีโซ่ต้นแบบนานกว่าขั้นตอนที่ 1

แทนที่จะตรวจสอบtypeofตัวแปรของเราแล้วทำการแฮ็กกรณีขอบฉันคิดว่ามันจะดีกว่าถ้าการตรวจสอบนั้นง่ายที่สุดเท่าที่จะทำได้เพื่อหลีกเลี่ยงการ refactor เมื่อมีการเพิ่มดั้งเดิมหรือวัตถุดั้งเดิมที่ลงทะเบียนเป็นtypeofวัตถุ '

ท้ายที่สุดtypeofผู้ดำเนินการจะบอกคุณว่ามีบางสิ่งบางอย่างเป็นวัตถุของ JavaScriptหรือไม่ แต่คำจำกัดความของ JavaScript ของวัตถุนั้นกว้างเกินไปสำหรับสถานการณ์ส่วนใหญ่ในโลกแห่งความเป็นจริง (เช่นtypeof null === 'object') ด้านล่างเป็นฟังก์ชั่นที่กำหนดว่าตัวแปรvเป็นวัตถุหรือไม่โดยการตรวจสอบซ้ำสองครั้ง:

  1. ห่วงจะเริ่มต้นที่ยังคงตราบเท่าที่รุ่น stringified ของมีv ฉันต้องการผลลัพธ์ของฟังก์ชันให้เหมือนกับบันทึกด้านล่างดังนั้นนี่เป็นเพียง "วัตถุประสงค์" - เกณฑ์ที่ฉันได้รับ ถ้ามันล้มเหลวฟังก์ชันจะคืนค่าเท็จทันที'[object Object]'
  2. vจะถูกแทนที่ด้วยต้นแบบถัดไปในห่วงโซ่ด้วยv = Object.getPrototypeOf(v)แต่ยังประเมินโดยตรงหลังจาก เมื่อค่าใหม่ของvคือnullหมายความว่าทุกต้นแบบรวมถึงต้นแบบต้นแบบ (ซึ่งอาจเป็นต้นแบบเดียวภายในห่วงโซ่) ได้ผ่านการตรวจสอบในขณะที่วงและเราสามารถกลับจริง มิฉะนั้นจะเริ่มซ้ำใหม่

function isObj (v) {
  while (     Object.prototype.toString.call(v) === '[object Object]')
  if    ((v = Object.getPrototypeOf(v))         === null)
  return true
  return false
}

console.log('FALSE:')
console.log('[]                   -> ', isObj([]))
console.log('null                 -> ', isObj(null))
console.log('document             -> ', isObj(document))
console.log('JSON                 -> ', isObj(JSON))
console.log('function             -> ', isObj(function () {}))
console.log('new Date()           -> ', isObj(new Date()))
console.log('RegExp               -> ', isObj(/./))

console.log('TRUE:')
console.log('{}                   -> ', isObj({}))
console.log('new Object()         -> ', isObj(new Object()))
console.log('new Object(null)     -> ', isObj(new Object(null)))
console.log('new Object({})       -> ', isObj(new Object({foo: 'bar'})))
console.log('Object.prototype     -> ', isObj(Object.prototype))
console.log('Object.create(null)  -> ', isObj(Object.create(null)))
console.log('Object.create({})    -> ', isObj(Object.create({foo: 'bar'})))
console.log('deep inheritance     -> ', isObj(Object.create(Object.create({foo: 'bar'}))))


6
if(typeof value === 'object' && value.constructor === Object)
{
    console.log("This is an object");
}

1
หากvalueเป็นnullเช่นนี้จะทำให้เกิดข้อผิดพลาด ...
Gershom

และแน่นอนมันจะเป็นสำหรับวัตถุfalse Object.assign({}, {constructor: null})
user4642212

6

{}ถ้าต้องการอย่างชัดเจนเพื่อตรวจสอบว่าค่าที่กำหนดคือ

function isObject (value) {
 return value && typeof value === 'object' && value.constructor === Object;
}

6
const isObject = function(obj) {
  const type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

!!objจดชวเลขสำหรับการตรวจสอบว่าobjเป็นความจริงหรือไม่ (เพื่อกรองออกnull)


6

มันเป็นคำถามเก่า แต่คิดว่าจะออกจากที่นี่ คนส่วนใหญ่กำลังตรวจสอบว่าตัวแปรมี{}ความหมายว่าคีย์ - ค่าจับคู่หรือไม่และสิ่งที่เป็นขีดเส้นใต้ที่ JavaScript ใช้สำหรับสิ่งที่กำหนดเพราะจะซื่อสัตย์ทุกอย่างใน JavaScript เป็นวัตถุ ดังนั้นการออกไปให้พ้นทาง ถ้าคุณทำ...

let x = function() {}
typeof x === 'function' //true
x === Object(x) // true
x = []
x === Object(x) // true

// also
x = null
typeof null // 'object'

ส่วนใหญ่สิ่งที่เราต้องการคือการรู้ว่าเรามีวัตถุทรัพยากรจาก API หรือการเรียกฐานข้อมูลของเรากลับมาจาก ORM จากนั้นเราสามารถทดสอบว่าไม่ใช่Array, ไม่ใช่null, ไม่ใช่ประเภทของ'function'และเป็นObject

// To account also for new Date() as @toddmo pointed out

x instanceof Object && x.constructor === Object

x = 'test' // false
x = 3 // false
x = 45.6 // false
x = undefiend // false
x = 'undefiend' // false
x = null // false
x = function(){} // false
x = [1, 2] // false
x = new Date() // false
x = {} // true

ปรากฏtrueสำหรับnew Date()
toddmo

1
@toddmo ขอบคุณที่ชี้ให้เห็น ตอนนี้โค้ดตัวอย่างจะคืนค่าเท็จสำหรับnew Date()
Gilbert

4

สิ่งที่ฉันชอบที่จะใช้คือสิ่งนี้

function isObject (obj) {
  return typeof(obj) == "object" 
        && !Array.isArray(obj) 
        && obj != null 
        && obj != ""
        && !(obj instanceof String)  }

ฉันคิดว่าในกรณีส่วนใหญ่วันที่ต้องผ่านการตรวจสอบเป็นวัตถุดังนั้นฉันจึงไม่กรองวันที่ออก


4

ฉันพบวิธี "ใหม่" ในการตรวจสอบประเภทนี้จากคำถาม SO นี้: ทำไมอินสแตนซ์ของการคืนค่าเท็จสำหรับตัวอักษรบางตัว

จากนั้นฉันสร้างฟังก์ชั่นสำหรับการตรวจสอบประเภทดังนี้

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return false;         //fallback for null or undefined
    }
}

จากนั้นคุณสามารถทำได้:

console.log(isVarTypeOf('asdf', String));   // returns true
console.log(isVarTypeOf(new String('asdf'), String));   // returns true
console.log(isVarTypeOf(123, String));   // returns false
console.log(isVarTypeOf(123, Number));   // returns true
console.log(isVarTypeOf(new Date(), String));   // returns false
console.log(isVarTypeOf(new Date(), Number));   // returns false
console.log(isVarTypeOf(new Date(), Date));   // returns true
console.log(isVarTypeOf([], Object));   // returns false
console.log(isVarTypeOf([], Array));   // returns true
console.log(isVarTypeOf({}, Object));   // returns true
console.log(isVarTypeOf({}, Array));   // returns false
console.log(isVarTypeOf(null, Object));   // returns false
console.log(isVarTypeOf(undefined, Object));   // returns false
console.log(isVarTypeOf(false, Boolean));   // returns true

มีการทดสอบบน Chrome 56, Firefox 52, Microsoft Edge 38, Internet Explorer 11, Opera 43

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

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return _var == _type;   //null and undefined are considered the same
        // or you can use === if you want to differentiate them
    }
}

var a = undefined, b = null;
console.log(isVarTypeOf(a, undefined)) // returns true
console.log(isVarTypeOf(b, undefined)) // returns true
console.log(isVarTypeOf(a, null)) // returns true

อัปเดตจากความคิดเห็นของ inanc: ยอมรับความท้าทาย: D

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

function isVarTypeOf(_var, _type, looseCompare){
    if (!looseCompare){
        try {
            return _var.constructor === _type;
        } catch(ex){
            return _var == _type;
        }
    } else {
        try{
            switch(_var.constructor){
                case Number:
                case Function:
                case Boolean:
                case Symbol:
                case Date:
                case String:
                case RegExp:
                    // add all standard objects you want to differentiate here
                    return _var.constructor === _type;
                case Error:
                case EvalError:
                case RangeError:
                case ReferenceError:
                case SyntaxError:
                case TypeError:
                case URIError:
                    // all errors are considered the same when compared to generic Error
                    return (_type === Error ? Error : _var.constructor) === _type;
                case Array:
                case Int8Array:
                case Uint8Array:
                case Uint8ClampedArray:
                case Int16Array:
                case Uint16Array:
                case Int32Array:
                case Uint32Array:
                case Float32Array:
                case Float64Array:
                    // all types of array are considered the same when compared to generic Array
                    return (_type === Array ? Array : _var.constructor) === _type;
                case Object:
                default:
                    // the remaining are considered as custom class/object, so treat it as object when compared to generic Object
                    return (_type === Object ? Object : _var.constructor) === _type;
            }
        } catch(ex){
            return _var == _type;   //null and undefined are considered the same
            // or you can use === if you want to differentiate them
        }
    }
}

ด้วยวิธีนี้คุณสามารถทำเช่นเดียวกับความคิดเห็นของ inanc:

isVarTypeOf(new (function Foo(){}), Object); // returns false
isVarTypeOf(new (function Foo(){}), Object, true); // returns true

หรือ

Foo = function(){};
Bar = function(){};
isVarTypeOf(new Foo(), Object);   // returns false
isVarTypeOf(new Foo(), Object, true);   // returns true
isVarTypeOf(new Bar(), Foo, true);   // returns false
isVarTypeOf(new Bar(), Bar, true);   // returns true
isVarTypeOf(new Bar(), Bar);    // returns true

สิ่งนี้ไม่สามารถตรวจพบว่าคลาสใหม่เป็นวัตถุหรือไม่ isVarTypeOf (ใหม่ (ฟังก์ชั่น Foo () {}), ออบเจ็กต์) // นี่จะคืนค่าเท็จแทนที่จะเป็นจริง ดูคำตอบของฉันด้านล่างสำหรับการตรวจสอบที่เหมาะสม
Inanc Gumus

อย่างไรก็ตามคุณสามารถใช้instanceofเพื่อตรวจสอบวัตถุ ถึงกระนั้นนี่ไม่ใช่วิทยาศาสตร์ที่แน่นอน
Inanc Gumus

@inanc กันดีว่าเป็นเพราะnew Foo()ผลตอบแทนFooวัตถุเช่นเดียวกับnew String()ผลตอบแทนStringวัตถุหรือnew Date()ผลตอบแทนDateวัตถุที่คุณสามารถทำFoo = function(){}; isVarTypeOf(new Foo(), Foo);ยัง
am05mhz

ใช่นั่นคือสิ่งที่ฉันพูดจริง ๆ : คุณไม่ได้ตรวจสอบว่ามันเป็นวัตถุตอนนี้หรือไม่
Inanc Gumus

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