자바 스크립트 연관 배열에서 객체를 어떻게 제거합니까?


619

이 코드가 있다고 가정하십시오.

var myArray = new Object();
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;

이제 "lastname"을 제거하고 싶습니까? ....
myArray["lastname"].remove()?

(요소의 수가 중요하고 물건을 깨끗하게 유지하기 위해 요소가 없어야합니다.)


27
팁 : 배열과 맵을 혼동하지 마십시오. php와 같은 일부 언어에는 둘 다 단일 객체가 있습니다. 여기에서 올바른 유형 (new Object ())을 myArray로 명명했지만 언어 표준의 문제 일뿐입니다.
Juan Mendes

JavaScript는 유형이 없으며 모든 것이 객체라는 것을 잊지 마십시오. 아래의 사울의 대답을보십시오.
stevek

4
@StephanKristyn-정확하게 말하면 JS에는 유형이 있지만 역동적 이고 약한 방식이 있습니다. 예를 들어 변수는 실제로 유형이 없지만 값은 다릅니다. 그것은 역동적 인 부분입니다. 약함 은 서로 다른 값 유형 간의 작업 이 엄격하게 정의되지 않았으며 비하인드 스토리 변환에 의존 함을 나타냅니다 . 예를 들어 "Test" + {};완벽하게 유효한 JS 문입니다.
사울

답변:


1135

JavaScript의 객체는 키 (속성)를 값에 매핑하는 연관 배열로 생각할 수 있습니다.

JavaScript의 객체에서 속성을 제거하려면 delete연산자 를 사용하십시오 .

const o = { lastName: 'foo' }
o.hasOwnProperty('lastName') // true
delete o['lastName']
o.hasOwnProperty('lastName') // false

때 참고 delete의 인덱스 속성에 적용 Array, 당신이 만듭니다 인구 밀도 배열 (예. 누락 된 인덱스 배열).

의 인스턴스로 작업 할 때 Array당신은 인구 밀도가 배열을 만들지 않으려면, - 당신은 일반적으로하지 않습니다 - 당신은 사용해야 Array#splice하거나 Array#pop.

deleteJavaScript 의 연산자는 메모리를 직접 비우지 않습니다. 그 목적은 객체에서 속성을 제거하는 것입니다. 속성의 존재가 삭제 한 경우 물론, 객체에 유일하게 남아있는 참조를 보유 o하고 o이후 쓰레기는 일반적인 방법으로 수집됩니다.

delete연산자를 사용하면 JavaScript 엔진의 코드 최적화 기능에 영향을 줄 수 있습니다 .


18
예를 들어, Array 객체 인스턴스에서 기존 요소를 제거하는 데 문제가 발생할 수 있습니다 delete myArray[0]. 참조 stackoverflow.com/a/9973592/426379삭제 배열 요소를
사울

4
어떤 문제가 발생합니까?
Gottox

26
@Gottox- lengthArray 객체 의 속성은 변경되지 않습니다.
Saul

12
@Saul이 :이 경우 문제가 될 myArray정말 배열로 사용 -하지만 그렇지 않은 ( myArray, 그 목적은 불행한 이름입니다). 따라서이 경우 delete에는 정상입니다. 그것이 new Array()연관 배열 로 작성되어 사용 되더라도 여전히 괜찮습니다. 그래도 실제 배열을 사용하는 경우 경고해야 할 사항이 있습니다.
johndodo

2
@johndodo-맞습니다. 나는 내 첫 코멘트를 시작하는 이유입니다 문제를 일으킬이를 하면 온 사용 배열 객체 인스턴스 . 그럼에도 불구하고 모든 경우에 올바르게 수행되는 접근법을 선호합니다. 아래 답변을 참조하십시오.
Saul

79

JavaScript의 모든 객체는 해시 테이블 / 연관 배열로 구현됩니다. 따라서 다음은 동일합니다.

alert(myObj["SomeProperty"]);
alert(myObj.SomeProperty);

그리고 이미 표시된 바와 같이 delete키워드 를 통해 객체에서 속성을 "제거"하면 두 가지 방법으로 사용할 수 있습니다.

delete myObj["SomeProperty"];
delete myObj.SomeProperty;

추가 정보가 도움이 되길 바랍니다 ...


10
속성이 단순한 용어가 아닌 경우 점 표기법이 작동하지 않습니다. 즉, myObj['some;property']작동하지만 myObj.some;property(명백한 이유로) 그렇지 않습니다. 또한 대괄호 표기법에서 변수를 사용할 수 있음이 분명하지 않을 수 있습니다.var x = 'SomeProperty'; alert(myObj[x])
Kip

