JavaScriptオブジェクトからプロパティを削除するにはどうすればよいですか?



Answers

オペレータのdeleteが予期せず遅いです!

benchmark見てください。

残差なしでオブジェクトのプロパティを削除する唯一の真の方法はDeleteですが、 "alternative"の設定object[key] = undefinedに比べて100倍も遅く動作しobject[key] = undefined

この選択肢は、この質問に対する正解ではありません! ただし、注意して使用すると、アルゴリズムの速度を大幅に向上させることができます。 delete inループをdeleteしていて、パフォーマンスに問題がある場合は、詳しい説明を読んでください。

1つはdeleteを使用し、設定値をundefinedますか?

オブジェクトは、キーと値のペアのセットとして見ることができます。 私が「値」と呼ぶものは、その「キー」に接続されたプリミティブまたは他のオブジェクトへの参照です。

コントロールを持たないコードに結果オブジェクトを渡すとき(またはチームや自分自身についてわからないとき)はdelete使用します。

ハッシュマップからキーを削除します

 var obj = {
     field: 1     
 };
 delete obj.field;

パフォーマンスを気にするときはundefinedに設定を使用してください 。 コードに深刻な影響を与える可能性があります。

キーはハッシュマップ内のその位置にとどまり、値はundefined置き換えられます。 理解してfor..inて、 for..inループは引き続きそのキーに対して反復処理を行います。

 var obj = {
     field: 1     
 };
 obj.field = undefined;

この方法を使用すると、 プロパティの存在を判断するすべての方法が期待通りに機能するわけではありません。

しかし、このコード:

object.field === undefined

両方の方法で同等に動作します。

テスト

要約すると、相違点はすべてプロパティの存在を判断する方法とfor..inループについてfor..in

 console.log('* -> "Takes prototype inheritance into consideration, that means it lookups all over prototype chain too."');

 console.log(obj.field === undefined, 'obj.field === undefined', 'You get "undefined" value when querying for "field" in object-hashmap. *');

 console.log(obj["field"] === undefined, 'obj["field"] === undefined', 'Just another way to query (equivalent). *');

 console.log(typeof obj.field === "undefined", 'typeof obj.field === "undefined"', 'Get the value attached to "field" key, and check it\'s type is "undefined". *');

 console.log("field" in obj, '"field" in obj', 'This statement returns true if "field" key exists in the hashmap. False otherwise. *');

 console.log(obj.hasOwnProperty("field"), 'obj.hasOwnProperty("field")', 'This statement returns true if \'field\' key exists in the hashmap. The ONLY way NOT to lookup for property in the prototype chain!');
 //Object.keys().indexOf() is an overkill that runs much slower :)

 var counter = 0,
     key;
 for (key in obj) {
     counter++;
 }
 console.assert(counter === 0, 'counter === 0', '"field" is not iterated using "for .. in" loop. *');

メモリリークに気をつけろ!

obj[prop] = undefineddelete obj[prop]delete obj[prop]よりも高速ですが、 obj[prop] = undefinedが常に適切であるとは限りません。 delete obj[prop]objからdelete obj[prop]してメモリから消去しますが、 obj[prop] = undefinedpropの値をobj[prop] = undefinedに設定するだけです。 したがって、多くのキーが作成および削除されている状況では、 obj[prop] = undefinedすると高価なメモリの調整(ページがフリーズする)やメモリー不足の可能性があります。 次のコードを調べます。

"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
    nodeRecords[i] = [];
    current = theNodeList[i] = document.createElement("div");
    current.textContent = i;
    document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
    var currentTime = Math.round( performance.now()*1000 )
    for (i = 0; i !== numberOfNodes; i++) {
        if (lastTime !== -1) {
            // the previously collected data is no longer in use
            /*************************************************/
            /****/ nodeRecords[i][lastTime] = undefined; /****/
            /*************************************************/
        }
        nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
    }
    lastTime = currentTime;
    requestAnimationFrame( recordUpdates );
});

