ฉันรู้ว่าหลายวิธีที่จะสร้างวัตถุ JS แต่ฉันไม่ทราบObject.create(null)'หนึ่ง
คำถาม:
มันเป็นเช่นเดียวกับ:
var p = {}
VS
var p2 = Object.create(null);
?
ฉันรู้ว่าหลายวิธีที่จะสร้างวัตถุ JS แต่ฉันไม่ทราบObject.create(null)'หนึ่ง
คำถาม:
มันเป็นเช่นเดียวกับ:
var p = {}
VS
var p2 = Object.create(null);
?
คำตอบ:
พวกเขาจะไม่เทียบเท่า {}.constructor.prototype == Object.prototypeในขณะที่Object.create(null)ไม่ได้รับมรดกจากอะไรและดังนั้นจึงไม่มีคุณสมบัติเลย
ในคำอื่น ๆ : การสืบทอดจาวาสคริปต์วัตถุจากวัตถุโดยค่าเริ่มต้นเว้นแต่ว่าคุณได้สร้างมันขึ้นมาด้วย null Object.create(null)เป็นต้นแบบของมันเช่น:
{}Object.create(Object.prototype)แทนจะเทียบเท่ากับ
ใน Chrome Devtool คุณจะเห็นว่าObject.create(null)ไม่มี__proto__คุณสมบัติในขณะ{}นั้น
พวกเขาไม่เทียบเท่ากันอย่างแน่นอน ฉันกำลังเขียนคำตอบนี้เพื่ออธิบายเพิ่มเติมอย่างเต็มที่ว่าทำไมจึงสร้างความแตกต่าง
var p = {};
Objectสร้างวัตถุที่สืบทอดคุณสมบัติและวิธีการจาก
var p2 = Object.create(null);
สร้างวัตถุที่ไม่สืบทอดสิ่งใด
หากคุณใช้วัตถุเป็นแผนที่และคุณสร้างวัตถุโดยใช้วิธีที่ 1 ด้านบนคุณต้องระมัดระวังเป็นพิเศษเมื่อทำการค้นหาในแผนที่ เนื่องจากคุณสมบัติและวิธีการจากObjectนั้นสืบทอดรหัสของคุณอาจทำงานในกรณีที่มีคีย์ในแผนที่ที่คุณไม่เคยใส่ ตัวอย่างเช่นหากคุณทำการค้นหาtoStringคุณจะพบฟังก์ชันแม้ว่าคุณจะไม่เคยใส่ค่านั้นลงไป คุณสามารถหลีกเลี่ยงสิ่งเหล่านี้ได้:
if (Object.prototype.hasOwnProperty.call(p, 'toString')) {
// we actually inserted a 'toString' key into p
}
หมายเหตุว่ามันจะปรับให้บางสิ่งบางอย่างที่จะกำหนดp.toStringมันก็จะแทนที่ได้รับมรดกฟังก์ชั่นบนtoStringp
โปรดทราบว่าคุณไม่สามารถเพียงแค่ทำp.hasOwnProperty('toString')เพราะคุณอาจได้ใส่คีย์ "hasOwnProperty" ลงดังนั้นเราจึงบังคับให้ใช้ในการดำเนินงานpObject
ในทางกลับกันหากคุณใช้วิธีที่ 2 ด้านบนคุณจะไม่ต้องกังวลเกี่ยวกับสิ่งต่าง ๆ ที่จะObjectปรากฏบนแผนที่
คุณไม่สามารถตรวจสอบการมีอยู่ของอสังหาริมทรัพย์ด้วยวิธีifนี้ได้ง่ายๆ:
// Unreliable:
if (p[someKey]) {
// ...
}
ค่าที่อาจจะเป็นสตริงว่างอาจจะมีfalseหรือnullหรือundefinedหรือ0หรือNaNฯลฯ Object.prototype.hasOwnProperty.call(p, someKey)เพื่อตรวจสอบว่าสถานที่ให้บริการที่มีอยู่ที่ทุกท่านยังคงต้องใช้
Object.create(null)เฉพาะในกรณีที่พวกเขาใช้ ฉันไม่ชอบที่จะตั้งสมมติฐานแบบนั้นแม้ว่าคุณจะถูกต้องแน่นอนว่ามันใช้Object.create(null)รหัสสามารถเปลี่ยนแปลงวัตถุสามารถถูกแทนที่ด้วยสิ่งที่สืบทอดมาObjectในบางจุด hasOwnPropertyทำงานได้เสมอ
{}เป็นที่แพร่หลายมากขึ้นกว่าObject.create(null)ที่ว่าถ้ารหัสของคุณคว้าทรัพย์สินที่สืบทอดมาโดยบังเอิญ ณ จุดนี้คุณอาจมีข้อผิดพลาดที่ใหญ่กว่าที่จะต้องกังวล ฉันสามารถเห็นคนที่ใช้ Object.create (null) เป็นการปรับให้เหมาะสมเล็กน้อย
!!p[key] Object.create(null)แต่hasKey = (key, input) => Object.prototype.hasOwnProperty.call(input, key)ก็ไม่เลวเหมือนกัน
pเพราะทุกวิธีสามารถแทรกได้และไม่ปลอดภัย
การสร้างออบเจกต์โดยใช้{}จะสร้างออบเจกต์ที่ต้นแบบObject.prototypeซึ่งสืบทอดฟังก์ชันพื้นฐานจากObjectต้นแบบในขณะที่สร้างออบเจ็กต์โดยใช้Object.create(null)จะสร้างออบเจ็กต์ว่างที่มีต้นแบบเป็นโมฆะ
หากใครบางคนกำลังมองหาการใช้งานObject.create(null)เพียงแค่รู้วิธีการ มันเขียนไว้ใช้__proto__ซึ่งเป็นที่ไม่ได้มาตรฐานและด้วยเหตุนี้ผมไม่แนะนำให้มัน
function objectCreateMimic()
{
/*optional parameters: prototype_object, own_properties*/
var P = arguments.length>0?arguments[0]:-1;
var Q = arguments.length>1?arguments[1]:null;
var o = {};
if(P!==null && typeof P === "object")
{
o.__proto__ = P;
}
else if(P===null)
{
o.__proto__ = null;
}
if(Q!==null && typeof Q === "object")
{
for(var key in Q)
{
o[key] = Q[key];
}
}
return o;
}
หมายเหตุ : ฉันเขียนสิ่งนี้ออกมาจากความอยากรู้อยากเห็นและเขียนเป็นคำง่าย ๆ เท่านั้นเช่นฉันไม่ถ่ายโอนตัวบอกคุณสมบัติจากวัตถุที่สองไปยังวัตถุที่ส่งคืน
__proto__ตอนนี้จะเป็นส่วนหนึ่งของภาษาอย่างเป็นทางการ
-1ในarguments.length>0?arguments[0]:-1;?
Objectต้นแบบถูกเก็บรักษาไว้หากไม่ได้รับอาร์กิวเมนต์แรก ชื่อตัวแปรอาจดีกว่ามากที่นี่
เมื่อคุณสร้างวัตถุที่มี Object.create (null) นั่นหมายความว่าคุณกำลังสร้างวัตถุที่ไม่มีต้นแบบ nullที่นี่หมายถึงจุดสิ้นสุดของเชนต้นแบบ อย่างไรก็ตามเมื่อคุณสร้างวัตถุเช่น {} วัตถุต้นแบบจะถูกเพิ่ม ดังนั้นสิ่งเหล่านี้จึงเป็นวัตถุสองแบบที่แตกต่างกันอย่างหนึ่งกับต้นแบบอีกชิ้นที่ไม่มีต้นแบบหวังว่านี่จะช่วยได้
if (someKey in p) {