Jak wyłączyć zmienną JavaScript?

Mam zmienną globalną w JavaScript (właściwie Właściwość window, ale nie sądzę, że ma to znaczenie), która była już wypełniona przez poprzedni skrypt, ale nie chcę innego skryptu, który uruchomi się później, aby zobaczyć jego wartość lub że został nawet zdefiniowany.

Umieściłem some_var = undefined i działa to w celu przetestowania typeof some_var == "undefined", ale naprawdę nie sądzę, aby to był właściwy sposób, aby to zrobić.

Co o tym myślisz?
Author: Jeremy Banks, 2009-10-20

10 answers

Operator delete usuwa właściwość z obiektu. Nie można usunąć zmiennej. Tak więc odpowiedź na pytanie zależy od tego, w jaki sposób globalna zmienna lub właściwość jest zdefiniowana.

(1) jeśli jest utworzony za pomocą var, nie można go usunąć.

Na przykład:

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) jeśli zostanie utworzony bez var, może zostać usunięty.

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

Wyjaśnienie Techniczne

1. Using var

W tym przypadku Referencja g_a jest tworzona w ECMAScript Spec calls "Variable Environment" to jest dołączone do bieżącego zakresu-może to być kontekst wykonania funkcji w przypadku użycia var wewnątrz funkcji (choć może to być nieco bardziej skomplikowane, jeśli weźmiemy pod uwagę let) lub w przypadku kodu "globalnego" zmiennyEnvironment jest dołączony do obiektu globalnego (często window).

Odwołania W Zmiennej nie są normalnie usuwalne-proces szczegółowo opisany w ECMAScript 10.5 wyjaśnia to szczegółowo, ale wystarczy powiedzieć, że jeśli kod nie jest wykonywany w kontekście eval (którego używa większość konsol programistycznych opartych na przeglądarce), zmienne zadeklarowane przez var nie mogą zostać usunięte.

2. Bez Użycia var

Podczas próby przypisania wartości do nazwy bez użycia słowa kluczowego var, Javascript próbuje zlokalizować nazwane odniesienie w tym, co wywołuje Specyfikacja ECMAScript"LexicalEnvironment ", i główna różnica polega na tym, że LexicalEvironmentS są zagnieżdżone - to jest LexicalEnvironment ma rodzica (co spec ECMAScript nazywa "zewnętrznym odniesieniem do środowiska"), a gdy Javscript nie zlokalizuje odniesienia w LexicalEenvironment , wygląda w rodzicu LexicalEnvironment (jak opisano w 10.3.1 oraz 10.2.2.1). Najwyższy poziom leksykalne środowisko to "środowisko globalne", oraz jest to związane z obiektem globalnym, ponieważ jego odwołania są właściwościami obiektu globalnego. Jeśli więc spróbujesz uzyskać dostęp do nazwy, która nie została zadeklarowana za pomocą słowa kluczowego var w bieżącym zakresie lub jakimkolwiek zewnętrznym zakresie, Javascript ostatecznie pobierze właściwość obiektu window, aby służyć jako odniesienie. Jak dowiedzieliśmy się wcześniej, właściwości na obiektach mogą zostać usunięte.

Uwagi

  1. Należy pamiętać, że var deklaracje są "podnoszone" - tzn. są zawsze uważa się, że miało to miejsce na początku zakresu, w którym się znajdują - choć nie inicjalizacja wartości, którą można wykonać w instrukcji var - która pozostaje tam, gdzie jest. Tak więc w poniższym kodzie a jest odniesieniem do zmiennej , a nie window Własności i jej wartość będzie 10 na końcu kodu:

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

  2. Powyższa dyskusja dotyczy sytuacji, gdy" tryb ścisły " nie jest włączony. Reguły wyszukiwania są nieco inne, gdy Używanie "trybu ścisłego" i odniesień leksykalnych, które rozwiązałyby się we właściwościach okna bez "trybu ścisłego", spowoduje błędy" niezgłoszonej zmiennej "w"trybie ścisłym". Nie bardzo rozumiem, gdzie to jest określone, ale jego jak przeglądarki zachowują się.

 338
Author: Dayong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-20 12:32:09

@scunlife ' s answer will work, but formalnie it should be

delete window.some_var; 

Delete ma być no-op, gdy obiekt docelowy nie jest właściwością obiektu. np.,

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

Ale ponieważ zmienne globalne są rzeczywiście członkami obiektu window, to działa.

Gdy używane są łańcuchy prototypów, użycie delete staje się bardziej złożone, ponieważ usuwa tylko właściwość z obiektu docelowego, a nie prototypu. np.,

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.
Więc bądź ostrożny.

