2013-02-19 9 views
93

क्या इनमें से कोई भी करने में कोई महत्वपूर्ण अंतर है?a.x बनाम a.x = अपरिभाषित

delete a.x; 

बनाम

a.x = undefined; 

जहां

a = { 
    x: 'boo' 
}; 

यह है कि वे बराबर हैं कहा जा सकता है?

(मैं "V8 likes not using delete better" की तरह खाते सामान को ध्यान में रखकर नहीं कर रहा हूँ)

+2

डिलीट ऑपरेटर पूरी तरह से एक संपत्ति को हटा देता है। एक संपत्ति को अपरिभाषित करने के लिए मूल्य को हटा देता है। संपत्ति को शून्य में सेट करने से मूल्य को शून्य मान में बदल दिया जाता है। यहाँ एक पर्फ़ परीक्षण करता है, तो आप की तरह है: http://jsperf.com/delete-vs-undefined-vs-null/3 – j08691

+1

@ Nit j08691: यह मूल्य नहीं निकालता है। यह 'undefined' मूल्य है, जो अभी भी एक है के रूप में प्रदान करती है .. –

+0

आपको इस बारे में बात करनी चाहिए कि आप इसकी परवाह क्यों करते हैं, तो उत्तर आपकी वास्तविक समस्या को पूरा कर सकता है। –

उत्तर

121

वे समान नहीं होते हैं। मुख्य अंतर यह है

a.x = undefined 

स्थापित करने का मतलब है कि a.hasOwnProperty("x") अभी भी सच वापस आ जाएगी, और इसलिए, यह अभी भी एक for in पाश में दिखाई देगा, और में Object.keys()

delete a.x 

मतलब यह है कि a.hasOwnProperty("x") अवास्तविक लौटाते हैं है

जिस तरह से वे समान हैं, आप यह नहीं बता सकते कि

परीक्षण करके कोई संपत्ति मौजूद है या नहीं
if (a.x === undefined) 

जो तुम अगर आप निर्धारित करने के लिए एक संपत्ति मौजूद है कोशिश कर रहे हैं ऐसा नहीं करना चाहिए, तो आप हमेशा

// If you want inherited properties 
if ('x' in a) 

// If you don't want inherited properties 
if (a.hasOwnProperty('x')) 

का उपयोग करना चाहिए प्रोटोटाइप श्रृंखला (zzzzBov ने उल्लेख किया) कॉलिंग delete यह करने की अनुमति देगा के बाद प्रोटोटाइप श्रृंखला ऊपर जाना है, जबकि अपरिभाषित करने के लिए मान सेट श्रृंखलित प्रोटोटाइप में संपत्ति के लिए देखो नहीं होगा http://jsfiddle.net/NEEw4/1/

var obj = {x: "fromPrototype"}; 
var extended = Object.create(obj); 
extended.x = "overriding"; 
console.log(extended.x); // overriding 
extended.x = undefined; 
console.log(extended.x); // undefined 
delete extended.x; 
console.log(extended.x); // fromPrototype 

विरासत गुणों को हटा रहा है यदि आप जिस संपत्ति को हटाने का प्रयास कर रहे हैं वह विरासत में है, delete इसे प्रभावित नहीं करेगा। यही है, delete केवल वस्तु से संपत्तियों को हटा देता है, विरासत गुण नहीं।

var obj = {x: "fromPrototype"}; 
var extended = Object.create(obj); 
delete extended.x; 
console.log(extended.x); // Still fromPrototype 

इसलिए, यदि आप यकीन है कि एक वस्तु के मूल्य अपरिभाषित हो जाएगा बनाने की जरूरत है, deleteundefined को उस स्थिति में काम नहीं करेगा जब संपत्ति विरासत में मिला है, तो आप सेट करना होगा (ओवरराइड) यह। जब तक जगह है कि यह के लिए जाँच कर रहा है hasOwnProperty उपयोग करेगा, लेकिन यह संभावना है कि हर जगह की जाँच करता है कि ग्रहण करने के लिए सुरक्षित नहीं होगा यह hasOwnProperty

+1

'' x '' में 'पूर्व' के साथ 'सत्य' और बाद वाले के साथ 'झूठी' भी लौटाएगा। 'Object.keys' का आउटपुट भी अलग होगा। – lonesomeday