上のコードでは、単純にnodeRecords[i][lastTime] = undefined; アニメーションフレームごとに大量のメモリリークが発生します。 各フレームでは、65536個のDOM要素すべてが別の65536個のスロットを占有しますが、前の65536スロットはundefinedに設定され、メモリに吊り下げられます。 先に、コンソール上で上記のコードを実行し、あなた自身のために見てみてください。 メモリ不足エラーを強制した後で、 delete演算子を代わりに使用する次のバージョンのコードを除いて、再度実行してdelete

"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
    nodeRecords[i] = [];
    current = theNodeList[i] = document.createElement("div");
    current.textContent = i;
    document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
    var currentTime = Math.round( performance.now()*1000 )
    for (i = 0; i !== numberOfNodes; i++) {
        if (lastTime !== -1) {
            // the previously collected data is no longer in use
            /********************************************/
            /****/ delete nodeRecords[i][lastTime]; /****/
            /********************************************/
        }
        nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
    }
    lastTime = currentTime;
    requestAnimationFrame( recordUpdates );
});

上のコードスニペットに見られるように、 delete演算子にはまれな適切な使用例がいくつかあります。 しかし、この問題についてあまり心配しないでください。 これは、常に新しいキーを追加するような長寿命のオブジェクトでのみ問題になります。 それ以外の場合(実際のプログラミングではほとんどすべての場合)、 obj[prop] = undefinedを使用するのが最も適切です。 このセクションの主な目的は、これをあなたの注意のもとに置くことです。コード内で問題が発生する可能性は稀ですが、問題をより簡単に理解することができ、コードを解読する時間を無駄にする必要はありませんこの問題を理解する。

必ずしもundefined設定する必要はありません

考慮すべき重要なJavascriptの1つの側面は多型です。 多態性は、以下に示すように、異なる変数/スロット・イン・オブ・オブジェクトの異なるタイプを割り当てるときです。

var foo = "str";
foo = 100;          // variable foo is now labeled polymorphic by the browser
var bar = ["Some", "example"];
bar[2] = "text";    // bar is a monomorphic array here because all its entries have the
                    // same type: string primitive
bar[1] = undefined; // bar is now a polymorphic array

しかし、多型配列には2つの大きな修正不可能な問題があります。

  1. 彼らは遅く、記憶が非効率的です。 特定のインデックスにアクセスする場合、配列のグローバルタイプを取得する代わりに、ブラウザはタイプごとにインデックスを取得する必要があり、各インデックスはそのタイプの追加のメタデータを格納します。
  2. 一度多型、常に多形性。 配列が多型になると、Webkitブラウザで多型を元に戻すことはできません。 したがって、多型配列を非多型に復元しても、それはブラウザによって多型配列として格納されます。

多型性を薬物中毒に似せることができる。 一見すると、それは非常に有益であるように思える:素敵なかなりふわふわしたコード。 次に、コーダはそれらのアレイを多型の薬物に導入する。 即座に、多型アレイは効率が悪くなり、薬を飲まれて以来、これまでと同じくらい効率的になることはありません。 そのような状況を現実のものと関連づけるために、コカインを服用している人は、単純なドアハンドルを操作することさえできず、PIの数字を計算することはできません。 同様に、多型薬物のアレイは、単相性アレイほど効率的ではありません。

しかし、ドラッグ旅行の類推は、 delete操作にどのように関連していますか? 答えは上のスニペットの最後のコード行を示しています。 それで、今度はツイストで再検査させましょう。

var bar = ["Some", "example"];
bar[2] = "text";    // bar is not a polymorphic array here because all its entries have the
                    // same type: string primitive
bar[1] = "";        // bar is still a monomorphic array
bar[1] = undefined; // bar is now a polymorphic array

