การลบวัตถุใน JavaScript


359

ฉันสับสนกับdeleteโอเปอเรเตอร์ของ JavaScript รับรหัสต่อไปนี้:

var obj = {
    helloText: "Hello World!"
};

var foo = obj;

delete obj;

หลังจากชิ้นส่วนของรหัสนี้ได้รับการดำเนินการobjเป็นnullแต่ยังหมายถึงวัตถุที่ว่าเหมือนfoo objฉันเดาว่าวัตถุนี้เป็นวัตถุเดียวกับที่fooชี้ไป

สับสนนี้เราเพราะเราคาดว่าการเขียนที่delete objถูกลบวัตถุที่ถูกชี้ไปในหน่วยความจำที่ไม่ได้เป็นเพียงตัวแปรobjobj

นี่เป็นเพราะ Garbage Collector ของจาวาสคริปต์ทำงานบนการรักษา / ปล่อยดังนั้นถ้าฉันไม่มีตัวแปรอื่น ๆ ที่ชี้ไปที่วัตถุมันจะถูกลบออกจากหน่วยความจำ?

(โดยวิธีการทดสอบของฉันเสร็จใน Safari 4)


7
การอ้างอิงของคุณ. developer.mozilla.org/en/Core_JavaScript_1.5_Reference/ …
Daniel A. White

บทความฉบับสมบูรณ์เกี่ยวกับคำหลักลบwebcache.googleusercontent.com/…
Vitim.us

2
ลิงค์ด้านบนควรเป็น: perfectionkills.com/understanding-delete
johnmdonahue

1
@Steve Harrison delete ไม่ได้สำหรับลบวัตถุใน javascript delete ใช้สำหรับลบ object key ในกรณีของคุณvar obj = { helloText: "Hello World!" }; var foo = obj; delete obj;วัตถุจะไม่ถูกลบตรวจสอบobjการใช้งาน delete: delete obj.helloTextแล้วตรวจสอบfoo now foo is an empty object
Umair Ahmed

2
@UmairAhmed การแปลฟรี: "" " deleteไม่ได้มีไว้สำหรับการลบวัตถุใน javascript deleteใช้สำหรับลบคีย์วัตถุในกรณีของคุณvar obj = { helloText: "Hello World!" }; var foo = obj; delete obj;วัตถุจะไม่ถูกลบตรวจสอบobjถัดไปเรียกใช้delete obj.helloTextแล้วคุณจะเห็นว่าfooตอนนี้ชี้ไปที่ว่างเปล่า วัตถุ "" "
Pacerier

คำตอบ:


448

ตัวดำเนินการลบจะลบเฉพาะการอ้างอิงเท่านั้นไม่ต้องเป็นวัตถุ ถ้ามันลบวัตถุเองการอ้างอิงอื่น ๆ ที่เหลือจะเป็นอันตรายเช่นการลบ C ++ (และการเข้าถึงหนึ่งในนั้นจะทำให้เกิดความผิดพลาดในการทำให้ทุกอย่างเป็นโมฆะจะหมายถึงการทำงานพิเศษเมื่อลบหรือหน่วยความจำเพิ่มเติมสำหรับแต่ละวัตถุ)

เนื่องจาก Javascript เป็นขยะที่เก็บรวบรวมคุณไม่จำเป็นต้องลบวัตถุเอง - มันจะถูกลบออกเมื่อไม่มีวิธีการอ้างอิงอีกต่อไป

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


23
deleteคำหลักที่ทำงานเฉพาะสำหรับคุณสมบัติของวัตถุที่ไม่ตัวแปร perfectionkills.com/understanding-delete
Alex Mund

1
@AlexJM ใช่คำตอบถัดไปจาก Guffa (และความคิดเห็น) พูดถึงเรื่องนี้ในรายละเอียด
Jesse Rusak

1
คุณสมบัติของวัตถุสามารถเป็นวัตถุอื่นได้ ตัวอย่างเช่น; var obj = {a: {}}; delete obj.a;
Alex Mund

2
แต่ ... คุณสมบัติของตัวแปรไม่ใช่windowหรือ?
RedClover

3
@Saku ไม่ได้เป็นตัวแปรท้องถิ่น (เช่นที่ประกาศไว้var)
Jesse Rusak

162

