Как сбросить переменную 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 объект, чтобы служить в качестве этой ссылки. Как мы узнали ранее, свойства объектов могут быть удалены.

Заметки

  1. Важно помнить, что var объявления "подняты" - т.е. они всегда считаются произошедшими в начале области действия, в которой они находятся, - но не инициализация значения, которая может быть выполнена в var Заявление - это оставлено там, где оно есть. Итак, в следующем коде a является ссылкой из VariableEnvironment, а не window собственность и ее стоимость будет 10 в конце кода:

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

  2. Обсуждение выше, когда "строгий режим" не включен. Правила поиска немного отличаются при использовании "строгого режима", и лексические ссылки, которые разрешены в свойствах окна без "строгого режима", приведут к ошибкам "необъявленная переменная" в "строгом режиме". Я не совсем понял, где это указано, но как ведут себя браузеры.

Ответ @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 как и с любым языком, если вы заботитесь достаточно, вы должны прочитать:

some_var = null;

//or remove it..
delete some_var;

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)

(источник )


Дальнейшее чтение:

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)
Другие вопросы по тегам