EDIT: moja odpowiedź brzmi nieco niedokładne (patrz "nieporozumienia" na końcu). Link wyjaśnia wszystkie krwawe szczegóły, ale podsumowanie jest takie, że mogą występować duże różnice między przeglądarkami i w zależności od obiektu, z którego usuwasz. delete object.someProp powinny być ogólnie bezpieczne tak długo, jak object !== window. Nadal nie używałbym go do usuwania zmiennych zadeklarowanych przez var, chociaż można to zrobić w odpowiednich okolicznościach.

 265
Author: noah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-11 17:11:04

Jeśli domyślnie deklarujesz zmienną bez var, właściwym sposobem byłoby użycie delete foo.

Jednak po usunięciu go, jeśli spróbujesz użyć go w operacji takiej jak dodanie, ReferenceError zostanie wyrzucony, ponieważ nie możesz dodać ciągu znaków do niezgłoszonego, niezdefiniowanego identyfikatora. Przykład:

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

W niektórych sytuacjach bezpieczniejsze może być przypisanie go do false, null lub undefined, aby został zadeklarowany i nie wyrzuci tego typu błędu.

foo = false

Zauważ, że w ECMAScript null, false, undefined, 0, NaN, lub '' wszystkie ocenią na false. Po prostu upewnij się, że nie używasz operatora !==, ale zamiast tego != podczas sprawdzania typu dla wartości logicznych i nie chcesz sprawdzania tożsamości (więc null będzie == false i false == undefined).

Zauważ również, że delete nie "usuwa" referencji, a jedynie właściwości bezpośrednio na obiekcie, np.:

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)

Jeśli zadeklarowałeś zmienną za pomocą var nie możesz jej usunąć:

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

W Rhino:

js> var x
js> delete x
false

Nie można też usunąć niektórych predefiniowanych właściwości, takich jak Math.PI:

js> delete Math.PI
false

Istnieją pewne dziwne wyjątki od delete jak w każdym języku, jeśli zależy ci na tyle powinieneś przeczytać:

 34
Author: meder omuraliev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-13 14:19:30
some_var = null;

//or remove it..
delete some_var;
 30
Author: scunliffe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-20 19:24:58

TLDR: proste zdefiniowane zmienne (Bez var, let, const) można usunąć za pomocą delete. W przypadku stosowania var, let, const - nie można ich usunąć ani za pomocą delete, ani za pomocą Reflect.deleteProperty.

Chrome 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"

FF Nightly 53. 0A1 pokazuje to samo zachowanie.

 8
Author: Serj.by,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-05 15:13:36

ECMAScript 2015 oferuje API Reflect. Możliwe jest usunięcie właściwości obiektu za pomocą Reflect.deleteProperty():

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

Aby usunąć właściwość obiektu global window:

Reflect.deleteProperty(window, 'some_var');

W niektórych przypadkach właściwości nie można usunąć (gdy właściwość nie jest konfigurowalna) i wtedy ta funkcja zwraca false (jak również operator delete ). W innych przypadkach zwraca 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

Istnieje różnica między funkcją deleteProperty a operatorem delete podczas uruchamiania w tryb ścisły:

'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
 3
Author: madox2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-25 16:17:32

Operator delete usuwa właściwość z obiektu.

delete object.property
delete object['property']

Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete

Zgodnie z pytaniem potrzebujesz jednego z następujących pytań

delete some_var;
delete window.some_var;
delete window['some_var'];
 2
Author: Swarnendu Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-14 21:11:58

Oprócz tego, co wszyscy napisali, zauważ również, że delete Zwraca wartość logiczną. Może Ci powiedzieć, czy usunięcie się powiodło, czy nie.

UPDATE:

Testując najnowszą Chrome, wszystko można było usunąć. delete funkcja zwróciła true dla wszystkich następujących metod i faktycznie je usunęła:

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
 2
Author: oriadam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-14 15:09:24

Zmienne, w przeciwieństwie do prostych właściwości, mają atrybut [[konfigurowalny]] , co oznacza niemożność usunięcia zmiennej za pomocą operatora delete . Istnieje jednak jeden kontekst wykonania, na który zasada ta nie ma wpływu. Jest to kontekst eval : tam [[konfigurowalny]] atrybut nie jest ustawiony dla zmiennych.

 2
Author: Eldiyar Talantbek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-25 04:46:55

Nie możesz usunąć zmiennej, jeśli zadeklarowałeś ją (za pomocą var x;) przy pierwszym użyciu. Jeśli jednak twoja zmienna x pojawiła się w skrypcie po raz pierwszy bez deklaracji, możesz użyć operatora delete (delete x;) i twoja zmienna zostanie usunięta, bardzo podobnie jak usunięcie elementu tablicy lub usunięcie właściwości obiektu.

 1
Author: Satyapriya Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-31 17:48:42