+0

आप क्यों कहते हैं कि मुझे अपरिभाषित की जांच नहीं करनी चाहिए? मुझे काफी उचित लगता है। – bevacqua

+0

@ निको क्योंकि यह आपको नहीं बताएगा कि कोई संपत्ति मौजूद है या नहीं। मैं यह नहीं कह रहा हूं कि इसका कभी भी उपयोग न करें। लेकिन अगर आप 'अपरिभाषित' की जांच कर रहे हैं, तो आप 'if (ax)' की जांच भी कर सकते हैं, जब तक कि यह संख्याओं के लिए न हो और 0 मान्य हो –

25

का उपयोग करेगा सवाल व्याख्या करने के लिए:

delete a.x और a.x = undefined बराबर हैं ?

सं

पूर्व चर से कुंजी, बाद में सेट undefined के एक मूल्य के साथ कुंजी को हटा।ऑब्जेक्ट्स के गुणों पर पुनरावृत्ति करते समय यह एक फर्क पड़ता है, और जब hasOwnProperty का उपयोग किया जाता है।

a = { 
    x: true 
}; 
a.x = undefined; 
a.hasOwnProperty('x'); //true 
delete a.x; 
a.hasOwnProperty('x'); //false 

इसके अतिरिक्त, प्रोटोटाइप श्रृंखला शामिल होने पर इससे महत्वपूर्ण अंतर आएगा।

function Foo() { 
    this.x = 'instance'; 
} 
Foo.prototype = { 
    x: 'prototype' 
}; 
a = new Foo(); 
console.log(a.x); //'instance' 

a.x = undefined; 
console.log(a.x); //undefined 

delete a.x; 
console.log(a.x); //'prototype' 
+2

+1 'हटाएं' के बारे में महान बिंदु प्रोटोटाइप श्रृंखला –

1

नोड से यह आरईपीएल अंतर को चित्रित करना चाहिए।

> a={ x: 'foo' }; 
{ x: 'foo' } 
> for (var i in a) { console.log(i); }; 
x 
undefined 
> a.x=undefined; 
undefined 
> for (var i in a) { console.log(i); }; 
x 
undefined 
> delete a.x; 
true 
> for (var i in a) { console.log(i); }; 
undefined 
2

नाम थोड़ा उलझन में हैं। a.x = undefined सिर्फ undefined को संपत्ति करता है, पर संपत्ति अभी भी वहाँ है:

> var a = {x: 3}; 
> a.x = undefined; 
> a.constructor.keys(a) 
["x"] 

delete वास्तव में इसे हटा देता है:

> var a = {x: 3}; 
> delete a.x; 
> a.constructor.keys(a) 
[] 
2

हाँ वहाँ एक अंतर है। यदि आप delete a.x का उपयोग करते हैं तो x किसी और की संपत्ति नहीं है, लेकिन यदि आप a.x=undefined का उपयोग करते हैं तो यह एक संपत्ति है लेकिन इसका मान अपरिभाषित है।

1

मुझे यकीन है कि आप var o1 = {p:undefined}; और var o2 = {}; के बीच अंतर देख सकते हैं।

दोनों मामलों में, o.pundefined हो जाएगा, लेकिन पहले मामले में, यह क्योंकि उस मूल्य है और दूसरे मामले में क्योंकि कोई मूल्य है। delete o1.p;:

delete ऑपरेटर आप o1 (या किसी अन्य वस्तु एक मूल्य के अपने p प्रॉपर्टी को निर्दिष्ट किया है) कि जिस तरह से o2 करने से प्राप्त करने देता है।

रिवर्स ऑपरेशन केवल o1.p = undefined; संपत्ति के लिए एक मान (undefined इस उदाहरण में असाइन करके किया जा सकता है लेकिन यह कुछ और हो सकता है)।

तो कोई, वे बराबर नहीं हैं।


delete o.p;

  • वस्तु से संपत्ति p निकाल देंगे अगर यह एक

  • अन्यथा

o.p = undefined; होगा

