JavaScript 변수를 설정 해제하는 방법?


591

JavaScript에 전역 변수가 있습니다 (실제로는 window속성이지만 중요하지는 않습니다). 이전 스크립트로 이미 채워져 있지만 나중에 그 값을 보거나 실행하기 위해 다른 스크립트를 원하지 않습니다. 한정된.

나는 some_var = undefined테스트 목적으로 작동 typeof some_var == "undefined"했지만 실제로 그것이 올바른 방법이라고 생각하지 않습니다.

어떻게 생각해?

답변:


453

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_aECMAScript 사양 이 현재 범위에 첨부 된 " 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.110.2.2.1 ). 최고 수준의 LexicalEnvironment 는 " 글로벌 환경입니다."은 참조가 전역 객체의 속성이라는 점에서 전역 객체에 바인딩됩니다. 따라서 var현재 범위 나 외부 범위에서 키워드를 사용하여 선언되지 않은 이름에 액세스하려고하면 Javascript는 결국 속성을 가져옵니다. 의 window객체가 참조 역할을합니다. 우리가 전에 배운대로, 개체의 속성은 삭제 될 수 있습니다.

노트

  1. var선언은 "호이 스팅" 되었다는 것을 기억하는 것이 중요합니다. 즉, var선언문 에서 수행 될 수있는 값 초기화가 아닌-선언문이있는 영역의 시작 부분에서 항상 발생한 것으로 간주됩니다. . 따라서 다음 코드 a에서 VariableEnvironment 의 참조 이며 window속성이 아니며 그 값은 10코드의 끝에 있습니다.

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

  2. 위의 설명은 "엄격 모드"가 활성화되지 않은 경우입니다. "엄격 모드"를 사용하는 경우 조회 규칙이 약간 다르며 "엄격 모드"없이 창 속성으로 해결 된 어휘 참조는 "엄격 모드"에서 "선언되지 않은 변수"오류를 발생시킵니다. 나는 이것이 어디에 지정되어 있는지 이해하지 못했지만 브라우저의 작동 방식.


8
당신이 말한 것은 일반적인 오해이지만 실제로는 틀립니다. Javascript에는 "전역 변수"가 없습니다. 명시 적 범위없이 정의 된 변수 (예 : var함수 외부 사용 )는 웹 브라우저에서 "글로벌 객체"의 속성입니다 window. 따라서- var a = 1; delete window.a; console.log(a);변수를 성공적으로 삭제하고 마지막 줄에서 참조 오류가 발생합니다.
거스

7
@Guss, 코드 var a = 1; delete window.a; console.log(a);는 1을 표시합니다.
Dayong

5
Chrome v36을 사용하고 있습니다. 다른 브라우저에서 테스트했습니다. 일관성있는 크로스 브라우저가 아닌 것 같습니다. Chrome 및 Opera에 1이 표시되었지만 컴퓨터의 Firefox, Safari 및 IE 11에 오류가 발생했습니다.
Dayong

3
알았어 내 실수 야 참조 ecma-international.org/ecma-262/5.1/#sec-10.5 하지만 어쩌면 (개발자 콘솔에서 내 테스트를 실행하는 경우, 일반적으로 "평가 상황"으로 간주된다 (서브 포인트 2 8.c.ii를) Chrome에없는 경우) 오류가 발생합니다. 실제 문서의 전역 컨텍스트에서 동일한 코드 1가 모든 브라우저에서 올바르게 출력 됩니다. 실제 문서에서 실행하면 코드 예제가 정확합니다. 답변을 올바른 것으로 선택했지만 설명 window.a = 1; delete window.a;및 메커니즘 을 포함하도록 답변을 편집 할 수 있으면 감사하겠습니다 . 당신이 신경 쓰지 않으면 나는 그렇게 할 수 있습니다.
거스

2
@KlaiderKlai 네. 함수 범위 변수는 함수가 실행될 때마다 생성 및 소멸됩니다. 아마도 폐쇄는 예외입니다.
Dayong

278

@ 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
}());

그러나 전역 변수는 실제로 창 개체의 멤버이므로 작동합니다.

프로토 타입 체인이 관련된 경우 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올바른 환경에서 할 수 는 있지만 선언 된 변수를 삭제하는 데 여전히 사용하지 않습니다 .


