1つのキー以外のJavaScriptオブジェクトを複製するにはどうすればよいですか?


308

フラットなJSオブジェクトがあります:

{a: 1, b: 2, c: 3, ..., z:26}

1つの要素を除いてオブジェクトを複製したい:

{a: 1, c: 3, ..., z:26}

これを行う最も簡単な方法は何ですか(可能であればes6 / 7を使用することをお勧めします)?


元のオブジェクトを変更せずに:JSON.parse(JSON.stringify({... obj、 'key2':undefined}))
infinity1975

回答:


441

あなたが使用している場合はバベルを、あなたは次の構文を使用することができます変数bにxからコピープロパティbとその後、変数yに残りのプロパティをコピーします

let x = {a: 1, b: 2, c: 3, z:26};
let {b, ...y} = x;

そしてそれは次のように変換されます:

"use strict";

function _objectWithoutProperties(obj, keys) {
  var target = {};
  for (var i in obj) {
    if (keys.indexOf(i) >= 0) continue;
    if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
    target[i] = obj[i];
  }
  return target;
}

var x = { a: 1, b: 2, c: 3, z: 26 };
var b = x.b;

var y = _objectWithoutProperties(x, ["b"]);

58
未使用の変数のコードをlintすると、「未使用の変数 'b'」になります。警告。
ロス・アレン

1
どのようにでしょう構文を見て、あなたが持っていた場合let x = [{a: 1, b: 2, c: 3, z:26}, {a: 5, b: 6, c: 7, z:455}];
ke3pup

14
@RossAllen ignoreRestSiblingsv3.15.0(2017年2月3日)で追加されたオプションがあります。参照:c59a0baコミット
イリヤPalkin

4
@IlyaPalkin興味深い。ただしb、スコープ内にあるという事実を変更しないため、少し怠惰な感じがします。
ロス・アレン

2
モジュールのビルドに失敗した場合:SyntaxError:予期しないトークンの場合、おそらくbabelレストスプレッド変換プラグインを追加する必要があります。babeljs.io/docs/plugins/transform-object-rest-spreadを参照してください
jsaven

133
var clone = Object.assign({}, {a: 1, b: 2, c: 3});
delete clone.b;

または、プロパティを未定義として受け入れる場合:

var clone = Object.assign({}, {a: 1, b: 2, c: 3}, {b: undefined});

7
プロパティを削除するだけで、明確で簡単な方法で削除できます。
sshow 2017

24
削除の注意点は、それが不変の操作ではないということです。
Javid Jamae 2017

1
これが鍵となる
Fareed Alnamrouti 2017年

1
私のコメントは、彼が回答を編集して削除ステートメントを追加する前に書かれました
Fareed Alnamrouti '10

これは私が探していたものとまったく同じですが、少し異なる方法で少し実装されています。var cake = {... currentCake、requestorId:undefined};
アベリト

73

イリヤパルキンの答えに追加するには:キーを動的に削除することもできます。

const x = {a: 1, b: 2, c: 3, z:26};

const objectWithoutKey = (object, key) => {
  const {[key]: deletedKey, ...otherKeys} = object;
  return otherKeys;
}

console.log(objectWithoutKey(x, 'b')); // {a: 1, c: 3, z:26}
console.log(x); // {a: 1, b: 2, c: 3, z:26};

Babel REPLのデモ

ソース:


3
これは素晴らしい構文です。
Hinrich

2
これは素晴らしいですが、未使用の変数deletedKeyを回避する方法はありますか?それが問題を引き起こしているわけではありませんが、JSHintは不平を言っています。
ジョンソンウォン

6
@JohnsonWong _使用するつもりのない変数に許可されている使用についてはどうですか?
Ryan H.

var b = {a:44, b:7, c:1}; let {['a']:z, ...others} = b; console.log(z , others ); // logs: 44, {b:7, c:1}
ジムモント2018

70

ES6を使用できない場合は、lodashまたはを使用できますunderscore

_.omit(x, 'b')

またはramda

R.omit('b', x)

6
ここでomitを使用する方が論理的ではないでしょうか? _.omit(x, 'b')
tibalt 2017年

@tibaltに感謝します。それで答えを更新しました。
Noel Llevares 2017年

削除はより簡潔です.lodash、underscore、またはramdaを使用することは、すでにそれらを使用および認識しているプロジェクトにのみ関連します。それ以外の場合、2018年以降、これはますます重要ではなくなります。
ジムモント2018