観察する。 bar[1] = ""は多型を強制しませんが、 bar[1] = undefinedは行いません。 したがって、可能であれば、必ず多型を誤って引き起こさないように、オブジェクトに対応する型を常に使用する必要があります。 そのような人の一人は、以下のリストを一般的な参照として使用して、それらを得ることができます。 ただし、以下の考え方を明示的に使用しないでください。 代わりに、あなたのコードにうまくいくものを使用してください。

  • booleanプリミティブに型付けされた配列/変数を使用する場合は、空の値としてfalseまたはundefinedを使用します。 不要なポリモーフィズムを避けるのは良いですが、明示的に禁止するようにすべてのコードを書き直すと、実際にはパフォーマンスが低下する可能性があります。 共通の判断を使用してください!
  • 数値プリミティブに型付けされた配列/変数を使用する場合は、空の値として0を使用します。 内部的には、高速な整数(2147483647〜-2147483648を含む)と遅い浮動小数点の2倍( NaNInfinityを含むもの以外のもの)の2種類があります。 整数が倍精度に降格されると、整数に昇格することはできません。
  • 文字列プリミティブに型付けされた配列/変数を使用する場合は、空の値として""を使用します。
  • シンボルを使用しているとき、なぜシンボルを使用しているのですか? 記号はパフォーマンスのために悪いジュジュです。 Symbolsを使用するようにプログラムされたすべてのプログラムは、Symbolsを使用しないように再プログラムすることができ、Symbolを使用しないでコードを高速化できます。 シンボルは実際には非常に非効率的なメタ砂糖です。
  • 他のものを使用する場合はnull使用してください。

しかし、注意してください! このような既存のコードを壊したり、奇妙なバグを導入したりする可能性があるため、既存のすべてのコードで突然この作業を開始しないでください。 むしろ、このような効率的なプラクティスは最初から実装する必要があります。既存のコードを変換するときは、古いコードをこの新しいプラクティスにアップグレードしようとするときに、2倍、3倍、4倍のすべての行をチェックすることをお勧めします。それは有益なので危険です。

Question

次のようにオブジェクトを作成します。

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};

次のように、新しいmyObject終わるプロパティregexを削除する最良の方法は何ですか?

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI"
};



Using delete method is the best way to do that, as per MDN description, the delete operator removes a property from an object. so you can simply write:

delete myObject.regex;
// OR
delete myObject['regex'];

The delete operator removes a given property from an object. On successful deletion, it will return true, else false will be returned. However, it is important to consider the following scenarios:

  • If the property which you are trying to delete does not exist, delete will not have any effect and will return true

  • If a property with the same name exists on the object's prototype chain, then, after deletion, the object will use the property from the prototype chain (in other words, delete only has an effect on own properties).

  • Any property declared with var cannot be deleted from the global scope or from a function's scope.

  • As such, delete cannot delete any functions in the global scope (whether this is part from a function definition or a function (expression).

  • Functions which are part of an object (apart from the
    global scope) can be deleted with delete.

  • Any property declared with let or const cannot be deleted from the scope within which they were defined. Non-configurable properties cannot be removed. This includes properties of built-in objects like Math, Array, Object and properties that are created as non-configurable with methods like Object.defineProperty().

The following snippet gives another simple example:

var Employee = {
  age: 28,
  name: 'abc',
  designation: 'developer'
}

console.log(delete Employee.name);   // returns true
console.log(delete Employee.age);    // returns true

// When trying to delete a property that does 
// not exist, true is returned 
console.log(delete Employee.salary); // returns true

For more info about and seeing more example, visit the link below:

developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…




Dan's assertion that 'delete' is very slow and the benchmark he posted were doubted. So I carried out the test myself in Chrome 59. It does seem that 'delete' is about 30 times slower:

var iterationsTotal = 10000000;  // 10 million
var o;
var t1 = Date.now(),t2;
for (let i=0; i<iterationsTotal; i++) {
   o = {a:1,b:2,c:3,d:4,e:5};
   delete o.a; delete o.b; delete o.c; delete o.d; delete o.e;
}
console.log ((t2=Date.now())-t1);  // 6135
for (let i=0; i<iterationsTotal; i++) {
   o = {a:1,b:2,c:3,d:4,e:5};
   o.a = o.b = o.c = o.d = o.e = undefined;
}
console.log (Date.now()-t2);  // 205

Note that I purposedly carried out more than one 'delete' operations in one loop cycle to minimize the effect caused by the other operations.




Another solution, using Array#reduce .

var myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};

