Как отключить переменную JavaScript?
У меня есть глобальная переменная в JavaScript (на самом деле это свойство window
, но я не думаю, что это важно), который уже был заполнен предыдущим script, но я не хочу, чтобы другой script позже, чтобы увидеть его значение или что он был даже определен.
Я положил some_var = undefined
, и он работает с целью тестирования typeof some_var == "undefined"
, но я действительно не думаю, что это правильный путь для этого.
Как вы думаете?
Ответы
Ответ 1
Оператор 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 ", и основное отличие заключается в том, что LexicalEvironments являются вложенными - то есть 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; }
-
Обсуждение выше, когда "строгий режим" не включен. Правила поиска немного отличаются при использовании "строгого режима", и лексические ссылки, которые разрешались бы в свойствах окна без "строгого режима", приводят к ошибкам "необъявленная переменная" в "строгом режиме". Я не совсем понял, где это указано, но как ведут себя браузеры.
Ответ 2
@scunlife ответ будет работать, но технически он должен быть
delete window.some_var;
delete должен быть не-op, если цель не является свойством объекта. например.
(function() {
var foo = 123;
delete foo; // wont do anything, foo is still 123
var bar = { foo: 123 };
delete bar.foo; // foo is gone
}());
Но поскольку глобальные переменные на самом деле являются членами оконного объекта, он работает.
Когда задействованы цепи прототипов, использование 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.
Поэтому будьте осторожны.
EDIT: Мой ответ несколько неточно (см. "Неправильные представления" в конце). Ссылка объясняет все детали gory, но резюме состоит в том, что между браузерами могут быть большие различия и в зависимости от объекта, который вы удаляете. delete object.someProp
обычно должен быть безопасным, если object !== window
. Я все равно не буду использовать его для удаления переменных, объявленных с помощью var
, хотя вы можете при подходящих обстоятельствах.
Ответ 3
Если вы неявно объявляете переменную без var
, правильным способом было бы использовать delete foo
.
Однако после его удаления, если вы попытаетесь использовать это в операции, например, добавьте ReferenceError
, потому что вы не можете добавить строку к необъявленному идентификатору undefined. Пример:
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
, как и для любого языка, если вы достаточно осторожны, вы должны прочитать:
Ответ 4
some_var = null;
//or remove it..
delete some_var;
Ответ 5
TL;DR: простые определенные переменные (без 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 показывает то же поведение.
Ответ 6
ECMAScript 2015 предлагает Reflect API. Можно удалить свойство объекта с помощью Reflect.deleteProperty():
Reflect.deleteProperty(myObject, 'myProp');
// it is equivalent to:
delete myObject.myProp;
delete myObject['myProp'];
Чтобы удалить свойство глобального объекта 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
Ответ 7
В дополнение к тому, что все написали, также обратите внимание, что delete
возвращает boolean. Он может сказать вам, удалено ли удаление или нет.
UPDATE:
Тестирование на последнем Chrome, все было deleltable. Функция 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
Ответ 8
Оператор delete удаляет свойство из объекта.
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'];
Ответ 9
Переменные, в отличие от простых свойств, имеют атрибут [[Конфигурируемый]], что означает невозможность удалить переменную с помощью оператора delete. Однако существует один контекст выполнения, на который это правило не влияет. Это контекст eval: атрибут [[Configurable]] не задан для переменных.
Ответ 10
Вы не можете удалить переменную, если вы ее объявили (с var x;) во время первого использования.
Однако, если ваша переменная x впервые появилась в script без объявления, вы можете использовать оператор delete (delete x;), и ваша переменная будет удалена, очень похожая на удаление элемента массива или удаление свойства объект.
Ответ 11
Я немного смущен. Если все, что вам нужно, это чтобы значение переменной не передавалось в другой сценарий, тогда нет необходимости удалять переменную из области. Просто обнулите переменную, а затем явно проверьте, является ли она нулевой. Зачем переживать проблему удаления переменной из области видимости? С какой целью этот сервер обнулять не может?
foo = null;
if(foo === null) or if(foo !== null)