1
@jimmont deleteは他の回答ですでに言及されています。重複して答える必要はありませんね。もちろん、これはlodashまたはramdaをすでに使用しているユーザーにのみ関係します。また、この回答に記載されているように、ES5以前で立ち往生している人にのみ関連しています。
Noel Llevares

@dashmug私の以前のコメントは、この回答で表されているアプローチを使用することを選択するときに注意すべき、あなたの回答ではなく、アプローチの批判でした。私が答えを読んでいるなら、この情報が欲しいと思います。それが私のコメントを追加して言及する理由ですdelete
ジムモント2018

63

私はこのESNextワンライナーを使用します

const obj = { a: 1, b: 2, c: 3, d: 4 }
const clone = (({ b, c, ...o }) => o)(obj) // remove b and c
console.log(clone)


汎用機能が必要な場合:

function omit(obj, props) {
  props = props instanceof Array ? props : [props]
  return eval(`(({${props.join(',')}, ...o}) => o)(obj)`)
}

// usage
const obj = { a: 1, b: 2, c: 3, d: 4 }
const clone = omit(obj, ['b', 'c'])
console.log(clone)


9
代わりに、アレイ内のラッピングのとmapあなたが行うことができます:(({b, c, ...others}) => ({...others}))(obj)
bucabay

@bucabay:素晴らしい!それがたくさんの最良の答えです!標準に準拠し、Nodeなどで完全に機能します。回答として送信する必要があります。
david.pfx

3
Fantastic answer mate .. <3
Ajithkumar S '

5
@totymedli:私ではない。標準のES6の一部である構文形式を、読みやすさの理由から、いつでも魔法の関数に適用します。
david.pfx

1
鮮やかさ。それで全部です。
darksoulsong

22

そのための簡単なヘルパー関数を書くことができます。Lodashは、同じ名前を持つ同様の機能を持っていますオミットを

function omit(obj, omitKey) {
  return Object.keys(obj).reduce((result, key) => {
    if(key !== omitKey) {
       result[key] = obj[key];
    }
    return result;
  }, {});
}

omit({a: 1, b: 2, c: 3}, 'c')  // {a: 1, b: 2}

また、Object.assignよりも高速であり、次に削除することに注意してください:http ://jsperf.com/omit-key


11

多分このようなもの:

var copy = Object.assign({}, {a: 1, b: 2, c: 3})
delete copy.c;

これで十分ですか?それともc実際にコピーできないのですか?


11

オブジェクトの破壊を使用する

const omit = (prop, { [prop]: _, ...rest }) => rest;
const obj = { a: 1, b: 2, c: 3 };
const objWithoutA = omit('a', obj);
console.log(objWithoutA); // {b: 2, c: 3}


素晴らしい解決策!
Denys Mikhalenko、

2
この解決策はJSLintの「未使用の変数」警告を防ぐことを意図していると思います。残念ながら、使用_してもESLintの問題は解決しません...
bert bruynooghe

6

オブジェクトをコピーしてからプロパティを削除しようとすると、参照の問題が発生するようです。JavaScriptが新しい値を作成するように、どこかでプリミティブ変数を割り当てる必要があります。

私が使った簡単なトリック(恐ろしいかもしれません)はこれでした

var obj = {"key1":"value1","key2":"value2","key3":"value3"};

// assign it as a new variable for javascript to cache
var copy = JSON.stringify(obj);
// reconstitute as an object
copy = JSON.parse(copy);
// now you can safely run delete on the copy with completely new values
delete copy.key2

console.log(obj)
// output: {key1: "value1", key2: "value2", key3: "value3"}
console.log(copy)
// output: {key1: "value1", key3: "value3"}

本当に好きです。できたJSON.parse(JSON.stringify(Object.assign({}, obj, { key2: undefined })));。削除する必要はありません。偽の値が必要です。
チャド

6

ここでは、まだ言及されていないと思われる動的キーを省略するオプションを示します。

const obj = { 1: 1, 2: 2, 3: 3, 4: 4 };
const removeMe = 1;

const { [removeMe]: removedKey, ...newObj } = obj;

removeMeとしてエイリアスされremovedKey、無視されます。newObjになり{ 2: 2, 3: 3, 4: 4 }ます。削除されたキーは存在せず、値がに設定されundefinedただけではないことに注意してください。


素晴らしい解決策。私は同様のユースケースを持っています(レデューサーの動的キー)。
ericgio

4

最も簡単な方法

const allAlphabets = {a: 1, b: 2, c: 3, ..., z:26};
const { b, ...allExceptOne } = allAlphabets;
console.log(allExceptOne);   // {a: 1, c: 3, ..., z:26}