myObject = Object.keys(myObject).reduce(function(obj, key) {
  if (key != "regex") {           //key you want to remove
    obj[key] = myObject[key];
  }
  return obj;
}, {});

console.log(myObject);

However, it will mutate the original object. If you want to create a new object without the specified key, just assign the reduce function to a new variable, eg:

(ES6)

const myObject = {
  ircEvent: 'PRIVMSG',
  method: 'newURI',
  regex: '^http://.*',
};

const myNewObject = Object.keys(myObject).reduce((obj, key) => {
  key !== 'regex' ? obj[key] = myObject[key] : null;
  return obj;
}, {});

console.log(myNewObject);




他の人が言ったように、あなたはdeleteを使用deleteことができます。 しかし、JavaScriptはOOP言語なので、すべてがオブジェクトです。 したがって、特定の注意点を指摘する必要があると感じています。

配列では、普通の古いオブジェクトと違って、 nullの形でガーベジの後ろにdelete葉を使用し、配列に「穴」を作成しnull

var array = [1, 2, 3, 4];
delete array[2];
/* Expected result --> [1, 2, 4]
 * Actual result   --> [1, 2, null, 4]
 */

ご覧のように、 deleteが期待どおりに機能deleteは限りません。 値は上書きされますが、メモリは再割り当てされません。

nullに内在する危険性や問題、およびスペースを無駄にすることなく、配列が正確である必要がある場合、これは問題になる可能性があります。

たとえば、JSONシリアライゼーションを使用して文字列(この場合はlocalStorage )に 'tabs'用の配列を格納するWebアプリケーションを作成しているとします。 また、コードが配列のメンバの数値インデックスを使用して、画面に描画するときにそれらを「タイトル」するとしましょう。 なぜあなたは単に "タイトル"も保存するのではなく、これをやっていますか? なぜなら... 理由

さて、1960年代のUNIXからPDP-11ミニコンピュータを使い、ElinksベースのJavaScript準拠のラインプリンターにやさしいブラウザはX11が問題にならないためです。

ますますばかげたエッジケースのシナリオを除いて、上記の配列のdeleteを使用deleteと、配列が汚染され、後でアプリケーションのバグが発生する可能性があります。 そしてnullをチェックすると、数字がスキップされ、タブが[1] [2] [4] [5] ...ようにレンダリングされ[1] [2] [4] [5] ...

if (array[index] == null)
    continue;
else
    title = (index + 1).toString();
/* 0 -> "1"
 * 1 -> "2"
 * 2 -> (nothing)
 * 3 -> "4"
 */

うん、それは間違いなくあなたが望むものではありません。

ここで、 jような2番目のイテレータを有効にすると、配列から有効な値が読み込まれたときにのみインクリメントすることができます。 しかし、それはnull問題を正確に解決することはできません、そして、あなたはまだそのPDP-11ユーザーを喜ばせなければなりません。 ああ、彼のコンピュータ最後の整数を保持するのに十分なメモリを持っていないだけです(可変幅の配列をどう扱うのか尋ねないでください)

だから、彼はあなたに怒りのメールを送ります:

Hey, your webapp broke my browser! I checked my localStorage database after your stupid code made my browser segfault, and this is what I found:

>"tabs:['Hello World', 'foo bar baz', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ... ]"

After clearing my precious data, it segfaulted again, and I did a backtrace, and what do I find? WHAT DO I FIND!? YOU USE TOO MANY VARIABLES!

>var i = index;
>var j = 1;

Grr, I am angry now.
-Troll Davidson

