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

Заметки

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

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

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

Ответ 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

Ответ 9

Переменные, в отличие от простых свойств, имеют атрибут [[Конфигурируемый]], что означает невозможность удалить переменную с помощью оператора delete. Однако существует один контекст выполнения, на который это правило не влияет. Это контекст eval: атрибут [[Configurable]] не задан для переменных.

Ответ 10

Вы не можете удалить переменную, если вы ее объявили (с var x;) во время первого использования. Однако, если ваша переменная x впервые появилась в script без объявления, вы можете использовать оператор delete (delete x;), и ваша переменная будет удалена, очень похожая на удаление элемента массива или удаление свойства объект.

Ответ 11

Я немного смущен. Если все, что вам нужно, это чтобы значение переменной не передавалось в другой сценарий, тогда нет необходимости удалять переменную из области. Просто обнулите переменную, а затем явно проверьте, является ли она нулевой. Зачем переживать проблему удаления переменной из области видимости? С какой целью этот сервер обнулять не может?

foo = null;
if(foo === null) or if(foo !== null)