deleteคำสั่งไม่มีผลต่อตัวแปรปกติคุณสมบัติเฉพาะ หลังจากdeleteคำสั่งคุณสมบัติไม่มีค่าnullมันจะไม่มีอยู่เลย

หากคุณสมบัติเป็นการอ้างอิงวัตถุdeleteคำสั่งจะลบคุณสมบัติ แต่ไม่ใช่วัตถุ ตัวเก็บรวบรวมขยะจะดูแลวัตถุหากไม่มีการอ้างอิงอื่น ๆ

ตัวอย่าง:

var x = new Object();
x.y = 42;

alert(x.y); // shows '42'

delete x; // no effect
alert(x.y); // still shows '42'

delete x.y; // deletes the property
alert(x.y); // shows 'undefined'

(ทดสอบใน Firefox)


39
หากสิ่งนี้ถูกดำเนินการในขอบเขตโกลบอลxตัวแปรของคุณจะกลายเป็นเพียงคุณสมบัติในwindowออบเจ็กต์โกลบอลและdelete x;จะลบxตัวแปรทั้งหมดโดยสิ้นเชิง
Crescent Fresh

18
@crescentfresh: เป็นเพียงคุณสมบัติเท่านั้นหากมีการประกาศโดยปริยาย หากมีการประกาศอย่างชัดเจนตามตัวอย่างมันเป็นตัวแปรทั่วโลกและไม่สามารถลบได้
Guffa

4
@Tarynn: ฉันเข้าใจว่านั่นคือปัญหา หากคุณทำสิ่งนี้ในคอนโซลด้วยเหตุผลบางอย่างxจะไม่เป็นตัวแปรที่เหมาะสมในบางเบราว์เซอร์ แต่เป็นคุณสมบัติในwindowวัตถุ แน่นอนว่านี่เป็นปัญหากับคอนโซลและไม่ได้สะท้อนถึงการใช้งานโค้ดตามปกติ
Guffa

2
@Guffa หลังจากการวิจัยมากมายฉันต้องยอมรับมันอาจจะเป็นสิ่งที่ดีที่ฉันไม่มีตัวแทนลงคะแนนมากพอ ขอโทษจริงใจของฉันและขอบคุณที่สละเวลาเพื่อแสดงให้ฉันสิ่งที่ถูก happeneing ... นี่คือ explination ลึก: perfectionkills.com/understanding-delete/#firebug_confusion
Tarynn

2
@ chao: ฉันเห็น คุณกำลังมีปัญหาเช่นเดียวกับ Tarynn (ดูความคิดเห็นก่อนหน้า) เมื่อคุณทำสิ่งนี้ในคอนโซลมันจะไม่ทำงานเหมือนกับในรหัสจริง
Guffa

56

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


53
ฉันไม่เคยรู้ว่า var เป็นเหี้ย
Gavin

1
นี่คือจุดที่ดีและ JS gotcha ผู้คนคุ้นเคยกับการลบ vars หน้าต่างและสงสัยว่าทำไมพวกเขาไม่สามารถทำเช่นเดียวกันกับตัวแปรท้องถิ่น
welbornio

2
letเดียวกันจะไปสำหรับ
Pacerier

23

มาจากเอกสาร Mozilla, "คุณสามารถใช้ตัวดำเนินการลบเพื่อลบตัวแปรที่ประกาศโดยปริยาย แต่ไม่ใช่ตัวแปรที่ประกาศด้วยคำสั่ง var"

นี่คือลิงค์: https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator


4

delete ไม่ได้ใช้สำหรับการลบวัตถุในจาวาสคริปต์

deleteใช้สำหรับการลบobject keyในกรณีของคุณ

var obj = { helloText: "Hello World!" }; 
var foo = obj;
delete obj;

วัตถุจะไม่ถูกลบตรวจสอบ obj ยังคงใช้ค่าเดิม ลบการใช้งาน:

delete obj.helloText

จากนั้นตรวจสอบobj, fooว่าทั้งคู่เป็นวัตถุว่างเปล่า


2

เพิ่งพบjsperfคุณอาจคิดว่าน่าสนใจในเรื่องนี้ (มันอาจจะสะดวกที่จะเก็บมันไว้รอบ ๆ เพื่อทำให้ภาพสมบูรณ์)

