javascript हरण जावास्क्रिप्ट चर को कैसे अनसेट करें?




व्हाट इस जावास्क्रिप्ट (8)

मेरे पास जावास्क्रिप्ट में एक वैश्विक चर है (वास्तव में एक window संपत्ति है, लेकिन मुझे नहीं लगता कि यह महत्वपूर्ण है) जो पहले से ही पिछली लिपि द्वारा पॉप्युलेट किया गया था, लेकिन मुझे एक और स्क्रिप्ट नहीं चाहिए जो बाद में अपना मूल्य देखने के लिए चलेगी या यह था यहां तक ​​कि परिभाषित भी।

मैंने some_var = undefined और यह typeof some_var == "undefined" के उद्देश्य के लिए काम करता है लेकिन मुझे नहीं लगता कि यह इसके बारे में जाने का सही तरीका है।

तुम क्या सोचते हो?


ईसीएमएस्क्रिप्ट 2015 प्रतिबिंब एपीआई प्रदान करता है। Reflect.deleteProperty() साथ ऑब्जेक्ट प्रॉपर्टी को हटाना संभव है:

Reflect.deleteProperty(myObject, 'myProp');
// it is equivalent to:
delete myObject.myProp;
delete myObject['myProp'];

वैश्विक window ऑब्जेक्ट की संपत्ति को हटाने के लिए:

Reflect.deleteProperty(window, 'some_var');

कुछ मामलों में गुणों को हटाया नहीं जा सकता है (जब संपत्ति कॉन्फ़िगर करने योग्य नहीं होती है) और फिर यह फ़ंक्शन false (साथ ही ऑपरेटर को हटा देता है ) देता है। अन्य मामलों में true आता true :

Object.defineProperty(window, 'some_var', {
    configurable: false,
    writable: true,
    enumerable: true,
    value: 'some_val'
});

var frozen = Object.freeze({ myProperty: 'myValue' });
var regular = { myProperty: 'myValue' };
var blank = {};

console.log(Reflect.deleteProperty(window, 'some_var')); // false
console.log(window.some_var); // some_var

console.log(Reflect.deleteProperty(frozen, 'myProperty')); // false
console.log(frozen.myProperty); // myValue

console.log(Reflect.deleteProperty(regular, 'myProperty')); // true
console.log(regular.myProperty); // undefined

console.log(Reflect.deleteProperty(blank, 'notExistingProperty')); // true
console.log(blank.notExistingProperty); // undefined

सख्त मोड में चलाते समय deleteProperty फ़ंक्शन और ऑपरेटर को delete बीच एक अंतर है:

'use strict'

var frozen = Object.freeze({ myProperty: 'myValue' });

Reflect.deleteProperty(frozen, 'myProperty'); // false
delete frozen.myProperty;
// TypeError: property "myProperty" is non-configurable and can't be deleted

वैरिएबल, सरल गुणों के विपरीत, विशेषता [[कॉन्फ़िगर करने योग्य]] है , जिसका अर्थ है डिलीट ऑपरेटर के माध्यम से एक चर को हटाने की असंभवता। हालांकि एक निष्पादन संदर्भ है जिस पर यह नियम प्रभावित नहीं होता है। यह eval संदर्भ है: वहाँ [[कॉन्फ़िगर करने योग्य]] विशेषता चर के लिए सेट नहीं है।


टीएलडीआर: सरल परिभाषित चर (बिना var , let , const ) को हटाकर हटाया जा सकता है। यदि आप var , let , const उपयोग let - तो उन्हें हटाया नहीं जा सकता है न तो delete और न ही Reflect.deleteProperty साथ।

क्रोम 55:

simpleVar = "1";
"1"
delete simpleVar;
true
simpleVar;
VM439:1 Uncaught ReferenceError: simpleVar is not defined
    at <anonymous>:1:1
(anonymous) @ VM439:1
var varVar = "1";
undefined
delete varVar;
false
varVar;
"1"
let letVar = "1";
undefined
delete letVar;
true
letVar;
"1"
const constVar="1";
undefined
delete constVar;
true
constVar;
"1"
Reflect.deleteProperty (window, "constVar");
true
constVar;
"1"
Reflect.deleteProperty (window, "varVar");
false
varVar;
"1"
Reflect.deleteProperty (window, "letVar");
true
letVar;
"1"

एफएफ नाइटली 53.0 ए 1 एक ही व्यवहार दिखाता है।


@ स्कूनलाइफ़ का जवाब काम करेगा, लेकिन तकनीकी रूप से यह होना चाहिए

delete window.some_var; 

जब लक्ष्य ऑब्जेक्ट प्रॉपर्टी नहीं होता है तो हटाएं नो-ऑप होना चाहिए। जैसे,