कुछ भी नहीं अगर यह अभी तक एक भी नहीं है और undefined

  • लिए अपने मूल्य सेट

    • वस्तु में कोई प्रॉपर्टी p जोड़ने बस संपत्ति के मूल्य बदलते हैं वस्तु पहले से ही यह

    है

    एक प्रदर्शन के दृष्टिकोण से, deleteबुरा क्योंकि यह वस्तु की संरचना को संशोधित करता है (यदि आपने इसे निर्माता में प्रारंभ नहीं किया है तो बस एक नई संपत्ति जोड़ने की तरह)।

    जबकि undefined पर मान सेट करना सामग्री को भी जारी करता है लेकिन संरचना को संशोधित करने के लिए मजबूर किए बिना।

  • 0

    ऑब्जेक्ट बस एक वृक्ष प्रतिनिधित्व है, जिसका अर्थ है, स्मृति में रूट विभिन्न बिंदुओं को इंगित करता है जहां उन वस्तुओं की कुंजी संग्रहित होती है। और वह स्थान किसी अन्य स्थान पर इंगित करता है जहां उस कुंजी का वास्तविक मान संग्रहीत होता है, या ऐसे स्थान जहां बच्चे कुंजी संग्रहीत होती हैं या स्थान जहां सरणी मान संग्रहीत होते हैं।

    जब आप को नष्ट का उपयोग कर एक वस्तु से किसी भी कुंजी को हटाते हैं, वास्तव में यह है कि कुंजी और उसकी मूल वस्तु और चाबी की स्मृति स्थानों और अपने मूल्य एक और जानकारी संग्रहीत करने के लिए उपलब्ध हो जाती रहे हैं के बीच की कड़ी को हटाता है।

    जब आप अपने मान के रूप में अपरिभाषित सेट करके किसी भी कुंजी को हटाने का प्रयास करते हैं, तो आप उस कुंजी को हटाए बिना अपना मान निर्धारित कर रहे हैं। इसका मतलब है कि कुंजी मेमोरी लोकेशन अभी भी अपने मूल ऑब्जेक्ट से जुड़ा हुआ है और यदि कुंजी अपरिभाषित है तो मान।

    हटाए गए कीवर्ड का उपयोग करने के बजाय अपरिभाषित का उपयोग करना एक बुरा अभ्यास है, क्योंकि यह उस कुंजी के स्मृति स्थान को जारी नहीं करता है।

    कुंजी की भी मौजूद नहीं है, और यदि आप अपरिभाषित सेट करते हैं, तो वह कुंजी 'अपरिभाषित' मान के साथ बनाई जाएगी।

    उदाहरण के लिए। var a = {} a.d = अपरिभाषित; console.log (ए); // यह प्रिंट करेगा {डी: अपरिभाषित}

    विरासत गुणों के साथ काम नहीं किया जा सकता क्योंकि यह संपत्ति उस बच्चे वस्तु का हिस्सा नहीं है।

    +1

    पर जाने की अनुमति देता है ध्यान दें कि नए इंजन आपको चाबियाँ नहीं हटाते हैं, क्योंकि जब आप इंजन करते हैं तो इंजन के लिए एक नई कक्षा बनाने की आवश्यकता होती है और जहां भी "कक्षा" का संदर्भ दिया जाता है उसे अपडेट किया जाता है। –

    +0

    @ जुआनमेंडेस, क्या आप कृपया कोई संदर्भ दे सकते हैं। –

    +2

    देखें [क्या हटाए गए कीवर्ड का उपयोग किसी ऑब्जेक्ट के v8 अनुकूलन को प्रभावित करता है?] (Https://groups.google.com/forum/#!topic/v8-users/zE4cOHBkAnY) टीएल; डीआर 'अंगूठे के सामान्य नियम के रूप में उपयोग करते हुए 'हटाएं' चीज धीमा कर देता है। 'और https://developers.google.com/v8/design 'जावास्क्रिप्ट गुणों तक पहुंचने के लिए आवश्यक समय को कम करने के लिए, V8 गुणों तक पहुंचने के लिए गतिशील लुकअप का उपयोग नहीं करता है। इसके बजाए, वी 8 गतिशील रूप से दृश्यों के पीछे छिपा वर्ग बनाता है। वी 8 में, एक ऑब्जेक्ट अपनी छुपी कक्षा को बदलता है जब एक नई संपत्ति जोड़ दी जाती है। ', और अंत में https://www.smashingmagazine.com/2012/11/writing-fast-memory- कुशल- जावास्क्रिप्ट / –

    संबंधित मुद्दे