次のようにオブジェクトを作成したとします。
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
次のように、プロパティregex
を削除して新しいmyObject
にする最良の方法は何ですか?
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI"
};
このような:
delete myObject.regex;
// or,
delete myObject['regex'];
// or,
var prop = "regex";
delete myObject[prop];
デモ
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
delete myObject.regex;
console.log(myObject);
もっと詳しく知りたいという人のために、Stack Overflow user kangax は、自分のブログのdelete
ステートメントに関する信じられないほど詳細なブログ記事を書いています。deleteについてお勧めです。
delete
は予想外に遅いです!ベンチマークを見てください。
削除は、残り物なしでオブジェクトのプロパティを削除する唯一の真の方法ですが、「代替」と比較して、100倍遅く〜動作しますobject[key] = undefined
。
この選択肢は、この質問に対する正しい答えではありません!ただし、注意して使用すると、一部のアルゴリズムを劇的に高速化できます。ループでdelete
を使用していて、パフォーマンスに問題がある場合は、詳細な説明を読んでください。
delete
を使用し、値をundefined
に設定する必要がありますか?オブジェクトは、キーと値のペアのセットとして見ることができます。 「値」と呼ぶものは、その「キー」に接続されたプリミティブまたは他のオブジェクトへの参照です。
制御できないコードに結果オブジェクトを渡す場合(または不明な場合)は、delete
、を使用しますあなたのチームまたはあなた自身について)。
ハッシュマップからキーを削除します。
var obj = {
field: 1
};
delete obj.field;
パフォーマンスを重視する場合は、undefined
、の設定を使用します。コードを大幅に強化できます。
キーはhashmap内のその場所に残り、値のみがundefined
に置き換えられます。 for..in
ループはそのキーを繰り返し処理することを理解してください。
var obj = {
field: 1
};
obj.field = undefined;
このメソッドを使用すると、すべての プロパティの存在を判断する方法 が期待どおりに機能するとは限りません。
ただし、このコード:
object.field === undefined
両方の方法で同等に動作します。
要約すると、違いはすべて、プロパティの存在を判断する方法と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] = undefined
の使用はdelete obj[prop]
の実行よりも高速ですが、別の重要な考慮事項は、obj[prop] = undefined
が常に適切であるとは限らないことです。 delete obj[prop]
はprop
をobj
から削除してメモリから消去しますが、obj[prop] = undefined
はprop
の値をundefined
に設定するだけでprop
を残します_まだメモリ内にあります。したがって、多くのキーが作成および削除される状況では、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スロットは未定義に設定されるだけで、メモリにハングアップしたままになります。コンソールで上記のコードを実行してみて、自分で確認してください。メモリ不足エラーを強制した後、代わりに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つの大きな問題があります。
多型を麻薬中毒にたとえることができます。一見したところ、それはすばらしくluかるように見えます。すてきなふわふわしたコードです。次に、コーダーは配列を多型の薬物に導入します。即座に、ポリモーフィック配列の効率は低下し、ドラッグされるため、以前ほど効率的になることはありません。このような状況を現実の生活に関連付けるために、コカインを使用している人は単純なドアハンドルを操作することすらできず、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
は強制します。したがって、誤ってポリモーフィズムを引き起こさないように、可能な場合は常に、オブジェクトに対応する型を使用する必要があります。そのような人は、次のリストを一般的な参考資料として使用して、それらを実行することができます。ただし、以下のアイデアを明示的に使用しないでください。代わりに、コードに適したものを使用してください。
false
またはundefined
を空の値として使用します。不要なポリモーフィズムを避けることは良いことですが、明示的に禁止するようにすべてのコードを書き換えると、実際にはパフォーマンスが低下する可能性があります。一般的な判断を使用してください!0
を空の値として使用します。内部的には、高速整数(2147483647〜-2147483648を含む)と低速浮動小数点の倍精度(NaN
およびInfinity
を含むもの以外)の2種類の数値があることに注意してください。整数がdoubleに降格されると、整数に戻すことはできません。""
を空の値として使用します。null
を使用します。ただし、注意してください!このような既存のコードが壊れたり、奇妙なバグが発生したりする可能性があるため、既存のすべてのコードでこれを突然開始しないでください。むしろ、そのような効率的なプラクティスは最初から実装する必要があり、既存のコードを変換するときは、古いコードをこの新しいプラクティスにアップグレードしようとして、それに関連するすべての行を二重、三重、四重チェックすることをお勧めしますやりがいがあるので危険です。
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
delete myObject.regex;
console.log ( myObject.regex); // logs: undefined
これはFirefoxとInternet Explorerで機能しますが、他のすべてでも機能すると思います。
pdate 2018-07-21:長い間、私はこの答えに恥ずかしさを感じていたので、少し修正するときだと思います。この回答の不必要に長く複雑な部分の読み上げを促進するためのほんの少しの解説、明確化、およびフォーマット。
他の人が言ったように、delete
を使用できます。
obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined
配列からdelete
しないでください。代わりにArray.prototype.splice
を使用してください。
arr // [1,2,3,4,5]
arr.splice(3,1); // 4
arr // [1,2,3,5]
JavaScriptはOOP言語であるため、arraysを含むすべてがオブジェクトです。したがって、特定の注意事項を指摘する必要があると感じています。
配列では、単純な古いオブジェクトとは異なり、delete
を使用すると、null
の形でゴミが残り、配列に「穴」ができます。
var array = [1, 2, 3, 4];
delete array[2];
/* Expected result --> [1, 2, 4]
* Actual result --> [1, 2, null, 4]
*/
ご覧のとおり、delete
は常に期待どおりに機能するとは限りません。値は上書きされますが、メモリは再割り当てされません。つまり、array[4]
はarray[3]
に再配置されません。これは、配列の先頭に要素を挿入し、すべてを上にシフトするArray.prototype.unshift
とは対照的です(array[0]
はarray[1]
などになります)
正直なところ、null
ではなくundefined
に設定することは別として、これは正当に奇妙なことです。この動作は、驚くべきことに、delete
はtypeof
のような単項演算子であり、言語にハードボイルドされており、type使用されているオブジェクトのArray
は、特定の目的のために設計されたメソッドを持つObject
のサブクラスです配列の操作。したがって、delete
が配列を再シフトするための特別なケースを用意する理由はありません。これは、不必要な作業で物事を遅くするだけです。振り返ってみると、私の期待は非現実的でした。
もちろん、didびっくりしました。私がこれを書いたのは、「ヌルごみ」に対する私の十字軍を正当化するためです。
null
に固有の危険性と問題、および無駄になるスペースを無視すると、配列を正確にする必要がある場合、これは問題になる可能性があります。
これはnull
s --null
を取り除くためのひどい正当化であり、不適切に使用された場合にのみ危険であり、「精度」とは関係ありません。配列からdelete
をすべきではない本当の理由は、不要なデータ構造を乱雑に残したままにしておくと、ずさんでバグが発生しやすいことです。
以下は、非常に長い時間を費やした不自然なシナリオです。したがって、必要に応じてThe Solutionのセクションにスキップできます。このセクションを去る唯一の理由は、おそらく面白いと思う人がいると思うからです。「面白い」答えを投稿し、後で「面白い」をすべて削除する「あの人」になりたくない。
...それは愚かだ、知っている。
たとえば、JSONシリアル化を使用して、「タブ」に使用される配列を文字列(この場合は
localStorage
)に格納するwebappを作成するとします。また、コードが配列のメンバーの数値インデックスを使用して、画面に描画するときにそれらに「タイトル」を付けるとしましょう。 「タイトル」だけを保存するのではなく、なぜこれを行うのですか?なぜなら...理由.さて、1960年代のUNIXを実行しているPDP-11ミニコンピューターを実行するこのoneユーザーの要求でメモリを節約しようとしているとしましょうX11は問題外であるため、独自のElinksベース、JavaScript準拠、ラインプリンター対応のブラウザーを作成しました。
ますます愚かなエッジケースシナリオを別にすれば、上記の配列で
delete
を使用すると、null
が配列を汚染し、後でアプリにバグを引き起こす可能性があります。そして、null
をチェックすると、数字をまっすぐスキップして、[1] [2] [4] [5] ...
のようにタブがレンダリングされます。if (array[index] == null) continue; else title = (index + 1).toString(); /* 0 -> "1" * 1 -> "2" * 2 -> (nothing) * 3 -> "4" */
ええ、それは間違いなくあなたが望んだものではありません。
ここで、couldは、有効な値が配列から読み取られたときにのみ増分するように、
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
幸いなことに、配列doには、インデックスを削除してメモリを再割り当てするための特別なメソッド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氏を喜ばせました。やった! (私はまだ彼に言いますが...)
これら2つの類似した名前の関数は、どちらも非常に有用なので、違いを指摘することが重要だと思います。
.splice()
は配列を変更し、削除されたインデックスを返します。配列はインデックスからスライスされ、start
、およびn
要素がスライスされます。 nが指定されていない場合、start
の後の配列全体がスライスされます(n = array.length - start
)。
let a = [5,4,3,2,1];
let chunk = a.splice(2,2);
// a [5,4,3,2,1]
// start 0 1 2 - -
// n - - 1 2 -
chunk; // [3,2]
a; // [5,4,1]
.slice()
は非破壊的であり、start
からend
までの指定されたインデックスを含む新しい配列を返します。 end
が指定されていない場合、動作は.splice()
(end = array.length
)と同じです。何らかの理由で、0ではなく1からend
インデックスが作成されるため、この動作は少し注意が必要です。これを行う理由はわかりませんが、そのようになっています。また、end <= start
の場合、結果は空の配列になります。
let a = [5,4,3,2,1];
let chunks = [
a.slice(2,0),
a.slice(2,2),
a.slice(2,3),
a.slice(2,5) ];
// a [5,4,3,2,1]
// start 0 1 2 - -
// end, for... - - - - -
// chunks[0] 0 - - - - -
// chunks[1] 1 2 - - -
// chunks[2] 1 2 3 - -
// chunks[3] 1 2 3 4 5
chunks; // [ [], [], [3], [3,2,1] ]
a; // [5,4,3,2,1]
それは実際に起こっていることではありませんが、そのように考える方が簡単です。 MDNによると、実際に起こっていることは次のとおりです。
// a [5,4,3,2,1]
// start 0 1 2 - - -
// end, for... - - - - - -
// chunks[0] 0 - - - - -
// chunks[1] 0 1 2 - - -
// chunks[2] 0 1(2)3 - -
// chunks[3] 0 1(2 3 4)5
end
で指定されたインデックスは、スライスから単に除外されます。括弧で囲まれたインデックスは、スライスされるものを示します。いずれにせよ、動作は直感的ではなく、オフバイワンエラーをかなりの割合で発生させるはずです。したがって、.splice()
の動作をより厳密にエミュレートするラッパー関数を作成すると便利です。
function ez_slice(array, start = 0, n = null){
if(!Array.isArray(array) || !is_number(start))
return null;
if(is_number(n))
return array.slice(start, start + n);
if(n === null)
return array.slice(start);
return null;
}
ez_slice([5,4,3,2,1], 2, 1) // [3]
ez_slice([5,4,3,2,1], 2) // [3,2,1]
/* Fun fact: isNaN is unreliable.
* [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(isNaN)
* [NaN, {}, undefined, "Hi"]
*
* What we want is...
*
* [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(is_nan)
* [NaN]
*/
function is_nan(num){
return typeof num === "number"
&& num !== num;
}
function is_number(num){
return !is_nan(num)
&& typeof num === "number"
&& isFinite(num);
}
ラッパー関数は型について非常に厳密になるように設計されており、何かがオフの場合はnull
を返すことに注意してください。これには、"3"
のような文字列を含めることが含まれます。彼の型について熱心に取り組むことはプログラマに任されています。これは、優れたプログラミングの実践を促進するためです。
is_array()
に関する更新これは、この(現在は削除された)スニペットに関するものです。
function is_array(array){
return array !== null
&& typeof array === "object"
&& typeof array.length !== "undefined"
&& array.__proto__ === Array.prototype;
}
結局のところ、実際にはISが配列が本当に配列であるかどうかを知るための組み込み方法であり、それがECMAScript 5(2009年12月)で導入されたArray.isArray()
です。私はこれを、オブジェクトから配列を伝えることについて質問するかどうか、私のものよりも良い解決策があるかどうか、またはない場合は追加するかどうかを調べているときに見つけました。そのため、ECMA 5より前のバージョンのJavaScriptを使用している場合、ポリフィルがあります。ただし、古いバージョンのJavaScriptを引き続きサポートすることは、それらを実装する古いブラウザーを引き続きサポートすることを意味するため、is_array()
関数の使用を強くお勧めします。つまり、安全でないソフトウェアの使用を奨励し、ユーザーをマルウェアの危険にさらすことを意味しますしたがって、Array.isArray()
を使用してください。 let
およびconst
を使用します。言語に追加される新しい機能を使用します。 ベンダープレフィックスを使用しないでください。 あなたのウェブサイトからIEポリフィルがらくたを削除します。そのXHTML <!CDATA[[...
がらくたも削除します。2014年にHTML5に移行しました。誰もが古い/難解なブラウザのサポートをすぐに廃止すると、ブラウザベンダーは実際にWeb標準に従い、新しいテクノロジを採用します。より早く、より安全なWebに移行できます。
昔の質問、現代の答え。オブジェクトの分解、 ECMAScript 6 機能を使うと、次のように簡単になります。
const { a, ...rest } = { a: 1, b: 2, c: 3 };
または質問サンプルでは:
const myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
const { regex, ...newObject } = myObject;
console.log(newObject);
Babelの試作エディタで実際に動作しているのを見ることができます。
編集:
同じ変数に再割り当てするには、let
を使用します。
let myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
({ regex, ...myObject } = myObject);
console.log(myObject);
別の方法は Underscore.js ライブラリを使用することです。
_.pick()
と_.omit()
は両方ともオブジェクトのコピーを返し、元のオブジェクトを直接変更しないことに注意してください。オリジナルのオブジェクトに結果を代入することはトリックをするべきです(示されていない)。
参照: link _.pick(object、* keys)
ホワイトリストに登録されたキー(または有効なキーの配列)の値のみを持つようにフィルタ処理されたオブジェクトのコピーを返します。
var myJSONObject =
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
_.pick(myJSONObject, "ircEvent", "method");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};
参照: link _.omit(object、* keys)
ブラックリストに記載されているキー(またはキーの配列)を除外するようにフィルタリングされた、オブジェクトのコピーを返します。
var myJSONObject =
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
_.omit(myJSONObject, "regex");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};
配列の場合、_.filter()
と_.reject()
を同じように使用できます。
必要な人には….
このスレッドで@Koenという答えを完成するには、スプレッド構文を使用して動的変数を削除したい場合は、次のようにします。
const key = 'a';
const { [key]: foo, ...rest } = { a: 1, b: 2, c: 3 };
console.log(rest); // { b: 2, c: 3 }
* foo
は、a
の値(1)を持つ新しい変数になります。
UPDATE:
オブジェクトからプロパティを削除する一般的な方法はほとんどありません。
それぞれ独自の長所と短所があります( このパフォーマンスの比較を確認してください )。
削除演算子
読みやすくて短いですが、パフォーマンスが最適化されていないため、多数のオブジェクトを操作している場合は最適な選択肢とは言えません。
delete obj[key];
再割り当てdelete
よりも2倍以上速いですが、このプロパティは ではなく 削除されているため、繰り返すことができます。
obj[key] = null;
obj[key] = false;
obj[key] = undefined;
Spread Operator
このES6
演算子を使用すると、既存のオブジェクトを変更することなく、プロパティを除いてまったく新しいオブジェクトを返すことができます。欠点は、上記のうちパフォーマンスが悪いため、一度に多数のプロパティを削除する必要がある場合には使用しないことをお勧めします。
{ [key]: val, ...rest } = obj;
質問タイトルRemove a property from a JavaScript object
で使用した用語は、いくつかの異なる方法で解釈できます。 1つはメモリ全体とオブジェクトキーのリストを削除することで、もう1つはオブジェクトから削除することです。他の回答でも述べたように、キーワードdelete
が主要部分です。次のようなオブジェクトがあるとしましょう。
myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
もしあなたがそうするなら:
console.log(Object.keys(myJSONObject));
結果は次のようになります。
["ircEvent", "method", "regex"]
次のようにオブジェクトキーからその特定のキーを削除できます。
delete myJSONObject["regex"];
Object.keys(myJSONObject)
を使ったオブジェクトキーは次のようになります。
["ircEvent", "method"]
しかし、ポイントは、メモリを気にしていて、オブジェクト全体をメモリから削除したい場合は、キーを削除する前にnullに設定することをお勧めします。
myJSONObject["regex"] = null;
delete myJSONObject["regex"];
ここでもう1つ重要な点は、同じオブジェクトに対する他の参照に注意することです。たとえば、次のような変数を作成したとします。
var regex = myJSONObject["regex"];
あるいは、それを別のオブジェクトへの新しいポインタとして追加します。
var myOtherObject = {};
myOtherObject["regex"] = myJSONObject["regex"];
それであなたがそれをあなたのオブジェクトmyJSONObject
から取り除いたとしても、その特定のオブジェクトはメモリから削除されないでしょう。なぜならregex
変数とmyOtherObject["regex"]
はまだそれらの値を持っているからです。では、どうすれば確実にオブジェクトをメモリから削除できますか?
その答えは、自分のコードにあるすべての参照をそのobjectを参照して削除し、さらにobject_への新しい参照を作成するためにvar
文を使用しないことです。 var
ステートメントに関する最後のポイントは、var
ステートメントを使用すると作成されたオブジェクトが削除されなくなるため、通常直面する最も重大な問題の1つです。
これは、この場合、regex
ステートメントを介してvar
変数を作成したために、そのオブジェクトを削除できないことを意味します。
delete regex; //False
結果はfalse
になります。これは、あなたのdelete文があなたの期待通りに実行されていないことを意味します。しかし、その変数を以前に作成したことがなく、最後の既存の参照としてmyOtherObject["regex"]
しかない場合は、次のように削除することでこれを実行できます。
myOtherObject["regex"] = null;
delete myOtherObject["regex"];
つまり、JavaScriptオブジェクトは、そのオブジェクトを指すコード内に参照がなくなるとすぐに強制終了されます。
更新: @AgentMEに感謝します。
削除する前にプロパティをnullに設定しても何も達成されません(Object.sealによってオブジェクトが封印されていて削除に失敗した場合を除きます。通常はそうではありません)。
Object.seal
の詳細情報を取得するには、 Object.seal() を使用してください。
ECMAScript 2015(またはES6)には Reflect objectが組み込まれています。ターゲットオブジェクトとプロパティキーをパラメータにして Reflect.deleteProperty() functionを呼び出すことで、オブジェクトのプロパティを削除することができます。
Reflect.deleteProperty(myJSONObject, 'regex');
これは以下と同等です。
delete myJSONObject['regex'];
しかし、オブジェクトのプロパティが設定できない場合は、deleteProperty関数でもdelete演算子でも削除できません。
let obj = Object.freeze({ prop: "value" });
let success = Reflect.deleteProperty(obj, "prop");
console.log(success); // false
console.log(obj.prop); // value
Object.freeze() (他のものを除いて)オブジェクトのすべてのプロパティを設定不可能にする。 deleteProperty
関数(および delete演算子 と同じ)は、そのいずれかのプロパティを削除しようとするとfalse
を返します。 propertyが設定可能な場合は、propertyが存在しなくてもtrue
を返します。
delete
とdeleteProperty
の違いは、厳密モードを使用する場合です。
"use strict";
let obj = Object.freeze({ prop: "value" });
Reflect.deleteProperty(obj, "prop"); // false
delete obj["prop"];
// TypeError: property "prop" is non-configurable and can't be deleted
次のようなオブジェクトがあるとします。
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'];
を呼び出します。
1人のスタッフまたは学生を削除する場合、手順は少し異なります。両方のプロパティが配列そのものであるためです。
あなたがあなたのスタッフのインデックスを知っているなら、あなたは単にこれをすることができます:
Hogwarts.staff.splice(3, 1);
インデックスがわからない場合は、インデックス検索も行う必要があります。
Hogwarts.staff.splice(Hogwarts.staff.indexOf('Minerva McGonnagall') - 1, 1);
技術的には配列にdelete
を使用できますが、それを使用すると、後でHogwarts.staff.length
を呼び出すときに誤った結果が得られる可能性があります。つまり、delete
は要素を削除しますが、length
プロパティの値は更新しません。 delete
を使うことはまたあなたのインデックス付けを台無しにするでしょう。
そのため、オブジェクトから値を削除するときは、常にオブジェクトのプロパティを扱うのか配列の値を扱うのかを最初に検討し、それに基づいて適切な戦略を選択してください。
これを試してみたい場合は、 this Fiddle を出発点として使用できます。
delete演算子 がそのための最善の方法です。
表示するライブの例:
var foo = {bar: 'bar'};
delete foo.bar;
console.log('bar' in foo); // Logs false, because bar was deleted from foo.
私は個人的に Underscore.js または Lodash をオブジェクトと配列の操作に使います。
myObject = _.omit(myObject, 'regex');
delete methodを使用するのが最善の方法です。MDNの説明によると、delete演算子はオブジェクトからプロパティを削除します。だからあなたは単に書くことができます:
delete myObject.regex;
// OR
delete myObject['regex'];
Delete演算子は、与えられたプロパティをオブジェクトから削除します。正常に削除された場合はtrue、それ以外の場合はfalseが返されます。ただし、以下のシナリオを検討することが重要です。
削除しようとしているプロパティが存在しない場合、deleteは効果がなく、trueを返します。
同じ名前のプロパティがオブジェクトのプロトタイプチェーンに存在する場合、削除後、オブジェクトはプロトタイプチェーンのプロパティを使用します(つまり、deleteは自身のプロパティにのみ影響します)。
Varで宣言されたプロパティは、グローバルスコープまたは関数のスコープから削除できません。
そのため、deleteはグローバルスコープ内の関数を削除できません(これが関数定義の一部であるか関数(式)の一部であるかにかかわらず)。
オブジェクトの一部である関数
グローバルスコープ)はdeleteで削除できます。Letまたはconstで宣言されたプロパティは、定義されている範囲から削除することはできません。構成不可能なプロパティは削除できません。これには、Math、Array、Objectなどの組み込みオブジェクトのプロパティ、およびObject.defineProperty()などのメソッドを使用して構成不可能として作成されたプロパティが含まれます。
次のスニペットは別の簡単な例を示しています。
var Employee = {
age: 28,
name: 'Alireza',
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
より多くの情報とより多くの例を見るために、以下のリンクを訪問してください:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
Array#reduce
を使用したもう1つの解決策。
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);
しかし、元のオブジェクトはmutateされます。指定したキーで新しいオブジェクトwithoutを作成したい場合は、reduce関数を新しい変数に代入してください。
(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);
この記事は非常に古く、とても役に立ちましたので、他の誰かがこの記事を見た場合に備えて、私が書いた設定解除関数を共有し、PHP設定解除関数ほど単純ではない理由を考えます。
この新しいunset
関数を書く理由は、このhash_mapの他のすべての変数のインデックスを保持するためです。次の例を見て、hash_mapから値を削除しても "test2"のインデックスが変わらないことを確認してください。
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"}
良い答えはたくさんありますが、JavaScriptでプロパティを削除するためにdeleteを使うときは、エラーを防ぐためにそのプロパティが存在するかどうかを最初に確認するのが賢明です。
例えば
var obj = {"property":"value", "property2":"value"};
if (obj && obj.hasOwnProperty("property2")) {
delete obj.property2;
} else {
//error handling
}
JavaScriptの動的な性質のため、プロパティが存在するかどうかがわからない場合がよくあります。 &&の前にobjが存在するかどうかをチェックすることで、未定義のオブジェクトに対してhasOwnProperty()関数を呼び出すことによるエラーをスローしないようにすることもできます。
これがあなたの特定のユースケースに追加されなかった場合は申し訳ありませんが、オブジェクトとそのプロパティを管理するときに適応するのに良い設計だと私は思います。
ramda#dissoc を使用すると、属性regex
を持たない新しいオブジェクトが得られます。
const newObject = R.dissoc('regex', myObject);
// newObject !== myObject
他の関数を使用して同じ効果を得ることもできます - 省略、選択、...
次の方法を試してください。 Object
プロパティ値をundefined
に割り当てます。それからstringify
オブジェクトとparse
。
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
myObject.regex = undefined;
myObject = JSON.parse(JSON.stringify(myObject));
console.log(myObject);
ES6を使用する:
(デストラクチャリング+スプレッド演算子)
const myObject = {
regex: "^http://.*",
b: 2,
c: 3
};
const { regex, ...noRegex } = myObject;
console.log(noRegex); // => { b: 2, c: 3 }
オブジェクト内で深くネストされたプロパティを削除したい場合は、2番目の引数としてプロパティへのパスを指定して次の再帰関数を使用できます。
var deepObjectRemove = function(obj, path_to_key){
if(path_to_key.length === 1){
delete obj[path_to_key[0]];
return true;
}else{
if(obj[path_to_key[0]])
return deepObjectRemove(obj[path_to_key[0]], path_to_key.slice(1));
else
return false;
}
};
例:
var a = {
level1:{
level2:{
level3: {
level4: "yolo"
}
}
}
};
deepObjectRemove(a, ["level1", "level2", "level3"]);
console.log(a);
//Prints {level1: {level2: {}}}
delete
キーワードを使用すると、オブジェクトの任意のプロパティを簡単に削除できます。
例えば:
var obj = {key1:"val1",key2:"val2",key3:"val3"}
key1
と言うプロパティを削除するには、次のようにdelete
キーワードを使用します。
delete obj.key1
あるいは、配列風の表記法を使うこともできます。
delete obj[key1]
参照: _ mdn _ 。
元のオブジェクトは常にプログラムの他の部分から参照される可能性があるため、"regex"
プロパティを指定せずに新しいオブジェクトを作成することを検討してください。したがって、あなたはそれを操作することを避けるべきです。
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
const { regex, ...newMyObject } = myObject;
console.log(newMyObject);
'削除'は非常に遅いというダンの主張と彼が発表したベンチマークは疑われていた。それで私はChrome 59で自分でテストを実行しました。それは '削除'が約30倍遅いようです:
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
他の操作による影響を最小限に抑えるために、1つのループサイクルで複数の「削除」操作を意図的に実行したことに注意してください。
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"];
}
}
);
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
const { regex, ...other } = myObject;
console.log(myObject)
console.log(regex)
console.log(other)
これを試して
delete myObject['key'];
こんにちはあなたはこの単純なソートを試すことができます
var obj = [];
obj.key1 = {name: "John", room: 1234};
obj.key2 = {name: "Jim", room: 1234};
delete(obj.key1);
このページにはさまざまなオプションが表示されていますが、ほとんどのオプションが間違っているため、または答えが重複しているためではありません。適切な手法は現在の状況や自分や自分のタスクの目的によって異なります。チームは達成しようとしています。明確にあなたの質問に答えるために、人は知る必要があります:
これら4つの質問に答えたら、あなたの目標を達成するために選ぶべきJavaScriptの「プロパティ除去」の4つのカテゴリーが本質的にあります。彼らです:
このカテゴリは、元の参照をそのまま使用し続け、コード内でステートレスな機能原則を使用していない場合に、オブジェクトリテラルまたはオブジェクトインスタンスを操作するためのものです。このカテゴリの構文の例
'use strict'
const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
delete iLikeMutatingStuffDontI[Symbol.for('amICool')] // true
Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
delete iLikeMutatingStuffDontI['amICool'] // throws
このカテゴリは、最も古く、最もわかりやすく、最も広くサポートされているプロパティの削除カテゴリです。文字列に加えてSymbol
&array indexもサポートしており、最初のリリースを除くすべてのバージョンのJavaScriptで動作します。ただし、これは突然変異型であり、プログラミングの原則に違反しており、パフォーマンスに影響を及ぼします。厳密モードの 設定不可能なプロパティに対して使用すると、キャッチされない例外が発生する可能性があります 。
このカテゴリは、非突然変異的なアプローチが望まれていて、Symbolキーを考慮する必要がないときに、新しいECMAScriptフレーバーのプレーンオブジェクトまたは配列インスタンスを操作するためのものです。
const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
const { name, ...coolio } = foo // coolio doesn't have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(
このカテゴリは、設定不可能なプロパティでスローされる例外から保護しながら、元の参照を保持または使用し続けたい場合に、オブジェクトリテラルまたはオブジェクトインスタンスを操作するためのものです。
'use strict'
const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
Reflect.deleteProperty(iLikeMutatingStuffDontI, Symbol.for('amICool')) // true
Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
Reflect.deleteProperty(iLikeMutatingStuffDontI, 'amICool') // false
さらに、インプレースでオブジェクトを変更することはステートレスではありませんが、Reflect.deleteProperty
の機能的性質を使用して、部分的な適用およびdelete
ステートメントでは不可能な他の機能的手法を実行できます。
このカテゴリは、非突然変異的なアプローチが望まれていて、Symbolキーを考慮する必要がないときに、新しいECMAScriptフレーバーのプレーンオブジェクトまたは配列インスタンスを操作するためのものです。
const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
const { name, ...coolio } = foo // coolio doesn't have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(
このカテゴリは一般に、シンボルの計算と1つのステートメント内の複数のプロパティの省略を含め、より大きな機能の柔軟性を可能にします。
const o = require("lodash.omit")
const foo = { [Symbol.for('a')]: 'abc', b: 'b', c: 'c' }
const bar = o(foo, 'a') // "'a' undefined"
const baz = o(foo, [ Symbol.for('a'), 'b' ]) // Symbol supported, more than one prop at a time, "Symbol.for('a') undefined"
Lodashを使う
import omit from 'lodash/omit';
const prevObject = {test: false, test2: true};
// Removes test2 key from previous object
const nextObject = omit(prevObject, 'test2');
Ramdaを使う
R.omit(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, c: 3}
ES6分解をrest演算子と一緒に使用できます。
destructuring を rest演算子 と組み合わせて使用して、プロパティを削除できます。あなたの例では、正規表現は分解され(無視され)、残りのプロパティはrestとして返されます。
const noRegex = ({ regex, ...rest }) => rest;
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
console.log(noRegex(myObjext)) //=> { "ircEvent": "PRIVMSG","method": "newURI" }
あるいは、このようなプロパティを動的に除外することもできます。
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
const removeProperty = prop => ({ [prop]: _, ...rest }) => rest
const removeRegex = removeProperty('regex') //=> { "ircEvent": "PRIVMSG","method":"newURI" }
const removeMethod = removeProperty('method') //=> { "ircEvent": "PRIVMSG", "regex":"^http://.*" }
@johnstock 、JavaScriptのプロトタイピングの概念を使用して、オブジェクトにメソッドを追加し、呼び出し元のオブジェクトで使用可能な渡されたキーをすべて削除することもできます。
上記の答えは大歓迎です。
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
// 1st and direct way
delete myObject.regex; // delete myObject["regex"]
console.log(myObject); // { ircEvent: 'PRIVMSG', method: 'newURI' }
// 2 way - by using the concept of JavaScript's prototyping concept
Object.prototype.removeFromObjectByKey = function(key) {
// If key exists, remove it and return true
if(this[key] !== undefined) {
delete this[key]
return true;
}
// Else return false
return false;
}
var isRemoved = myObject.removeFromObjectByKey('method')
console.log(myObject) // { ircEvent: 'PRIVMSG' }
// More examples
var obj = { a: 45, b: 56, c: 67}
console.log(obj) // { a: 45, b: 56, c: 67 }
// Remove key 'a' from obj
isRemoved = obj.removeFromObjectByKey('a')
console.log(isRemoved); //true
console.log(obj); // { b: 56, c: 67 }
// Remove key 'd' from obj which doesn't exist
var isRemoved = obj.removeFromObjectByKey('d')
console.log(isRemoved); // false
console.log(obj); // { b: 56, c: 67 }
とても簡単
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
delete myObject.regex;
以下のようにdelete
演算子を使うことができます。
var multiverse = {
earth1: "Silver Age",
earth2: "Golden Age"
};
delete multiverse.earth2;//will return true if it finds
// Outputs: { earth1: "Silver Age" }
console.log(multiverse);
Delete演算子にはreturn value.
もあります。プロパティの削除に成功した場合、trueが返されます。プロパティが書き込み不可であるためにプロパティの削除に失敗した場合はreturn false
になります。厳密モードの場合はエラーをスローします。
すでに多くの人が言っているように、 "delete"(javascriptプロパティ)または "unset"(lodashを使用)のどちらかを使用できます。
また、lodashプロパティ "pick"を使用して必要なオブジェクトプロパティのみを選択することもできます。オブジェクトから複数のプロパティを削除するときに役立ちます。
下記のように使用方法:
var _ = require("lodash");
var obj = {"a":1, "b":2, "c":3};
obj = _.pick(obj,["a","b"]);
//Now obj contains only 2 props {"a":1, "b":2}
lodash "unset" をネストされたオブジェクトに対しても行うために使用しています。これは、省略メソッドで期待されるプロパティキーのパスを取得するための小さなロジックを書く必要があるだけです。
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>
var unset = require('lodash.unset');
unset(a,getPathOfKey(a,"price_index.final_price"));
function removeProperty(obj, prop) {
if(prop in obj){
Reflect.deleteProperty(obj, prop);
return true;
} else {
return false;
}
}
For
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
myObject ["regex"];を削除します。また、Egのキーのインデックスも知っています。あなたはそれから2nd key(regex)を削除する必要があります。
var key = Object.keys(myObject)[2]
delete myObject[key];
オブジェクト内のインデックスベースの削除が必要になることが多いです
プロパティなしでオブジェクトを複製するには:
例えば:
let object = { a: 1, b: 2, c: 3 };
そして 'a'を削除する必要があります。
1.明示的なpropキーを使って:
const { a, ...rest } = object;
object = rest;
2.可変支柱キー付き:
const propKey = 'a';
const { [propKey]: propValue, ...rest } = object;
object = rest;
3.クールアロー機能
const removePropery = (propKey, { [propKey]: propValue, ...rest }) => rest;
object = removePropery('a', object);