(function() {
   var foo = 123;
   delete foo; // wont do anything, foo is still 123
   var bar = { foo: 123 };
   delete bar.foo; // foo is gone
}());

लेकिन चूंकि वैश्विक चर वास्तव में विंडो ऑब्जेक्ट के सदस्य हैं, यह काम करता है।

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

function Foo() {}
Foo.prototype = { bar: 123 };
var foo = new Foo();
// foo.bar is 123
foo.bar = 456;
// foo.bar is now 456
delete foo.bar;
// foo.bar is 123 again.

तो सावधान रहें।

संपादित करें: मेरा जवाब कुछ हद तक गलत है (अंत में "गलत धारणाएं" देखें)। लिंक सभी गॉरी विवरण बताता है, लेकिन सारांश यह है कि ब्राउज़र के बीच बड़े अंतर हो सकते हैं और उस ऑब्जेक्ट के आधार पर जो आप हटा रहे हैं। delete object.someProp को delete object.someProp आमतौर पर object !== window तक सुरक्षित delete object.someProp चाहिए object !== window । मैं अभी भी var साथ घोषित चर को हटाने के लिए इसका उपयोग नहीं करता हूं, हालांकि आप सही परिस्थितियों में कर सकते हैं।


some_var = null;

//or remove it..
delete some_var;

यदि आप बिना किसी चर के चर को घोषित कर रहे हैं, तो उचित तरीके से delete foo का उपयोग करना होगा।

हालांकि, इसे हटाने के बाद, यदि आप इसे किसी ऑपरेशन में उपयोग करने का प्रयास करते हैं जैसे कि ReferenceError एरर फेंक दिया जाएगा क्योंकि आप एक अविकसित, अपरिभाषित पहचानकर्ता को स्ट्रिंग नहीं जोड़ सकते हैं। उदाहरण:

x = 5;
delete x
alert('foo' + x )
// ReferenceError: x is not defined

कुछ परिस्थितियों में यह गलत, शून्य, या अपरिभाषित करने के लिए सुरक्षित हो सकता है, इसलिए यह घोषित किया गया है और इस प्रकार की त्रुटि नहीं फेंक देगा।

foo = false

ध्यान दें कि ECMAScript null , false , undefined , 0 , NaN , या '' सभी false मूल्यांकन करेंगे। बस सुनिश्चित करें कि आप !== ऑपरेटर का उपयोग नहीं करते हैं, बल्कि इसके बजाय != जब बूलियन के लिए जांच टाइप करें और आप पहचान जांच नहीं चाहते हैं (तो null == false और false == undefined )।

यह भी ध्यान रखें कि delete संदर्भों को "हटाएं" नहीं बल्कि केवल वस्तु पर गुण हैं, उदाहरण के लिए:

bah = {}, foo = {}; bah.ref = foo;

delete bah.ref;
alert( [bah.ref, foo ] )
// ,[object Object] (it deleted the property but not the reference to the other object)

यदि आपने var साथ एक चर घोषित किया है तो आप इसे हटा नहीं सकते:

(function() {
    var x = 5;
    alert(delete x)
    // false
})();

राइनो में:

js> var x
js> delete x
false

न ही आप कुछ पूर्वनिर्धारित गुणों को हटा सकते हैं जैसे Math.PI :

js> delete Math.PI
false

किसी भी भाषा के साथ delete लिए कुछ अजीब अपवाद हैं, यदि आप पर्याप्त देखभाल करते हैं तो आपको पढ़ना चाहिए:


जो कुछ भी लिखा था उसके अलावा, यह भी ध्यान दें कि रिटर्न बूलियन delete । यह आपको बता सकता है कि हटाना सफल था या नहीं।

अद्यतन करें:

नवीनतम क्रोम पर परीक्षण, सब कुछ हटाना था। delete फ़ंक्शन निम्न सभी विधियों के लिए true लौटा, और वास्तव में उन्हें हटा दिया:

implicit_global = 1;
window.explicit_global = 1;
function_set = function() {};
function function_dec() { };
var declared_variable = 1;

delete delete implicit_global; // true, tested on Chrome 52
delete window.explicit_global; // true, tested on Chrome 52
delete function_set; // true, tested on Chrome 52
delete function_dec; // true, tested on Chrome 52
delete declared_variable; // true, tested on Chrome 52

मुझे पता है कि यह एक पुराना धागा है, लेकिन चयनित उत्तर मेरे लिए पर्याप्त स्पष्ट नहीं है।

बिंदु यह है कि डिलीट ऑपरेटर किसी ऑब्जेक्ट से किसी संपत्ति को हटा देता है। यह एक चर को हटा नहीं सकता है। तो सवाल का जवाब इस बात पर निर्भर करता है कि वैश्विक चर या संपत्ति को कैसे परिभाषित किया जाता है।

