Как сбросить переменную JavaScript?
У меня есть глобальная переменная в JavaScript (на самом деле window
свойство, но я не думаю, что это имеет значение), который уже был заполнен предыдущим скриптом, но я не хочу, чтобы другой скрипт запускался позже, чтобы увидеть его значение или чтобы он был даже определен.
Я положил some_var = undefined
и это работает с целью тестирования typeof some_var == "undefined"
но я действительно не думаю, что это правильный путь.
Как вы думаете?
12 ответов
delete
Оператор удаляет свойство из объекта. Он не может удалить переменную. Таким образом, ответ на вопрос зависит от того, как определяется глобальная переменная или свойство.
(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 называет " VariableEnvironment ", которая прикреплена к текущей области - это может быть контекст выполнения функции в случае использования var
внутри функции (хотя это может быть немного сложнее, если учесть, let
) или в случае "глобального" кода VariableEnvironment присоединяется к глобальному объекту (часто window
).
Ссылки в VariableEnvironment обычно не удаляются - процесс, подробно описанный в ECMAScript 10.5, объясняет это подробно, но достаточно сказать, что если ваш код не выполняется в eval
контекст (который используют большинство браузерных консолей разработки), затем переменные, объявленные с var
не может быть удалено
2. Без использования var
При попытке присвоить значение имени без использования var
В ключевом слове Javascript пытается найти именованную ссылку в том, что спецификация ECMAScript называет " LexicalEnvironment ", и основное отличие заключается в том, что LexicalEvironment являются вложенными - то есть у LexicalEnvironment есть родительский элемент (что спецификация ECMAScript называет "ссылкой на внешнюю среду") и когда Javscript не может найти ссылку в LexicalEenvironment, он смотрит в родительскую LexicalEnvironment (как подробно описано в 10.3.1 и 10.2.2.1). Верхний уровень LexicalEnvironment - это " глобальная среда ", которая привязана к глобальному объекту в том смысле, что его ссылки являются свойствами глобального объекта. Так что если вы попытаетесь получить доступ к имени, которое не было объявлено с помощью var
ключевое слово в текущей области или любых внешних областях, Javascript будет в конечном итоге получить свойство window
объект, чтобы служить в качестве этой ссылки. Как мы узнали ранее, свойства объектов могут быть удалены.
Заметки
Важно помнить, что
var
объявления "подняты" - т.е. они всегда считаются произошедшими в начале области действия, в которой они находятся, - но не инициализация значения, которая может быть выполнена вvar
Заявление - это оставлено там, где оно есть. Итак, в следующем кодеa
является ссылкой из VariableEnvironment, а неwindow
собственность и ее стоимость будет10
в конце кода:function test() { a = 5; var a = 10; }
Обсуждение выше, когда "строгий режим" не включен. Правила поиска немного отличаются при использовании "строгого режима", и лексические ссылки, которые разрешены в свойствах окна без "строгого режима", приведут к ошибкам "необъявленная переменная" в "строгом режиме". Я не совсем понял, где это указано, но как ведут себя браузеры.
Ответ @scunlife сработает, но технически это должно быть
delete window.some_var;
Предполагается, что delete не используется, если цель не является свойством объекта. например,
(function() {
var foo = 123;
delete foo; // wont do anything, foo is still 123
var bar = { foo: 123 };
delete bar.foo; // foo is gone
}());
Но поскольку глобальные переменные на самом деле являются членами объекта window, он работает.
Когда задействованы цепочки прототипов, использование delete становится более сложным, поскольку оно удаляет только свойство из целевого объекта, а не прототип. например,
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
как правило, должны быть в безопасности, пока object !== window
, Я все еще не использовал бы это, чтобы удалить переменные, объявленные с var
хотя вы можете при правильных обстоятельствах.
Если вы неявно объявляете переменную без var
, правильный способ будет использовать delete foo
,
Однако после его удаления, если вы попытаетесь использовать это в такой операции, как добавление ReferenceError
будет брошено, потому что вы не можете добавить строку в необъявленный, неопределенный идентификатор. Пример:
x = 5;
delete x
alert('foo' + x )
// ReferenceError: x is not defined
В некоторых ситуациях может быть безопаснее присвоить ему значение false, null или undefined, чтобы оно было объявлено и не выдавало этот тип ошибки.
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
как и с любым языком, если вы заботитесь достаточно, вы должны прочитать:
TLDR: простые определяемые переменные (без var
, let
, const
) можно удалить с помощью delete
, Если вы используете var
, let
, const
- их нельзя было удалить ни с помощью delete
ни с 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 показывает то же самое поведение.
⚠️ Принятый ответ (и другие) устарел!
TL;DR
никак не удалить переменные .
(Это только для удаления свойства из объекта.)Правильный способ "сбросить" - просто установить для переменной значение<em><strong></strong></em>. ( )
(Это позволяет автоматическим процессам JavaScript удалять переменную из памяти.)
Пример:
x = null;
😉
Больше информации:
Использование Оператор над переменной устарел с 2012 года, когда все браузеры реализовали (автоматическую) сборку мусора с пометкой и очисткой . Процесс работает, автоматически определяя, когда объекты / переменные становятся « недостижимыми » (решая, требуются ли они по-прежнему для кода).
С помощью JavaScript во всех современных браузерах:
В оператор используется только для удаления свойства объекта; он не удаляет переменные.
В отличие от общепринятого мнения (возможно, из-за других языков программирования, таких как C++), оператор не имеет ничего общего с непосредственным освобождением памяти. Управление памятью осуществляется косвенно, через прерывание ссылок. ( источник )
При использовании строгого режима (
'use strict';
, в отличие от обычного / "небрежного режима" ) попытка удалить переменную приведет к ошибке и не допускается. Обычные переменные в JavaScript нельзя удалить с помощью
delete
оператор ( ) (или любым другим способом, по состоянию на 2021 год).
... увы, единственное решение:
Освобождение содержимого переменной
Чтобы освободить содержимое переменной , вы можете просто установить для нее значение<em> <tcode id="3179853"></tcode></em>:
var x;
// ...
x = null; // (x can now be garbage collected)
(источник )
Дальнейшее чтение:
- Управление памятью (документы MDN)
- Сборка мусора (Университет Эребру)
- Самые основы сборки мусора (javascript.info)
- Понимание управления памятью JavaScript с помощью сборки мусора
- Устранение утечек памяти в Javascript
ECMAScript 2015 предлагает Reflect API. Удалить свойство объекта можно с помощью Reflect.deleteProperty ():
Reflect.deleteProperty(myObject, 'myProp');
// it is equivalent to:
delete myObject.myProp;
delete myObject['myProp'];
Удалить свойство global window
объект:
Reflect.deleteProperty(window, 'some_var');
В некоторых случаях свойства не могут быть удалены (если свойство не настраивается), а затем эта функция возвращает false
(а также оператор удаления). В других случаях возвращается 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
В дополнение к тому, что все написали, также обратите внимание, что delete
возвращает логическое значение. Он может сказать вам, было ли удаление успешным или нет.
ОБНОВИТЬ:
Тестирование на последнем Chrome, все можно было удалить. 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
Переменные, в отличие от простых свойств, имеют атрибут [[Configurable]], что означает невозможность удаления переменной с помощью оператора удаления. Однако есть один контекст выполнения, на который это правило не влияет. Это eval context: там атрибут [[Configurable]] не установлен для переменных.
Оператор удаления удаляет свойство из объекта.
delete object.property
delete object['property']
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
По вопросу вам нужно одно из следующих
delete some_var;
delete window.some_var;
delete window['some_var'];
Вы не можете удалить переменную, если вы объявили ее (с помощью var x;) во время первого использования. Однако, если ваша переменная x впервые появилась в скрипте без объявления, вы можете использовать оператор delete (delete x;), и ваша переменная будет удалена, что очень похоже на удаление элемента массива или удаление свойства объекта,
Я немного смущен. Если все, что вам нужно, это чтобы значение переменной не передавалось в другой сценарий, тогда нет необходимости удалять переменную из области. Просто обнулите переменную, а затем явно проверьте, является ли она нулевой. Зачем переживать проблему удаления переменной из области видимости? С какой целью этот сервер обнулять не может?
foo = null;
if(foo === null) or if(foo !== null)