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




javascript オブジェクト 削除 (24)

ramda#dissocを使用すると、属性なしで新しいオブジェクトが得られますregex

const newObject = R.dissoc('regex', myObject);
// newObject !== myObject

あなたは同じ効果を達成するために他の関数を使うこともできます - 省略、選択、...

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

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

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

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

別の解決策、使用します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);

しかし、それはなり変異させ、元のオブジェクトを。指定したキーを指定せずに新しいオブジェクトを作成する場合は、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);


古い質問、現代的な答え。 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);

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

console.log ( myObject.regex); // logs: undefined

これはFirefoxとInternet Explorerで動作しますが、他のすべてで動作すると思います。


あなたの質問のタイトルで使用した用語Remove a property from a JavaScript objectには、いくつかの異なる方法で解釈することができます。 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"];

他の重要な点は、同じオブジェクトへの他の参照を注意することです。 たとえば、次のような変数を作成するとします。

var regex = myJSONObject["regex"];

または、次のような別のオブジェクトへの新しいポインタとして追加します。

var myOtherObject = {};
myOtherObject["regex"] = myJSONObject["regex"];

その後、たとえあなたのオブジェクトmyJSONObjectからそれを削除しても、その特定のオブジェクトはメモリから削除されません。なぜなら、 regex変数とmyOtherObject["regex"]はそれらの値を持っているからです。 それでは、どのようにしてオブジェクトを確実にメモリから取り除くことができますか?

その答えは、コード内のすべての参照削除し、そのオブジェクト指し、 varステートメントを使用してそのオブジェクトへの新しい参照を作成しないことです。 varステートメントに関するこの最後の点は、 varステートメントを使用すると、作成されたオブジェクトが削除されないため、通常直面する最も重要な問題の1つです。

これは、この場合、 varステートメントでregex変数を作成し、次の場合にそのオブジェクトを削除できないことを意味します。

delete regex; //False

結果はfalseになりfalse 。これは、delete文が期待通りに実行されていないことを意味します。 しかし以前にその変数を作成しておらず、最後の既存の参照としてmyOtherObject["regex"]しかない場合は、次のように削除するだけでした。

myOtherObject["regex"] = null;
delete myOtherObject["regex"];

言い換えれば、JavaScriptオブジェクトは、そのオブジェクトを指しているコードに参照が残っていなくなるとすぐに取り除かれます。

アップデート: @AgentMEのおかげで:

オブジェクトを削除する前にプロパティをnullに設定しても、何も成立しません(オブジェクトがObject.sealでシールされていない場合や、削除に失敗した場合を除きます)。

Object.seal詳細情報を取得するには: Object.seal()


このような:

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);

kangaxユーザーkangaxはブログのdeleteステートメントに関する深いブログ記事「Understanding delete」を書いています。 強くお勧めします。


これを試して

delete myObject['key'];

こんにちはあなたはこの単純な並べ替え

var obj = [];

obj.key1 = {name: "John", room: 1234};
obj.key2 = {name: "Jim", room: 1234};

delete(obj.key1);

ES6の使用:

(デストラクチャリング+スプレッド演算子)

    const myObject = {
      regex: "^http://.*",
      b: 2,
      c: 3
    };
    const { regex, ...noRegex } = myObject;
    console.log(noRegex); // => { b: 2, c: 3 }

この投稿は非常に古いので、私は非常に参考になっているので、私は他の誰かがこの投稿を見て、それが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"}

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

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'];

同様に、全体の学生の配列を削除することは呼び出して実行されるだろう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台無しにあなたのインデックスをもう。

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

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



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

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

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


非常に単純です:

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

delete myObject.regex;

2(ES6)

それを必要とする人には...

このスレッドで@Koenの答えを完了するには、普及している構文を使用して動的変数を削除したい場合は、次のようにします:

const key = 'a';

const { [key]: foo, ...rest } = { a: 1, b: 2, c: 3 };

console.log(rest); // { b: 2, c: 3 }

* fooは値がa(1)の新しい変数になります。


更新
オブジェクトからプロパティを削除する一般的な方法はほとんどありません。
各自が賛否両論を持っています(このパフォーマンス比較を確認してください):

developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
読み込み可能で短く、ただし、パフォーマンスが最適化されていないため多数のオブジェクトで操作している場合は最適ではない場合があります。

delete obj[key];