3

ロダッシュ省略

let source = //{a: 1, b: 2, c: 3, ..., z:26}
let copySansProperty = _.omit(source, 'b');
// {a: 1, c: 3, ..., z:26}

はい、ロダッシュはエレガントなオプションですが、私はバニラES6で同じことを達成しようとしていました
andreasonny83

3

スプレッド演算子を使用してこれを行うこともできます

const source = { a: 1, b: 2, c: 3, z: 26 }
const copy = { ...source, ...{ b: undefined } } // { a: 1, c: 3, z: 26 }

2
とても気の利いたようです。ただし、これはキーを未定義のままにしますcopy
カノ2018

そこに存在する唯一のキーがある場合、未定義のキーを削除できます
Victor

1
コピーで追加の拡散を行った理由がわからないため、const copy = { ...source, b: undefined } 完全に同じに 要約されます。
bert bruynooghe

3

上記の構造化を使用した解決策は、使用された変数があるという事実に悩まされています。これを使用している場合、ESLintから不満が生じる可能性があります。

だからここに私の解決策があります:

const src = { a: 1, b: 2 }
const result = Object.keys(src)
  .reduce((acc, k) => k === 'b' ? acc : { ...acc, [k]: src[k] }, {})

ほとんどのプラットフォーム(Babelを使用しない限りIEを除く)では、次のこともできます。

const src = { a: 1, b: 2 }
const result = Object.fromEntries(
  Object.entries(src).filter(k => k !== 'b'))


2

巨大な変数を扱っている場合は、それをコピーしてから削除するのは効率的ではないため、避けたいです。

hasOwnPropertyチェックを含む単純なforループが機能し、将来のニーズにはるかに適応できます。

for(var key in someObject) {
        if(someObject.hasOwnProperty(key) && key != 'undesiredkey') {
                copyOfObject[key] = someObject[key];
        }
}

1
スプレッド演算子ソリューションは、はるかに優れた構文でまったく同じことを行います。
david.pfx

2

これはどうですか?私はこのパターンを見つけたことはありませんが、追加のオブジェクトを作成する必要なしに、1つ以上のプロパティを除外しようとしていました。これで問題は解決したようですが、目に見えない副作用があります。確かに非常に読みやすいではありません。

const postData = {
   token: 'secret-token',
   publicKey: 'public is safe',
   somethingElse: true,
};

const a = {
   ...(({token, ...rest} = postData) => (rest))(),
}

/**
a: {
   publicKey: 'public is safe',
   somethingElse: true,
}
*/

2

私のReduxレデューサーからの例として、私はこの方法でそれを達成しました:

 const clone = { ...state };
 delete clone[action.id];
 return clone;

言い換えると:

const clone = { ...originalObject } // note: original object is not altered
delete clone[unwantedKey]           // or use clone.unwantedKey or any other applicable syntax
return clone                        // the original object without the unwanted key

3年前に受け入れられた回答と比較して、多くの余分な作業のようです(そして、両方のオプションは、多くのブラウザーでへのトランスパイルに依存しています)。
-carpiediem

私は同様のユースケース(レデューサー)を持っているので、変更なしで動的キーをサポートする素晴らしい方法を思いつきました。基本的に:const { [removeMe]: removedKey, ...newObj } = obj;-この質問に対する私の回答を参照してください。
goldins '10

1

私は最近これを非常に簡単な方法で行いました:

const obj = {a: 1, b: 2, ..., z:26};

スプレッド演算子を使用して、不要なプロパティを分離します。

const {b, ...rest} = obj;

...そして「残りの」部分だけを取るためのobject.assign

const newObj = Object.assign({}, {...rest});

3
restはすでに新しいオブジェクトです。最後の行は必要ありません。さらに、これは承認されたソリューションと同じです。
carpiediem

0
const x = {obj1: 1, pass: 2, obj2: 3, obj3:26};

const objectWithoutKey = (object, key) => {
  const {[key]: deletedKey, ...otherKeys} = object;
  return otherKeys;
}

console.log(objectWithoutKey(x, 'pass'));

1
このコードは質問に対する解決策を提供するかもしれませんが、それがなぜ/どのように機能するかに関してコンテキストを追加する方が良いです。これは、将来のユーザーが学習し、その知識を自分のコードに適用するのに役立ちます。また、コードが説明されている場合は、賛成票の形でユーザーから肯定的なフィードバックを受ける可能性があります。
borchvm
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.