(1) यदि यह var के साथ बनाया गया है, तो इसे हटाया नहीं जा सकता है।

उदाहरण के लिए:

var g_a = 1; //create with var, g_a is a variable 
delete g_a; //return false
console.log(g_a); //g_a is still 1

(2) यदि यह var के बिना बनाया गया है, तो इसे हटाया जा सकता है।

g_b = 1; //create without var, g_b is a property 
delete g_b; //return true
console.log(g_b); //error, g_b is not defined

तकनीकी स्पष्टीकरण

1. var का उपयोग करना

इस मामले में संदर्भ g_a बनाया गया है जो ECMAScript spec को " VariableEnvironment g_a " कहते हैं जो वर्तमान दायरे से जुड़ा हुआ है - यह फ़ंक्शन के अंदर var का उपयोग करने के मामले में फ़ंक्शन निष्पादन संदर्भ हो सकता है (हालांकि यह थोड़ा सा हो सकता है जब आप मानते हैं let अधिक जटिल) या "वैश्विक" कोड के मामले में वैरिएबल एंटरप्राइज वैश्विक ऑब्जेक्ट (अक्सर window ) से जुड़ा हुआ है।

वेरिएबल एंटरप्राइज़ में संदर्भ सामान्य रूप से हटाए जाने योग्य नहीं होते हैं - ईसीएमएस्क्रिप्ट 10.5 में विस्तृत प्रक्रिया विस्तार से बताती है, लेकिन यह कहने के लिए पर्याप्त है कि जब तक आपका कोड किसी eval संदर्भ में निष्पादित नहीं किया जाता है (जो कि अधिकांश ब्राउज़र-आधारित विकास कंसोल का उपयोग करता है), तो चर के साथ घोषित var हटाया नहीं जा सकता है।

2. var का उपयोग किए बिना

var कीवर्ड का उपयोग किए बिना किसी नाम को मान असाइन करने का प्रयास करते समय, जावास्क्रिप्ट नामित संदर्भ का पता लगाने की कोशिश करता है कि ईसीएमएस्क्रिप्ट स्पेक " VariableEnvironment " कहता है, और मुख्य अंतर यह है कि लेक्सिकल एवायरमेंट्स नेस्टेड हैं - यह एक लेक्सिकल एनवायरमेंट में माता-पिता हैं (ईसीएमएस्क्रिप्ट स्पेक "बाहरी पर्यावरण संदर्भ" कहता है) और जब जावास्क्रिप्ट लेक्सिकलएन्वायरमेंट में संदर्भ का पता लगाने में विफल रहता है, तो यह मूल लेक्सिकल एंटरप्राइज़ (जैसा कि 10.3.1 और 10.2.2.1 में विस्तृत है) में 10.2.2.1 । शीर्ष स्तर लेक्सिकल पर्यावरण पर्यावरण " वैश्विक पर्यावरण " है, और यह वैश्विक वस्तु से जुड़ा हुआ है कि इसके संदर्भ वैश्विक वस्तु के गुण हैं। तो यदि आप किसी ऐसे नाम तक पहुंचने का प्रयास करते हैं जिसे वर्तमान दायरे या किसी बाहरी क्षेत्र में एक var कीवर्ड का उपयोग करके घोषित नहीं किया गया था, तो जावास्क्रिप्ट अंततः उस संदर्भ के रूप में कार्य करने के लिए window ऑब्जेक्ट की एक संपत्ति प्राप्त करेगा। जैसा कि हमने पहले सीखा है, वस्तुओं पर गुण हटाया जा सकता है।

टिप्पणियाँ

  1. यह याद रखना महत्वपूर्ण है कि var घोषणाएं "फिसल गई हैं" - यानी उन्हें हमेशा उस दायरे की शुरुआत में माना जाता है, जो कि वे हैं - हालांकि वैल्यू कथन में मूल्य प्रारंभिक नहीं किया जा सकता है - यह छोड़ा गया है यह है। तो निम्न कोड में, a वैरिएबल एंटरप्राइज़ का संदर्भ है, न कि window संपत्ति और उसका मान कोड के अंत में 10 होगा:

    function test() { a = 5; var a = 10; }

  2. उपर्युक्त चर्चा तब होती है जब "सख्त मोड" सक्षम नहीं होता है। "सख्त मोड" और लेक्सिकल संदर्भों का उपयोग करते समय लुकअप नियम थोड़ा अलग होते हैं जो "सख्त मोड" के बिना विंडो गुणों के लिए हल हो जाते हैं, "सख्त मोड" के तहत "अविकसित चर" त्रुटियां बढ़ाएंगे। मैं वास्तव में यह नहीं समझ पाया कि यह कहां निर्दिष्ट है, लेकिन यह ब्राउज़र कैसे व्यवहार करता है।





undefined