자바스크립트 delete 연산자에 대한 고찰
Scripter/JAVASCRIPT / 2009. 11. 18. 00:21
AJAX에서 XMLHttpRequest 객체 삭제
ajax 강의중 메모리에 있는 객체를 삭제시키는 방법에 대해서 질문을 하신 분이 있었는데 사실 명시적으로 null 로 처리하면 되나 좀더 깔끔한 방법을 소개하고자 한다.
function deletexhr(xhr) { function doNothing() { } xhr.onreadystatechange = doNothing; //onreadystatechagne를 더미함수로 대체 xhr.abort(); //xhr 요청 중단 delete xhr; //xhr 객체 밑의 모든 프로퍼티 삭제 }
자바스크립트에서 delete 연산자
자바스크립트의 delete연산자는 단항연산자로써 피연산자로 지정된 객체 프로퍼티, 배열원소 또는 변수의 삭제를 시도한다.
(C++ 프로그래머라면 자바스크립트의 delete연산자는 C++의 delete연산자와 전혀 닮지 않았다는 것을 발견할 것이다. 자바스크립트의 메모리 해제는 GC에 의해 자동으로 관리되기 때문에-순환참조 제외- 메모리를 직접 해제하는일에 신경 쓸 필요가 전혀없다.)
피연산자가 성공적으로 삭제되었을 경우 true를 반환하고, 삭제될 수 없는 경우 false를 반환한다. 모든 변수나 프로퍼티를 삭제할 수는 없다. 즉 객체자체는 삭제할 수 없으나 객체의 프로퍼티는 삭제할 수 있다는 것이다. 몇몇 핵심 프로퍼티나 클라이언트측 프로퍼티는 삭제하려 해도 소용으며 사용자가 var문으로 정의한 변수들도 삭제할 수 없다. 존재하지 않은 프로퍼티에 대해 delete을 호출할 경우 true가 반환되며 심지어 ECMAScript표준에 따르면 피연산자가 프로퍼티, 배열 원소 또는 변수가 아닐 경우에도 true를 반환한다고 명시되어 있다.
var o = { //변수 정의 및 객체 초기화 x:1, y:2 } delete o.x; //객체 프로퍼티중 하나를 삭제한다. true 반환 typeof o.x; //존재하지 않은 프로퍼티. "undefined" 반환 delete o.x; //존재하지 않는 프로퍼티를 삭제하려한다. true반환 delete o; //선언된 변수는 삭제할 수 없다. false 반환 delete 1; //정수도 삭제할 수 없다. true 반환 x = 1; //var 키워드를 사용하지 않고 암묵적으로 변수를 선언 delete x; //이와 같은 변수는 삭제할수 있다. true반환 x; //런타임 에러, x는 삭제되었으므로 정의되지 않았다.
삭제된 프로퍼티나 변수, 배열원소는 단순히 undefined값으로 설정된 것이 아니라는 것을 주의하라. 어떤 프로퍼티가 삭제되면 그 프로퍼티는 더이상 존재하지 않는다.
한가지 중요한 점은, delete이 영향을 미치는 것은 오직 프로퍼티 뿐이며 해당 프로퍼티가 참조했던 객체는 무관하다는 것이다.
var my = new Object(); //'my'라는 이름의 객체를 생성 my.hire = new Date(); //my.hire는 Date객체 참조 my.fire = my.hire; //my.fire도 동일한 객체 참조 delete my.hire; //hire속성 삭제 true반환 document.write(my.fire); //하지만 my.fire는 여전히 Date객체를 참조
javascript에서의 delete는 개체(object), 개체의 속성(property), 배열의 특정 인덱스에 있는 원소(element)를 지우는 연산자이며. 문법은 다음과 같다
delete objectNamedelete objectName.property delete objectName[index]delete property // with 문장 안에서만 유효
objectName은 개체 이름이고, property는 개체에 존재하는 속성이고, index는 배열의 원소 위치를 나타내는 정수. 네 번째 형식은 개체의 속성을 지우는 코드인데, with 문장 안에서만 사용할 수 있다.
암시적으로 선언된 변수를 지울 때는 delete 연산자를 사용할 수 있지만 단 var 문장을 이용해서 선언된 변수는 지울 수 없다.
delete 연산자 실행이 성공하면, 속성이나 원소가 undefined로 설정되며. delete 연산자는 실행이 가능하면 true를 반환하고, 불가능하면 false를 반환하게 된다.
var x=42; var y= 43; var myobj=new Number(); myobj.h=4; // h라는 속성을 만듭니다 delete x; // returns true (암시적으로 선언된 변수는 지울 수 있습니다) delete y; // returns false (var로 선언한 변수는 지울 수 없습니다) delete Math.PI; // returns false (미리 정의된 속성은 지울 수 없습니다) delete myobj.h; // returns true (사용자 정의 속성은 지울 수 있습니다) delete myobj; // returns true (암시적으로 선언되었으므로 지울 수 있습니다)
먼저 아래 예제에서 trees[3]을 delete로 제거한 예제이다.
trees=new Array("redwood","bay","cedar","oak","maple"); delete trees[3]; if (3 in trees) { // 이 블록은 실행되지 않는다. alert(trees[3]); }
즉 trees라는 배열에는 trees[3] 이라는 배열원소 자체가 삭제(undefined)되어 실행되지 않지만 단지 배열 원소가 존재하긴 하지만 정의되지 않은 값을 가지도록 하고 싶다면 delete 연산자 대신 undefined 키워드를 사용하면 된다.
다음은 trees[3]에 undefined 값을 할당하는 경우이다
trees=new Array("redwood","bay","cedar","oak","maple"); trees[3]=undefinedif (3 in trees) { // 이 블록은 실행된다. }undefined 키워드로 배열의 값은 정의되지 않았지만 배열원소는 유지되므로 블록은 실행된다
- PHPSCHOOL에서 -
delete는 해당 변수를 삭제하는 용도로 주로 쓰입니다. C언어에서는 클래스를 삭제하는 등등 뭐 여러가지로 잘도 쓰이죠. 하지만 JS에서는 그닥 delete문은 쓰잘데기 없습니다. 기본적인 사용예제입니다.
var a=document.getElementsByTagName('div'); for(i=0;i
a를 통해 div 태그를 모조리 뽑아온 다음 모조리 배경색을 초록으로 바꾸고 그변수를 버립니다. 물론 그 이후 a를 출력시키면 undefined로 나오죠. 뭐.. 객체 자체를 삭제할 수는 있지만 객체 안의 멤버를 삭제할 수는 없습니다.
delete a.member;
이래봐야 결과값은 각설이처럼 죽지도 않고 또출력되네~ 입니다. 하지만 a의 동적 멤버, 즉, 프로토타입은 delete문으로 지울 수 있습니다.
delete Integer.prototype.toUnsigned;
물론 객체 자체를 삭제해야 하기 때문에 괄호를 붙이면 안되겠죠. 그렇다고 객체 자체가 삭제되지는 않으니 안심하세요. 어쨌든 이렇게 되면 잠시동안 프로토타입을 선언한 후 쓰다가 지울 수 있는 괴기한 스크립트를 만들 수 있겠습니다.
Object.prototype.extend=function(obj){ for(var x in obj) this[x]=obj[x]; return this; } var ob={ a:'가', b:'나', c:function(){ return '다'; }, d:4 }; ob=ob.extend({e:5,f:'라마바',g:(function(ret){return ret;})('사아자차카타파하')}); delete Object.prototype.extend;prototype 멤버를 delete로 삭제할 수 있다는 걸 알려주는것 뿐입니다.
자바스크립트에서의 가비지컬렉션
300.slimes님 블로그글중 일부발췌
Vervain과 Verbena는 서로를 참조하고 있다. 이러한 경우를 순환참조라고 한다. 객체에 대한 참조를 따라가 보면 완전한 연결고리를 형성하게 된다.
먼저 순환 참조에 대한 일반적인 이해에는 Garbage Collector에 대한 간단한 작동 방식을 이해해야 된다.다음 코드를 보자.
var Vervain = new Herb(); var Verbena = Vervain;
Vervena 가 객체 Vervain을 참조하게 되면 scope 내에 Vervain에 대한 참조카운트가 1이 증가한다. 그리고 실행이 끝나고, scope 를 벗어날 때 해당 scope 내에 Verbena는 파괴되게 된다. 그렇게 되면 Vervain 객체에 대한 참조카운트는 다시 1이 감소한다. 그렇게 되면 GC에서는 Vervain의 참조카운트가 0이 되었으므로 더 이상 사용하지 않는 객체로 판단하고 메모리를 해제하게 된다.하지만 다음과 같은 경우는 어떨까?
var Vervain = new Herb(); var Verbena = new Herb(); Vervain.see = Verbena; Verbena.see = Vervain;
하지만 위와 같은 경우는 어떻게 메모리를 해제해야 될까?
Vervain과 Verbena의 참조카운트는 모두 1이다. Vervain 를 해제하기 위해서는 Vervain에 대한 참조카운트가 0이 되어야 하는데, 이는 Verbena.see 가 Vervain을 참조하고 있다.
역으로 Verbena에 대한 참조카운트도 0이 되어야 하나 Vervain.see 는 Verbena를 참조하고 있다.
결국 이러한 순환참조는 메모리 누수현상을 가져오게 된다. (IE 7에선 이러한 문제가 해결되었다.) 이러한 메모리 누수현상을 방지하기 위해서는 위와 같은 순환 참조를 형성하지 않거나, Vervain.see = null 혹은 Verbena.see = null 을 할당함으로써 참조카운트를 0으로 만들어 GC에서 메모리를 해제하게끔 만들어야 한다.
참조사이트 :
extjs에서 delete 연산자 사용확인
extjs-base.js파일을 까보았다. 객체를 소멸시킬때 사용하는 destroy함수에도 쓰이고 있었다.
//IE일 경우 모든 이벤트 및 프로퍼티 삭제 if(Ext.isIE) { function fnCleanUp() { var p = Function.prototype; delete p.createSequence; delete p.defer; delete p.createDelegate; delete p.createCallback; delete p.createInterceptor; window.detachEvent("onunload", fnCleanUp); } window.attachEvent("onunload", fnCleanUp); }//객체 destory 처리 destroy : function(){ Ext.each(arguments, function(arg){ if(arg){ if(Ext.isArray(arg)){ this.destroy.apply(this, arg); }else if(Ext.isFunction(arg.destroy)){ arg.destroy(); }else if(arg.dom){ arg.remove(); } } }, this); }, destroyMembers : function(o, arg1, arg2, etc){ for(var i = 1, a = arguments, len = a.length; i < len; i++) { Ext.destroy(o[a[i]]); delete o[a[i]]; } }, remove : function(o){ var index = this.indexOf(o); if(index != -1){ this.splice(index, 1); } return this; }
'Scripter > JAVASCRIPT' 카테고리의 다른 글
offsetParent의 모든것! (0) | 2010.02.04 |
---|---|
Javascript로된 Wiki Parser : Creole 1.0 (0) | 2009.01.12 |
자바스크립트 가이드 (0) | 2008.12.03 |
JsonML 활용하기 (0) | 2008.11.12 |
CSS & JAVASCRIPT 최적화 도구 (0) | 2008.10.26 |