Reassignment
2倍以上高速ですdeleteが、プロパティは削除され、反復処理が可能です。

obj[key] = null;
obj[key] = false;
obj[key] = undefined;


スプレッド演算子
このES6演算子を使用すると、既存のオブジェクトに変更を加えることなく、プロパティを除いた新しいオブジェクトを返すことができます。欠点は、上記のパフォーマンスが悪化していて、一度に多数のプロパティを削除する必要がある場合に使用するように提案されていないことです。

{ [key]: val, ...rest } = obj;

オペレータの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が必ずしも適切でobj[prop] = undefined可能性があります。 delete obj[prop]objからdelete obj[prop]し、メモリから消去しますが、 obj[prop] = undefinedpropの値をobj[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スロットは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倍のすべての行をチェックすることをお勧めします。それは有益なので危険です。


Update 2018-07-21:長い間、私はこの答えに恥ずかしい思いをしていましたので、少し触れてみてください。 この解答の不必要に長く複雑な部分の読解を促進するためのちょっとした解説、説明、書式設定。

短いバージョン

質問に対する実際の答え

他の人が言ったように、あなたはdeleteを使用deleteことができます。

obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined

配列相当

配列からはdeleteしないでdelete 。 代わりにArray.prototype.spliceを使用してください。

arr // [1,2,3,4,5]
arr.splice(3,1); // 4
arr // [1,2,3,5]

長いバージョン

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は限りません。 値は上書きされますが、メモリは再割り当てされません。 つまり、 array[4]array[3]再配置されません。 Array.prototype.unshiftとは対照的Array.prototype.unshift 。これは、配列の先頭に要素を挿入し、すべてをシフトします( array[0]array[1]などになります)

正直なところ、 undefinedよりもむしろnull設定することを除いて - 正当な理由で奇妙です - この動作驚くべきではありません .typeofのような単項演算子であり、言語に固執され、それが使用されているオブジェクトのタイプについて、 ArrayObjectサブクラスであり、 Arrayを操作するために特別に設計されたメソッドを持っています。 そのため、配列を再シフトするために特別なケースを作成する必要はありません。不要な作業で処理が遅くなるからです。 振り返ってみると、私の期待は非現実的でした。

もちろん、それ私を驚かせた。 なぜなら、「ヌル・ゴミ」に対する私の十字軍を正当化するためにこれを書いたからです。

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

これはnullを取り除くためのひどい正当な理由です。nullは、不適切に使用された場合にのみ危険であり、 "精度"とは何の関係もありません。 配列からdeleteしてはいけない本当の理由は、ガーベッジがいっぱいで面倒なデータ構造を残しておくと、うんざりしてバグが発生しやすいからです。

以下に続くのは、かなり長い時間がかかった人為的なシナリオなので、必要に応じてThe The Solutionのセクションに飛ぶことができます。 私がこのセクションを残す唯一の理由は、おそらく誰かがそれが面白いと思うと思うからだ。私は「面白い」答えを投稿し、その後「面白い」答えを投稿する「その人」になりたくないと思うからだ。 。

...それは馬鹿だ、私は知っている。

考案され長年に亘るPDP-11のシナリオ

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

さて、1960年代のUNIXからPDP-11ミニコンピュータを実行しているこの1人のユーザーの要望でメモリを節約しようとしており、独自の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.splice() 。 あなたは次のようなものを書くことができます:

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

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

Array.prototype.spliceとArray.prototype.slice

これらの2つの同様の名前の関数の違いを指摘することが重要であると感じています。なぜなら、これらは両方とも非常に便利なためです。

Array.prototype.splice(start、n)

.splice()は配列を変更し、削除されたインデックスを返します。 配列はインデックスstartn要素からスライスされ、スライスされます。 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]

Array.prototype.slice(start、end)

.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で指定されたインデックスは単にスライスから除外されます。 カッコで囲まれたインデックスは、何がスライスされるかを示します。 どちらの方法でも、その動作は直感的ではなく、off-by-oneエラーの公平な共有に.splice()ため、 .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;
}

