도끼 삭제 vs 도끼 = 정의되지 않음


138

이들 중 하나를 수행하는 데 실질적인 차이가 있습니까?

delete a.x;

vs

a.x = undefined;

어디

a = {
    x: 'boo'
};

그것들이 동등하다고 말할 수 있습니까?

(나는 "V8은 delete더 잘 사용하지 않는 것을 좋아한다" 와 같은 것을 고려하지 않고있다 )


2
삭제 연산자는 속성을 완전히 제거합니다. 속성을 undefined로 설정하면 값이 제거됩니다. 속성을 null로 설정하면 값이 null 값으로 변경됩니다. 여기 경우처럼 반환 한 테스트는 다음과 같습니다 jsperf.com/delete-vs-undefined-vs-null/3
j08691는

1
@ j08691 Nit : 값을 제거하지 않습니다. 그것은 undefined여전히 .. 값으로 할당 됩니다.

왜 당신이 이것에 관심이 있는지에 대해 이야기해야하며, 그 대답은 실제 문제를 해결할 수 있습니다.
Juan Mendes

답변:


181

그것들은 동등하지 않습니다. 가장 큰 차이점은

a.x = undefined

a.hasOwnProperty("x"), 여전히 true를 반환하므로 for in루프 에 계속 표시됩니다 .Object.keys()

delete a.x

a.hasOwnProperty("x")거짓을 반환 한다는 의미

그것들이 동일한 방법은 테스트를 통해 속성이 존재하는지 알 수 없다는 것입니다

if (a.x === undefined)

속성이 존재하는지 확인하려는 경우하지 말아야 할 것, 항상 사용해야합니다

// If you want inherited properties
if ('x' in a)

// If you don't want inherited properties
if (a.hasOwnProperty('x'))

프로토 타입 체인 ( zzzzBov에 의해 언급 )에 따라 호출 delete하면 프로토 타입 체인으로 올라갈 수 있지만, 값을 undefined로 설정하면 체인 된 프로토 타입에서 속성을 찾지 않습니다 http://jsfiddle.net/NEEw4/1/

var obj = {x: "fromPrototype"};
var extended = Object.create(obj);
extended.x = "overriding";
console.log(extended.x); // overriding
extended.x  = undefined;
console.log(extended.x); // undefined
delete extended.x;
console.log(extended.x); // fromPrototype

상속 된 속성 삭제 삭제 하려는 속성이 상속되면 delete영향을 미치지 않습니다. 즉, delete상속 된 속성이 아니라 개체 자체에서 속성 만 삭제합니다.

var obj = {x: "fromPrototype"};
var extended = Object.create(obj);
delete extended.x;
console.log(extended.x); // Still fromPrototype

따라서 객체의 값이 정의되지 않았는지 확인해야하는 경우 delete속성이 상속 될 때 작동하지 않으면이 경우로 설정 (재정의)해야합니다 undefined. 확인하는 장소가을 사용하지 않으면 확인 hasOwnProperty하는 모든 곳에서 사용한다고 가정하는 것이 안전하지 않을 수 있습니다hasOwnProperty


1
"x" in atrue전자 false와 후자로 돌아올 것이다 . 출력 Object.keys도 다릅니다.
lonesomeday

정의되지 않은 검사를하지 말아야하는 이유는 무엇입니까? 나에게 충분히 합리적인 것 같습니다.
bevacqua 2019

@Nico 속성이 존재하는지 알려주지 않기 때문입니다. 나는 그것을 사용하지 말라고 말하는 것이 아닙니다. 그러나를 확인하는 경우 숫자가 undefinedif (a.x)
Juan Mendes

33

질문을 바꾸려면 :

인가 delete a.xa.x = undefined동등한?

아니.

전자는 변수에서 키를 제거하고 나중에 키를 값으로 설정합니다 undefined. 이것은 객체의 속성을 반복 할 때 hasOwnProperty와 사용될 때 차이를 만듭니다 .

a = {
    x: true
};
a.x = undefined;
a.hasOwnProperty('x'); //true
delete a.x;
a.hasOwnProperty('x'); //false

또한 이것은 프로토 타입 체인이 관련 될 때 큰 차이를 만듭니다.

function Foo() {
    this.x = 'instance';
}
Foo.prototype = {
    x: 'prototype'
};
a = new Foo();
console.log(a.x); //'instance'

a.x = undefined;
console.log(a.x); //undefined

delete a.x;
console.log(a.x); //'prototype'

2
+1 delete프로토 타입 체인을 올라갈 수있는 좋은 점
Juan Mendes

4

a.xsetter 함수 인 경우 함수 a.x = undefined를 호출하지만 함수는 호출 delete a.x하지 않습니다.


3

예, 차이가 있습니다. delete a.xx 를 사용 하면 더 이상 a의 속성이 아니지만 사용 a.x=undefined하면 속성이지만 값은 정의되지 않습니다.


2