14
그 흥미로운 기사에 대한 링크에 대해 @jedierikb에게 감사드립니다. 보다 구체적으로이 부분의 < perfectionkills.com/understanding-delete/#misconceptions >는 저자가 "삭제가 no-op로되어 있어야한다"라는 노아의 진술이 왜 정확하지 않은지 설명과 함께 부정확하다고 주장하는 기사의 내용입니다. . (메신저를 쏘지 마세요!)
Rob Wells

2
수정 된 답변의 마지막 문장과 관련하여 선언 된 변수를 삭제할 수있는 유일한 상황 var은 변수가로 선언 된 경우입니다 eval.
Stephen Booher

1
에서 이 경우 , 삭제 문은 전혀 아무것도 나타나지 않습니다. 무슨 일이야?
앤더슨 그린

@AndersonGreen-데칼 된 전역 변수는 DontDelete 플래그 로 작성 되므로 삭제할 수 없습니다. 이 코드는 예상대로 작동합니다.
RobG

35

없이 변수를 암시 적으로 선언하는 var경우 올바른 방법을 사용하는 것 delete foo입니다.

그러나 삭제 한 후에 추가와 같은 작업에서 이것을 사용하려고 ReferenceError하면 선언되지 않은 정의되지 않은 식별자에 문자열을 추가 할 수 없으므로 a 가 발생합니다. 예:

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== falsefalse == 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당신이 충분히 관심이 있다면 읽어야 할 언어와 마찬가지로 이상한 예외가 있습니다.


모든 세부 정보가 포함 된 완전한 답변을 주셔서 감사합니다. 나는 이것을 위해 그것을 표시했지만, 간단한 질문은 간결함이 완성보다 더 중요하다고 믿기 때문에 Noah의 대답을 받아 들였습니다. 다시 한번,이 답변에 대해 해주신 많은 노력에 감사드립니다.
Guss

30
some_var = null;

//or remove it..
delete some_var;

11
이 코드의 범위가 함수 인 경우 작동하지 않습니다. 올바른 해결책은 @noah의 답변을 참조하십시오.
Roatin Marth

1
답변에 감사드립니다. 그러나 나는 노아의 대답을 받아 들였습니다 delete.
Guss

3
걱정하지 마라 ... 나는 "빠른 n 더티"간단한 대답을했다 – @noah은 "다른"경우에 대한 모든 세부 사항을 추가했다. ;-)
scunliffe

7
이것은 정확하지 않습니다. delete속성에 대해서만 작동합니다. null변수를 설정하면 여전히 존재합니다.
Derek 朕 會 功夫

1
이 답변은 "if (some_var) {..}"로 확인하는 대부분의 경우에 충분합니다
BearCode

16

TLDR는 (없이 간단한 변수를 정의 var, let, const)와 함께 삭제 될 수 있습니다 delete. , - 를 사용 var하면 -와 함께 또는 함께 삭제할 수 없습니다 .letconstdeleteReflect.deleteProperty

크롬 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은 동일한 동작을 보여줍니다.


귀하의 답변은 기술적으로 정확하므로 요점을 알 수 있지만 작성한 모든 답변은 ECMAScript 사양에 대한 훨씬 자세한 내용과 참조로 선택된 답변에 포함됩니다. 나중에 게시하기 전에 기존 답변을 검토하는 것이 좋습니다.
Guss

5
동의했다. 그러나 var사례 만 언급했습니다 . 나에 관해서는 테스트하고 공유 let하고 const사례도 흥미로 웠습니다 . 그러나 참고해 주셔서 감사합니다. 다음에 더 구체적으로 노력할 것입니다.
Serj.

4

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');

경우에 따라 속성을 구성 할 수없는 경우 속성을 삭제할 수 없으며이 함수는 delete 연산자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

4

변수는 단순한 속성과 달리 속성 [[Configurable]] 을 가지므로 delete 연산자 를 통해 변수를 제거 할 수 없습니다 . 그러나이 규칙에 영향을 미치지 않는 하나의 실행 컨텍스트가 있습니다. 그것은 인 평가의 컨텍스트 :이 [구성] 속성이 변수에 대해 설정되지 않는다.