実際には、配列が本当に配列であるかどうかを知る組み込みの方法があります。これはECMAScript 5(2009年12月Array.isArray()で導入されたArray.isArray() )です。 私はオブジェクトから配列を伝えること、私よりも優れた解決策があるかどうかを調べること、または存在しない場合には私を追加することを質問する質問があるかどうかを見ながら探しました。 したがって、ECMA 5より前のバージョンのJavaScriptを使用している場合は、ポリフィルがあります。 しかし、私はis_array()関数を使用しないことを強くお勧めします。古いバージョンのJavaScriptをサポートし続けるということは、それを実装する古いブラウザをサポートし続けることです。つまり、安全でないソフトウェアの使用を奨励し、 Array.isArray()使用してください。 letconst使用letます。 言語に追加される新機能を使用します。 ベンダープレフィックス使用しないでください 。 あなたのウェブサイトからそのIE polyfillのいたずらを削除してください。 そのXHTML <!CDATA[[...でも、2014年にHTML5に移行しました。早く誰もが古い/難解なブラウザをサポートしなくなると、ブラウザのベンダーは実際にWeb標準に従い、新しいテクノロジを使用すると、より安全なWebに移行することができます。


ここでは良い答えがたくさんありますが、JavaScriptでプロパティを削除するためにdeleteを使用する場合、エラーを防ぐためにそのプロパティが存在するかどうか最初にチェックすることが賢明なことがあります。

例えば

var obj = {"property":"value", "property2":"value"};

if (obj && obj.hasOwnProperty("property2")) {
  delete obj.property2;
} else {
  //error handling
}

JavaScriptの動的な性質のため、プロパティが存在するかどうかわからない場合がよくあります。&&の前にobjが存在するかどうかをチェックすることで、未定義のオブジェクトに対してhasOwnProperty()関数を呼び出すためにエラーが発生しないようにします。

これはあなたの特定のユースケースに追加されていない場合は申し訳ありませんが、私はこれがオブジェクトとそのプロパティを管理するときに適応する良い設計であると信じています。


deleteメソッドを使用するのが最善の方法です。MDNの説明に従って、delete演算子はオブジェクトからプロパティを削除します。だからあなたは単に書くことができます:

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

delete演算子は、オブジェクトから特定のプロパティを削除します。削除が成功するとtrueを返し、そうでない場合はfalseを返します。ただし、次のシナリオを検討することが重要です。

  • 削除しようとしているプロパティが存在しない場合、deleteは効果を持たずtrueを返します

  • 同じ名前のプロパティがオブジェクトのプロトタイプチェーン上に存在する場合、削除後、オブジェクトはプロトタイプチェーンのプロパティを使用します(つまり、deleteは自分のプロパティにのみ影響します)。

  • varで宣言されたプロパティは、グローバルスコープまたは関数のスコープから削除することはできません。

  • したがって、deleteは、グローバルスコープ内の関数を削除することはできません(これは、関数定義または関数(式)の一部であるかどうかにかかわらず)。

  • オブジェクトの一部である関数(
    グローバルスコープを除く)はdeleteで削除できます。

  • letまたはconstで宣言されたプロパティは、定義されているスコープから削除することはできません。構成できないプロパティは削除できません。これには、Object.defineProperty()などのメソッドを使用して構成できないように作成されたMath、Array、Object、およびPropertiesなどの組み込みオブジェクトのプロパティが含まれます。

次のスニペットは別の簡単な例を示しています:

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

もっと多くの例を見ると、以下のリンクをご覧ください:

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


deleteキーワードを使用して、オブジェクトの任意のプロパティを削除することができます。

例えば:

var obj = {key1:"val1",key2:"val2",key3:"val3"}

プロパティを削除するにはkey1、次のdeleteようなキーワードを使用します。

delete obj.key1

あるいは、配列のような表記を使うこともできます:

delete obj[key1]

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


ECMAScript 2015(またはES6)にはReflectオブジェクトが組み込まれていました。ターゲットオブジェクトとプロパティキーをパラメータとしてReflect.deleteProperty()関数を呼び出して、オブジェクトプロパティを削除することができます。

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関数(およびdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/…)はfalse、そのプロパティのいずれかを削除しようとしたときに戻ります。プロパティが設定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

次の方法を試してください。Objectプロパティ値をに割り当てますundefined。次にstringifyオブジェクトとparse

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

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

console.log(myObject);


ダンの「削除」の主張は非常に遅く、投稿したベンチマークは疑問だった。そこで私は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回のループサイクルで複数の「削除」操作を意図的に実行したことに注意してください。


また、 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()も同様の方法で使用できます。





object-properties