มันเปรียบเทียบลบ , การตั้งค่าnullและการตั้งค่าที่ไม่ได้กำหนด

แต่โปรดจำไว้ว่ามันทดสอบกรณีเมื่อคุณลบ / ตั้งค่าคุณสมบัติหลายครั้ง


2

นอกเหนือจากคำถาม GC สำหรับประสิทธิภาพที่ควรพิจารณาการเพิ่มประสิทธิภาพที่เบราว์เซอร์อาจทำในพื้นหลัง ->

http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/

ดูเหมือนว่าจะเป็นการดีกว่าหากการอ้างอิงเป็นโมฆะกว่าที่จะลบเนื่องจากอาจเปลี่ยนการใช้ Chrome 'ระดับ' เบื้องหลัง


1

IE 5 ถึง 8 มีข้อผิดพลาดที่ใช้การลบในคุณสมบัติของวัตถุโฮสต์ (Window, Global, DOM ฯลฯ ) พ่น TypeError "วัตถุไม่สนับสนุนการกระทำนี้"

var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
    delete el.foo;
}catch(){
    //alert("Curses, drats and double double damn!");
    el.foo=undefined; // a work around
}

ในภายหลังหากคุณต้องการตรวจสอบว่าสถานที่ให้บริการมีความหมายการใช้มูลค่าเต็มel.foo !== undefinedเพราะ"foo" in el จะกลับจริงใน IE

หากคุณต้องการทรัพย์สินที่จะหายไปจริงๆ ...

function hostProxy(host){
    if(host===null || host===undefined) return host;
    if(!"_hostProxy" in host){
       host._hostproxy={_host:host,prototype:host};
    }
    return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};

delete el.foo; // removing property if a non-host object

ถ้าคุณต้องการใช้วัตถุโฮสต์กับโฮสต์ API ...

el.parent.removeChild(el._host);

1

ฉันพบบทความนี้ในการค้นหาคำตอบเดียวกันนี้ สิ่งที่ฉันทำลงไปคือการเอาobj.pop()ค่า / วัตถุทั้งหมดที่เก็บไว้ในวัตถุของฉันออกมาเพื่อที่ฉันจะได้นำวัตถุนั้นกลับมาใช้ใหม่ได้ ไม่แน่ใจว่านี่เป็นการปฏิบัติที่ไม่ดีหรือไม่ เทคนิคนี้มีประโยชน์สำหรับฉันในการทดสอบรหัสของฉันในเครื่องมือ Chrome Dev หรือ FireFox Web Console


1

งานนี้สำหรับฉันแม้ว่ามันจะไม่ใช่แนวปฏิบัติที่ดี มันเพียงลบองค์ประกอบที่เกี่ยวข้องทั้งหมดที่เป็นวัตถุ

 for (element in homeService) {
          delete homeService[element];
  }

แนวปฏิบัติที่ดีที่สุดคืออะไร ฉันจำได้ว่าการอ่านว่าตัวดำเนินการลบนั้นไม่สามารถนำไปใช้ในการลบคุณสมบัติวัตถุได้ดีที่สุด ฉันเชื่อว่าฉันอ่านสิ่งนี้ในหนังสือ JavaScript ของ Crockford แต่ไม่สามารถขุดได้ในขณะนี้
zero_cool

0

การตั้งค่าตัวแปรเพื่อให้nullแน่ใจว่าได้ทำลายการอ้างอิงใด ๆ ไปยังวัตถุในเบราว์เซอร์ทั้งหมดรวมถึงการอ้างอิงแบบวงกลมที่ทำระหว่างองค์ประกอบ DOM และขอบเขต Javascript โดยการใช้deleteคำสั่งเรากำลังทำเครื่องหมายวัตถุที่จะถูกล้างในการทำงานครั้งต่อไปของคอลเลกชันขยะ แต่หากมีหลายตัวแปรที่อ้างอิงถึงวัตถุเดียวกันการลบตัวแปรเดียวจะไม่ทำให้วัตถุว่างเปล่ามันจะลบการเชื่อมโยงระหว่างตัวแปรนั้นและ วัตถุ. และในการเรียกใช้ครั้งต่อไปของการรวบรวมขยะจะมีเพียงการล้างตัวแปรเท่านั้น

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