今、あなたはあなたの知恵の終わりです。 この男はあなたのアプリについてノンストップを訴えています。あなたは彼に黙ってより良いコンピュータを手に入れるように伝えたいと思っています。

幸いにも、配列に 、インデックスを削除してメモリを再割り当てするための特別なメソッドArray.prototype.splice()ます。 あなたは次のようなものを書くことができます:

Array.prototype.remove = function(index){
  this.splice(index,1);
}
...
array = [1, 2, 3, 4];
array.remove(2);
// Result -> [1, 2, 4]

そしてそれと同じように、あなたはPDP-11さんを気に入っています。 やめ! (私はまだ彼に言いたいのですが...)




これを試して

delete myObject['key'];



const myObject = {
        "ircEvent": "PRIVMSG",
        "method": "newURI",
        "regex": "^http://.*"
    };

const { regex, ...other } = myObject;

console.log(myObject)
console.log(regex)
console.log(other)




次のようなオブジェクトがあるとします。

var Hogwarts = {
    staff : [
        'Argus Filch',
        'Filius Flitwick',
        'Gilderoy Lockhart',
        'Minerva McGonagall',
        'Poppy Pomfrey',
        ...
    ],
    students : [
        'Hannah Abbott',
        'Katie Bell',
        'Susan Bones',
        'Terry Boot',
        'Lavender Brown',
        ...
    ]
};

オブジェクトプロパティの削除

staff配列全体を使用したい場合は、これを行う適切な方法は、これを行うことです。

delete Hogwarts.staff;

あるいは、これを行うこともできます:

delete Hogwarts['staff'];

同様に、students配列全体をdelete Hogwarts.students;呼び出しdelete Hogwarts.students; delete Hogwarts['students'];

配列インデックスの削除

今度は、1人の職員または学生を削除したい場合、両方のプロパティが配列そのものなので、プロシージャは少し異なります。

あなたの職員のインデックスを知っているならば、単にこれを行うことができます:

Hogwarts.staff.splice(3, 1);

インデックスを知らない場合は、インデックス検索も行う必要があります:

Hogwarts.staff.splice(Hogwarts.staff.indexOf('Minerva McGonnagall') - 1, 1);

注意

技術的には配列に対してdeleteを使用deleteことができますが、後でHogwarts.staff.lengthなどを呼び出すと間違った結果が得られます。 つまり、 deleteは要素を削除しますが、 lengthプロパティの値は更新されません。 deleteを使用deleteと、索引付けが混乱deleteこともあります。

したがって、オブジェクトから値を削除するときは、まずオブジェクトのプロパティを扱っているかどうか、または配列の値を扱っているかどうかを検討し、それに基づいて適切な戦略を選択します。

これを実験したい場合は、 このフィドルを出発点として使用できます。




you can use the delete operator as of below.

 var multiverse = {
        earth1: "Silver Age",
        earth2: "Golden Age"
    };

delete multiverse.earth2;//will return true if it finds 

// Outputs: { earth1: "Silver Age" }
console.log(multiverse);

The delete operator also has a return value. If it succeeds in deleting a property, it will return true. If it fails to delete a property because the property is unwritable it will return false , or if in strict mode it will throw an error.




Object.assign() & Object.keys() & Array.map()

const obj = {
    "Filters":[
        {
            "FilterType":"between",
            "Field":"BasicInformationRow.A0",
            "MaxValue":"2017-10-01",
            "MinValue":"2017-09-01",
            "Value":"Filters value"
        }
    ]
};

let new_obj1 = Object.assign({}, obj.Filters[0]);
let new_obj2 = Object.assign({}, obj.Filters[0]);

/*

// old version

let shaped_obj1 = Object.keys(new_obj1).map(
    (key, index) => {
        switch (key) {
            case "MaxValue":
                delete new_obj1["MaxValue"];
                break;
            case "MinValue":
                delete new_obj1["MinValue"];
                break;
        }
        return new_obj1;
    }
)[0];


let shaped_obj2 = Object.keys(new_obj2).map(
    (key, index) => {
        if(key === "Value"){
            delete new_obj2["Value"];
        }
        return new_obj2;
    }
)[0];


*/