이름이 약간 혼란 스럽다. a.x = undefined속성을로 설정 undefined하지만 속성은 여전히 ​​있습니다.

> var a = {x: 3};
> a.x = undefined;
> a.constructor.keys(a)
["x"]

delete 실제로 삭제합니다.

> var a = {x: 3};
> delete a.x;
> a.constructor.keys(a)
[]

1

이 REPL from node는 차이점을 설명해야합니다.

> a={ x: 'foo' };
{ x: 'foo' }
> for (var i in a) { console.log(i); };
x
undefined
> a.x=undefined;
undefined
> for (var i in a) { console.log(i); };
x
undefined
> delete a.x;
true
> for (var i in a) { console.log(i); };
undefined

1

난 당신의 차이를 볼 수 있습니다 확신 var o1 = {p:undefined};하고 var o2 = {};.

두 경우 모두, o.p될 것입니다 undefined하지만이 때문에 첫 번째 경우에, 그것의 과 두 번째 경우에 때문에 값이없는 .

delete당신이에서 얻을 할 수있는 연산자 o1(또는 할당 된 값이 다른 객체 p속성)에 o2그 방법은 : delete o1.p;.

역동 작은 단순히 undefined속성에 값을 할당함으로써 이루어집니다 ( 이 예제에서는 다른 것일 수도 있습니다) o1.p = undefined;.

따라서 no 는 동일하지 않습니다.


delete o.p; 의지

  • 속성 p이있는 경우 개체 에서 속성 을 제거하십시오.

  • 달리 아무것도 하지마

o.p = undefined; 의지

  • p아직 속성 이 없으면 객체에 속성 을 추가 하고 값을undefined

  • 객체에 이미있는 경우 속성 값을 변경하기 만하면됩니다.


성능 관점에서 delete입니다 나쁜 것이 있기 때문에 객체의 구조를 변경 (당신이 생성자에서 초기화하지 않은 경우 새 속성을 추가하는 등).

값을 설정하면 undefined내용도 해제되지만 구조를 강제로 수정하지는 않습니다.


1

객체는 단순히 트리 표현입니다. 즉, 메모리에서 루트는 해당 객체의 키가 저장된 다양한 메모리 위치를 가리 킵니다. 그 위치는 그 키의 실제 값이 저장되는 다른 위치, 또는 자식 키가 저장되는 위치 또는 어레이 값이 저장되는 위치를 가리킨다.

delete를 사용하여 객체에서 키를 삭제하면 실제로 해당 키와 상위 객체 사이의 링크가 삭제되고 키의 메모리 위치와 해당 값은 다른 정보를 저장하기 위해 해제됩니다.

undefined를 값으로 설정하여 키를 삭제하려고하면 해당 키를 삭제하지 않고 값만 설정하면됩니다. 즉, 키 메모리 위치는 여전히 상위 오브젝트 및 키가 정의되지 않은 경우 값과 연결되어 있습니다.

delete 키워드를 사용하는 대신 undefined를 사용하면 해당 키의 메모리 위치가 해제되지 않으므로 좋지 않습니다.

키가없고 정의되지 않은 것으로 설정하더라도 해당 키는 value로 생성됩니다 undefined.

예 :

var a = {};
a.d = undefined;
console.log(a); // this will print { d: undefined }

상속 된 속성은 해당 자식 개체의 일부가 아니므로 delete 속성을 사용할 수 없습니다.


1
최신 엔진은 키를 삭제하지 않는 것이 좋습니다. 엔진을 수행 할 때 엔진이 새 클래스를 작성하고 "클래스"가 참조되는 곳이면 어디서든 업데이트해야하기 때문입니다.
Juan Mendes

@ JuanMendes, 당신은 어떤 참조를 줄 수 있습니까?
Laxmikant Dange 2016 년

3
delete 키워드 사용이 객체의 v8 최적화에 영향을 줍니까?를 참조하십시오 . TL; DR as a general rule of thumb, using 'delete' makes thing slower.developers.google.com/v8/design To reduce the time required to access JavaScript properties, V8 does not use dynamic lookup to access properties. Instead, V8 dynamically creates hidden classes behind the scenes. In V8, an object changes its hidden class when a new property is added. , 마침내 smashingmagazine.com/2012/11/…
Juan Mendes

1

객체 대신 배열을 사용하면 delete가 정의되지 않은 것보다 적은 힙 메모리를 사용한다는 것을 보여줄 수 있습니다.

예를 들어이 코드는 완료되지 않습니다.

let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
    ary.push(y);
    ary[y] = undefined;
    y += 1;
}
console(ary.length);

이 오류가 발생합니다.

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.

보시 undefined다시피 실제로 힙 메모리를 차지합니다.

그러나 deleteary-item도 (로 설정하는 대신 undefined) 경우 코드는 천천히 끝납니다.

let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
    ary.push(x);
    ary[x] = undefined;
    delete ary[x];
    x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);

이것들은 극단적 인 예이지만, delete어느 누구도 언급하지 않은 것에 대해 지적합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.