कुल्हाड़ी बनाम कुल्हाड़ी हटाना = अपरिभाषित करना


138

क्या इन दोनों को करने में कोई महत्वपूर्ण अंतर है?

delete a.x;

बनाम

a.x = undefined;

कहाँ पे

a = {
    x: 'boo'
};

क्या यह कहा जा सकता है कि वे समान हैं?

(मैं "वी 8 पसंद करताdelete हूं बेहतर उपयोग नहीं कर रहा है" जैसे खाते में सामान नहीं ले रहा है )


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

1
@ j08691 Nit: यह मान नहीं निकालता है। यह undefinedमान के रूप में असाइन करता है , जो अभी भी है ..

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

जवाबों:


181

वे समकक्ष नहीं हैं। मुख्य अंतर यह है कि सेटिंग

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

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


1
"x" in atrueपूर्व के साथ भी लौटेंगे , और falseबाद वाले के साथ। का आउटपुट Object.keysभी अलग होगा।
लोन्समेडे

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

@ निको क्योंकि अगर संपत्ति मौजूद है तो आपको यह नहीं बताया जाएगा। मैं यह नहीं कह रहा हूँ कि इसका इस्तेमाल कभी मत करो। लेकिन अगर आप जाँच कर रहे हैं undefined, तो आप बस जाँच कर सकते हैं if (a.x), जब तक कि यह संख्या के लिए नहीं है और 0 वैध है
जुआन मेंडेस

33

प्रश्न को स्पष्ट करने के लिए:

कर रहे हैं 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 शानदार बिंदु deleteइसे प्रोटोटाइप श्रृंखला में जाने की अनुमति देने के बारे में
जुआन मेंडेस

4

यदि a.xएक सेटर फ़ंक्शन है, a.x = undefinedतो फ़ंक्शन को कॉल delete a.xकरेगा जबकि फ़ंक्शन को कॉल नहीं करेगा।


3

हां, वहां एक अंतर है। यदि आप delete a.xx का उपयोग करते हैं तो कोई भी अधिक संपत्ति नहीं है, लेकिन यदि आप इसका उपयोग करते हैं a.x=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)
[]

1

नोड से इस REPL को अंतर स्पष्ट करना चाहिए।

> 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

1

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

दोनों मामलों में, o.pहो जाएगा undefined, लेकिन पहले मामले में, यह क्योंकि वह है मूल्य और दूसरे मामले में, क्योंकि वहाँ कोई मूल्य नहीं है

deleteवह ऑपरेटर है जो आपको उस तरह से o1(या किसी अन्य वस्तु से जो कि उसकी pसंपत्ति को दिया गया मूल्य है) प्राप्त करने देता o2है delete o1.p;:।

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

तो नहीं , वे समकक्ष नहीं हैं।


delete o.p; मर्जी

  • pयदि वह एक है तो वस्तु से संपत्ति को हटा दें

  • अन्यथा कुछ न करें

o.p = undefined; मर्जी

  • pयदि यह अभी तक एक नहीं है, तो वस्तु में एक संपत्ति जोड़ें और इसका मूल्य निर्धारित करेंundefined

  • यदि संपत्ति में पहले से ही संपत्ति का मूल्य बदल गया है


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

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


1

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

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

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

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

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

जैसे

var a = {};
a.d = undefined;
console.log(a); // this will print { d: undefined }

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


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

@JuanMendes, क्या आप कृपया कोई संदर्भ दे सकते हैं।
लक्ष्मीकांत डांगे

3
देखें क्या कीवर्ड हटाने का उपयोग किसी वस्तु के v8 अनुकूलन को प्रभावित करता है? TL, DR as a general rule of thumb, using 'delete' makes thing slower.और Developers.google.com/v8/design To reduce the time required to access JavaScript properties, V8 does not use dynamic lookup to access properties. Instead, V8 dynamically creates hidden classes behind the scenes. In V8, an object changes its hidden class when a new property is added. , और अंत में smashingmagazine.com/2012/11/…
जुआन मेंडेस

1

किसी ऑब्जेक्ट के बजाय, एक सरणी का उपयोग करके, मैं दिखा सकता हूं कि डिलीट अपरिभाषित की तुलना में कम हीप मेमोरी का उपयोग करता है।

उदाहरण के लिए, यह कोड समाप्त नहीं होगा:

let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
    ary.push(y);
    ary[y] = undefined;
    y += 1;
}
console(ary.length);

यह इस त्रुटि का उत्पादन करता है:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.

तो, जैसा कि आप देख सकते हैं कि undefinedवास्तव में ढेर स्मृति लेता है।

हालाँकि, यदि आप भी deleteआर्य-आइटम (केवल इसे सेट करने के बजाय undefined), कोड धीरे-धीरे समाप्त हो जाएगा:

let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
    ary.push(x);
    ary[x] = undefined;
    delete ary[x];
    x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);

ये चरम उदाहरण हैं, लेकिन वे इस बारे में एक बिंदु बनाते हैं deleteकि मैंने किसी का उल्लेख कहीं नहीं देखा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.