2
"JavaScript의 모든 객체는 해시 테이블 / 연관 배열로 구현됩니다."-false. V8은 객체를 숨겨진 클래스 + 밀도가 높은 필드로 저장하는 것을 선호합니다. 필드 제거와 같은 이상한 일을하는 경우에만 장면 뒤의 해시 맵을 포기하고 사용합니다.
John Dvorak

4
@ JanDvorak-이 답변이 처음 작성된 시점을 알고 있습니다. 이 설명은 대부분의 목적을 위해 충분하고 여전히 충분합니다. 나는 말도 안되게 pedantic 이해합니다. :)
Jason Bunting 2016

41

더 없다 - 이전 답변 없음 자바 스크립트로 시작하는 연관 배열을하지 않는다는 사실 해결하지 array, 유형 등 참조 typeof.

Javascript에는 동적 속성이있는 객체 인스턴스가 있습니다. 속성이 Array 객체 인스턴스의 요소와 혼동되면 Bad Things ™가 발생합니다.

문제

var elements = new Array()

elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]

console.log("number of elements: ", elements.length)   // returns 2
delete elements[1]
console.log("number of elements: ", elements.length)   // returns 2 (?!)

for (var i = 0; i < elements.length; i++)
{
   // uh-oh... throws a TypeError when i == 1
   elements[i].onmouseover = function () { window.alert("Over It.")}
   console.log("success at index: ", i)
}

해결책

폭파되지 않는 범용 제거 기능을 사용하려면 다음을 사용하십시오.

Object.prototype.removeItem = function (key) {
   if (!this.hasOwnProperty(key))
      return
   if (isNaN(parseInt(key)) || !(this instanceof Array))
      delete this[key]
   else
      this.splice(key, 1)
};

//
// Code sample.
//
var elements = new Array()

elements.push(document.getElementsByTagName("head")[0])
elements.push(document.getElementsByTagName("title")[0])
elements["prop"] = document.getElementsByTagName("body")[0]

console.log(elements.length)                        // returns 2
elements.removeItem("prop")
elements.removeItem(0)
console.log(elements.hasOwnProperty("prop"))        // returns false as it should
console.log(elements.length)                        // returns 1 as it should

8
이 솔루션에는 두 가지 문제가 있습니다. 배열과 객체가 JS에서 완전히 다른 짐승이라는 사실을 숨기고 (알지만 OP는 그렇지 않습니다) 프로토 타입을 사용합니다. 그가 배열과 객체에 대해 배우고 그에 따라 변수의 이름을 지정하면 OP가 더 나을 것입니다. 두 가지의 차이점을 숨기려고하면 더 많은 어려움을 겪을 것입니다. 물론 IMHO.
johndodo

1
@johndodo - 모든 ArrayJS에서의 객체를 시도하다 typeof new Array();또는 typeof []확인 할 수 있습니다. Array단순히 "다른 짐승"이 아닌 특정 종류의 물체입니다. JS에서 객체는 생성자 이름과 프로토 타입 체인으로 구별됩니다 . 프로토 타입 기반 프로그래밍을 참조하십시오 .
Saul

9
요점이 없습니다. 배열도 객체라는 것을 알고 있지만 그렇게 사용하는 것이 현명하다는 것을 의미하지는 않습니다. 프로그래머는 무언가를 배열 (푸시, 팝, [], ...) 또는 객체 / "연관 배열"로 사용할 것인지 결정해야합니다. 믹스 앤 매치는 솔루션이 숨기려고하는 문제로 인해 좋은 레시피가 아닙니다. 사용할 디자인 패턴 (배열 또는 객체)을 미리 결정하면 아무런 문제가 없습니다.
johndodo

7
@johndodo-무슨 문제에 대해 구체적으로 이야기하고 있습니까? 위의 코드의 목적은 간단한 다형성 함수를 제공함으로써 결함 delete연산자와 관련된 결함 Array을 해결하는 것입니다.
Saul

1
delete결함이 없습니다. delete속성을 제거하도록 설계되었습니다. 그게 다야. delete 연산자를 배열의 인덱스에 적용하면 해당 인덱스가 제거됩니다. 더 필요한 게 뭐야? 언어의 기능인 희소 배열이 남아 있습니다. 희소 배열을 원하지 않으면 색인을 삭제하지 마십시오 : use splice또는 pop.
벤 애스턴

35

객체 만 삭제하지만 배열 길이는 동일하게 유지합니다.

제거하려면 다음과 같은 작업을 수행해야합니다.

array.splice(index, 1);