// new version!

let shaped_obj1 = Object.keys(new_obj1).forEach(
    (key, index) => {
        switch (key) {
            case "MaxValue":
                delete new_obj1["MaxValue"];
                break;
            case "MinValue":
                delete new_obj1["MinValue"];
                break;
            default:
                break;
        }
    }
);

let shaped_obj2 = Object.keys(new_obj2).forEach(
    (key, index) => {
        if(key === "Value"){
            delete new_obj2["Value"];
        }
    }
);




また、 Underscore.jsライブラリを使用することもできます。

_.pick()_.omit()両方ともオブジェクトのコピーを返し、元のオブジェクトを直接変更しないことに注意してください。 元のオブジェクトに結果を割り当てるには、トリック(図示せず)を行う必要があります。

参照: link _.pick(オブジェクト、*キー)

ホワイトリストに登録されたキー(または有効なキーの配列)の値のみを持つようにフィルタリングされた、オブジェクトのコピーを返します。

var myJSONObject = 
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

_.pick(myJSONObject, "ircEvent", "method");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

参照: link _.omit(オブジェクト、*キー)

ブラックリストのキー(またはキーの配列)を省略するようにフィルタリングされたオブジェクトのコピーを返します。

var myJSONObject = 
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

_.omit(myJSONObject, "regex");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

配列の場合、 _.filter()_.reject()も同様の方法で使用できます。




この投稿は非常に古いので、私は非常に参考になっているので、私は他の誰かがこの投稿を見て、それがPHPのunset関数のように簡単ではないと思う場合に書いた設定されていない機能を共有することに決めました。

この新しいunset関数を書く理由は、このhash_mapの他のすべての変数のインデックスを保持することです。 次の例を見て、 "test2"のインデックスがhash_mapから値を削除した後にどのように変化しなかったかを見てください。

function unset(unsetKey, unsetArr, resort){
  var tempArr = unsetArr;
  var unsetArr = {};
  delete tempArr[unsetKey];
  if(resort){
    j = -1;
  }
  for(i in tempArr){
    if(typeof(tempArr[i]) !== 'undefined'){
      if(resort){
        j++;
      }else{
        j = i;
      }
      unsetArr[j] = tempArr[i];
    }
  }
  return unsetArr;
}

var unsetArr = ['test','deletedString','test2'];

console.log(unset('1',unsetArr,true)); // output Object {0: "test", 1: "test2"}
console.log(unset('1',unsetArr,false)); // output Object {0: "test", 2: "test2"}



I have used lodash "unset" to make it happen for nested object also.. only this need to write small logic to get path of property key which expected by omit method.

  1. Method which returns property path as array

var a = {"bool":{"must":[{"range":{"price_index.final_price":{"gt":"450","lt":"500"}}},{"bool":{"should":[{"term":{"color_value.keyword":"Black"}}]}}]}};

function getPathOfKey(object,key,currentPath, t){
     var currentPath = currentPath || [];

    for(var i in object){
		if(i == key){
        t = currentPath;
      }
      else if(typeof object[i] == "object"){
        currentPath.push(i)
       return getPathOfKey(object[i], key,currentPath)
      }
    }
	t.push(key);
    return t;
}
document.getElementById("output").innerHTML =JSON.stringify(getPathOfKey(a,"price_index.final_price"))
<div id="output"> 

</div>

  1. Then just using lodash unset method remove property from object.

var unset = require('lodash.unset');
unset(a,getPathOfKey(a,"price_index.final_price"));




Try the following method. Assign the Object property value to undefined . Then stringify the object and parse .

 var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

myObject.regex = undefined;
myObject = JSON.parse(JSON.stringify(myObject));

console.log(myObject);









Links