3

모든 사람이 작성한 것 외에도 delete부울 을 반환 한다는 점에 유의하십시오 . 삭제 성공 여부를 알려줍니다.

Chrome에서 테스트 한 결과를 제외하고 모든 let것이 삭제되었습니다. delete반환 되면 true실제로 제거했습니다.

implicit_global = 1;
window.explicit_global = 1;
function_set = function() {};
function function_dec() { };
var declared_variable = 1;
let let_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
delete let_variable; // false, tested on Chrome 78

항상 정확하지는 않습니다. 특히 Chrome에서. Firefox는 모든 것을 올바르게 반환합니다. 다른 브라우저에서는 테스트하지 않았습니다. 에 관해서는 let바르하고 const이 변수가 삭제하지만, 그렇지 않은 수단해야한다는 것을 사실 반환 바르. Chrome과 FF에서 모두 확인할 수 있습니다. Chrome이 아닌 동안 FF가 올바른 값을 반환하는 것 같습니다. 따라서 실제로 신뢰할 수 있는지 확신하지 마십시오. let letVar = "1"; undefined delete letVar; true letVar "1" typeof letVar; "string" const constVar="1"; undefined delete constVar; true constVar; "1" typeof constVar; "string"
Serj

1
아래에 언급 된 jedierikb으로 kangax perfectionkills.com/understanding-delete의 기사 는 주로 delete운영자의 작동 방식 과 이유를 설명 합니다. 그러나 왜 문자 그대로 상황을 함수로 묶는 지 설명하지 않습니다. 안타깝게도 그러나 변수와 관련하여 상황이 훨씬 명확 해지기 시작합니다.
Serj.에 의해

2

변수를 처음 사용할 때 변수를 선언 한 경우 (var x;로) 삭제할 수 없습니다. 그러나 변수 x가 선언없이 스크립트에 처음 나타난 경우 delete 연산자 (delete x;)를 사용하면 배열의 요소를 삭제하거나 객체의 속성을 삭제하는 것과 매우 유사한 변수가 삭제됩니다. .


1

조금 혼란 스러워요. 변수 값이 다른 스크립트로 전달되지 않는 것이라면 범위에서 변수를 삭제할 필요가 없습니다. 변수를 무효화 한 다음 null인지 아닌지 명시 적으로 확인하십시오. 범위에서 변수를 삭제하는 데 어려움이있는 이유는 무엇입니까? 이 서버는 무효화 할 수없는 목적이 무엇입니까?

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

요구 사항은 내 통제하에 있지 않은 주문 스크립트가 변수가 존재한다는 것을 알 수 없다는 것입니다. 특히 OP의 경우 대상 스크립트에는 null트리거하지 않으려 는 값에 대한 동작 이 있습니다.
거스

이 질문을 작성하는 동안 "백엔드"가 남용되지 않았습니다. 이것들은 웹 사이트 에서이 스크립트 이외의 것을 제어 할 수없는 몇 개의 스크립트입니다.
거스

두 스크립트가 같은 문서에 있거나 다른 하나가로드하도록 다른 문서에 있습니까? 주문 스크립트 및 대상 스크립트를 언급했습니다. 변수가 get / post 변수를 통해 다른 스크립트로 전달되는 문제라면 자바 스크립트가 손을 잡기 전에 백엔드에서 변수를 삭제합니다. PHP에서 이것의 예는 다음과 같습니다. <?php if(isset($_POST['somevariable']) unset($_POST['somevariable']); if(isset($_GET['somevariable']) unset($_GET['somevariable']); ?>
designdrumm

내가 참조. 글쎄, null에 대한 점검과 균형이 있다면 그것을 값으로 설정하면 대상 스크립트는 아무것도 논리적으로 보이지 않는 것보다 스코프에서 변수를 삭제하는 것처럼 보이지만 대답을 찾기 위해 말을 놓을 것입니다. 답변 주셔서 감사합니다.
designdrumm

간단한 질문입니다. 제어 할 수 없지만 여전히이 변수가 필요한 스크립트가 있을까요? 그렇다면 범위에서 변수를 삭제하는 것은 좋지 않습니다.
designdrumm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.