11
사실, 그러나이 경우 배열은 사용되지 않고 평범한 오래된 객체이므로 길이 또는 스플 라이스 방법이 없습니다.
MooGoo

2
@Andreaa Panagiotidis 우리가 배열에 대해 이야기하지 않을 때를 제외하고는,이 경우 100 % 잘못된 것입니다.
Drenai

17

허용되는 답변은 정확하지만 왜 작동하는지에 대한 설명이 없습니다.

우선, 당신의 코드는이 사실 반영해야 하지 배열을 :

var myObject = new Object();
myObject["firstname"] = "Bob";
myObject["lastname"] = "Smith";
myObject["age"] = 25;

모든 객체 ( Array s )를 이런 식으로 사용할 수 있습니다. 그러나 객체에서 작동 할 표준 JS 배열 함수 (pop, push, ...)를 기대하지 마십시오!

허용 된 답변에서 말했듯이 delete객체에서 항목을 제거하는 데 사용할 수 있습니다 .

delete myObject["lastname"]

객체 (연관 배열 / 사전)를 사용하거나 배열 (지도)을 사용하려는 경로를 결정해야합니다. 두 가지를 섞지 마십시오.


6
아주 좋은 대답입니다. 나는 이것을 읽는 사람에게 자바 스크립트의 배열을 '지도'로 추상화하지 말고 '목록'으로 추상화해야한다고 조언합니다. 배열을 사용할 때 요소의 인덱스를 제어하려고 시도해서는 안되기 때문입니다. 시도해 보면 ... 음, : D
rodolfo42

6

메소드 splice를 사용 하여 객체 배열에서 항목을 완전히 제거하십시오.

Object.prototype.removeItem = function (key, value) {
    if (value == undefined)
        return;

    for (var i in this) {
        if (this[i][key] == value) {
            this.splice(i, 1);
        }
    }
};

var collection = [
    { id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
    { id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
    { id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];

collection.removeItem("id", "87353080-8f49-46b9-9281-162a41ddb8df");

1
이것은보다 일반적인 솔루션이며 js 파일에 추가 할 수 있으며 메소드는 하나의 배열이 아닌 모든 배열에서 사용할 수 있습니다.
Hussain

6

다른 답변에서 언급했듯이 사용중인 것은 Javascript 배열이 아니라 Javascript 객체입니다.이 객체는 모든 키가 문자열로 변환된다는 점을 제외하고 다른 언어의 연관 배열과 거의 유사합니다. 새 지도 는 키를 원래 유형으로 저장합니다.

객체가 아닌 배열이있는 경우 배열의 .filter 함수를 사용하여 제거하려는 항목없이 새 배열을 반환 할 수 있습니다 .

var myArray = ['Bob', 'Smith', 25];
myArray = myArray.filter(function(item) {
    return item !== 'Smith';
});

이전 브라우저와 jQuery가있는 경우 jQuery에는 다음 과 유사한 $.grep방법 이 있습니다.

myArray = $.grep(myArray, function(item) {
    return item !== 'Smith';
});

완벽한 설명. 원하는 결과를 얻기 위해 필터를 사용했습니다. 배열에서 객체를 제거하기 위해 반환 항목이 어떻게 작동하는지 설명 하시겠습니까? 포함 된 문자열을 포함하지 않는 한 배열을 반환한다고 가정합니다.
에드워드


5

Object를 사용하고 있는데 연관 배열이 없습니다. 연관 배열을 사용하면 항목을 추가하고 제거하는 방법은 다음과 같습니다.

    Array.prototype.contains = function(obj) 
    {
        var i = this.length;
        while (i--) 
        {
            if (this[i] === obj) 
            {
                return true;
            }
        }
        return false;
    }


    Array.prototype.add = function(key, value) 
    {
        if(this.contains(key))
            this[key] = value;
        else
        {
            this.push(key);
            this[key] = value;
        }
    }


    Array.prototype.remove = function(key) 
    {
        for(var i = 0; i < this.length; ++i)
        {
            if(this[i] == key)
            {
                this.splice(i, 1);
                return;
            }
        }
    }



    // Read a page's GET URL variables and return them as an associative array.
    function getUrlVars()
    {
        var vars = [], hash;
        var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');

        for(var i = 0; i < hashes.length; i++)
        {
            hash = hashes[i].split('=');
            vars.push(hash[0]);
            vars[hash[0]] = hash[1];
        }

        return vars;
    }



    function ForwardAndHideVariables() {
        var dictParameters = getUrlVars();

        dictParameters.add("mno", "pqr");
        dictParameters.add("mno", "stfu");

        dictParameters.remove("mno");



        for(var i = 0; i < dictParameters.length; i++)
        {
            var key = dictParameters[i];
            var value = dictParameters[key];
            alert(key + "=" + value);
        }
        // And now forward with HTTP-POST
        aa_post_to_url("Default.aspx", dictParameters);
    }


    function aa_post_to_url(path, params, method) {
        method = method || "post";

        var form = document.createElement("form");

        //move the submit function to another variable
        //so that it doesn't get written over if a parameter name is 'submit'
        form._submit_function_ = form.submit;

        form.setAttribute("method", method);
        form.setAttribute("action", path);

        for(var i = 0; i < params.length; i++)
        {
            var key = params[i];

            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
        }

        document.body.appendChild(form);
        form._submit_function_(); //call the renamed function
    }

4

'undefined'에 명시 적으로 할당하여 맵에서 항목을 제거 할 수 있습니다. 귀하의 경우와 같이 :

myArray [ "lastname"] = 정의되지 않음;


키가 사전에 있는지 확실하지 않지만 경우에 따라 키를 제거하려는 경우에 유용 할 수 있습니다. 내가 Amytis가 틀렸다면 나를 바로 잡으십시오.
Hassan Baig 2016 년

3

어떤 이유로 든 삭제 키가 작동하지 않는 경우 (나를 위해 작동하지 않은 것처럼)

스플 라이스 아웃 한 다음 정의되지 않은 값을 필터링 할 수 있습니다.

// to cut out one element via arr.splice(indexToRemove, numberToRemove);
array.splice(key, 1)
array.filter(function(n){return n});

스플 라이스가 제거 된 요소를 반환하므로 연결을 시도하지 마십시오.


3

함수 로서도 사용할 수 있습니다. 프로토 타입으로 사용하면 Angular에서 약간의 오류가 발생합니다. 감사합니다 @HarpyWar. 문제 해결에 도움이되었습니다.

var removeItem = function (object, key, value) {
    if (value == undefined)
        return;

    for (var i in object) {
        if (object[i][key] == value) {
            object.splice(i, 1);
        }
    }
};

var collection = [
    { id: "5f299a5d-7793-47be-a827-bca227dbef95", title: "one" },
    { id: "87353080-8f49-46b9-9281-162a41ddb8df", title: "two" },
    { id: "a1af832c-9028-4690-9793-d623ecc75a95", title: "three" }
];

removeItem(collection, "id", "87353080-8f49-46b9-9281-162a41ddb8df");


1

"delete"키워드 를 사용하면 javascript의 배열에서 배열 요소를 삭제합니다.

예를 들어

다음 진술을 고려하십시오.

var arrayElementToDelete = new Object();

arrayElementToDelete["id"]           = "XERTYB00G1"; 
arrayElementToDelete["first_name"]   = "Employee_one";
arrayElementToDelete["status"]       = "Active"; 

delete arrayElementToDelete["status"];

코드의 마지막 줄은 키가 "상태"인 배열 요소를 배열에서 제거합니다.


0
var myArray = newmyArray = new Object(); 
myArray["firstname"] = "Bob";
myArray["lastname"] = "Smith";
myArray["age"] = 25;

var s = JSON.stringify(myArray);

s.replace(/"lastname[^,}]+,/g,'');
newmyArray = JSON.parse(p);

반복 / 반복없이 우리는 동일한 결과를 얻습니다


0

"배열"의 경우 :

색인을 알고있는 경우 :

array.splice(index, 1);

값을 알고있는 경우 :

function removeItem(array, value) {
    var index = array.indexOf(value);
    if (index > -1) {
        array.splice(index, 1);
    }
    return array;
}

가장 큰 답 delete은 실제 배열에는 적합하지 않지만 객체의 경우에는 잘 작동합니다. 내가 사용 delete하면 루프에서 요소를 제거하지만 요소를 유지하고 empty배열 길이는 변경되지 않습니다. 일부 시나리오에서는 문제가 될 수 있습니다.

예를 들어, 제거 후 myArray에서 myArray.toString ()을 수행 delete하면 빈 항목이 생성됩니다.


0

나를위한 유일한 작업 방법 :

function removeItem (array, value) {
    var i = 0;
    while (i < array.length) {
        if(array[i] === value) {
            array.splice(i, 1);
        } else {
            ++i;
        }
    }
    return array;
}

용법:

var new = removeItem( ["apple","banana", "orange"],  "apple");
// ---> ["banana", "orange"]

대신 필터를 사용하지 않겠습니까? 이것은 필터를위한 완벽한 사용 사례입니다
Code Maniac
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.