---
type: how-to
language: javascript
slug: object/pick
title: "オブジェクトから必要な鍵だけ取り出す・除く"
title_tag: "JavaScript オブジェクトの鍵を絞る — pick と omit"
summary: >
  entries() で配列にして絞り、fromEntries() で戻します。分割代入の残余で除く短い書き方、
  無い鍵を渡したとき、入れ子が共有されたままになる点までを実行して確かめます。
description: >
  パスワードなど外に出したくない鍵を除く定石です。分割代入の残余で書く短い形と、
  鍵を変数で渡せる形の使い分け、複製が1段しか効かない点まで実行して示します。
status: published
difficulty: 2
minutes: 7

versions:
  verified: "Node 22.22.3"
  since: "ES2019"
  deprecated: null
  removed: null

sources:
  - title: "Object.fromEntries — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-object.fromentries"
  - title: "Destructuring Binding Patterns — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-destructuring-binding-patterns"
  - title: "分割代入 — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring"

terms: [残余プロパティ, 往復変換, 浅いコピー]

links:
  related:
    - javascript/learn/object/iterate
    - javascript/how-to/object/merge
    - javascript/reference/object/keys

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

## 答え

**除くだけなら、分割代入の残余がいちばん短い**です。

```js run
const user = { id: 1, name: 'あ', secret: 'x' };

const { secret, ...rest } = user;

console.log(rest);
console.log(user);
```
```output
{ id: 1, name: 'あ' }
{ id: 1, name: 'あ', secret: 'x' }
```

`...rest` が[key:残り全部]を受け取ります。元のオブジェクトは変わりません。

**鍵を変数で渡したいなら**、`entries()` で絞ります。

```js run
function pick(source, keys) {
  return Object.fromEntries(
    Object.entries(source).filter(([key]) => keys.includes(key)),
  );
}

const user = { id: 1, name: 'あ', secret: 'x' };

console.log(pick(user, ['id', 'name']));
```
```output
{ id: 1, name: 'あ' }
```

## 除く側も同じ形

```js run
function omit(source, keys) {
  return Object.fromEntries(
    Object.entries(source).filter(([key]) => !keys.includes(key)),
  );
}

const user = { id: 1, name: 'あ', secret: 'x' };

console.log(omit(user, ['secret']));
```
```output
{ id: 1, name: 'あ' }
```

`!` を付けるだけです。**「配列にして、絞って、戻す」形はここでも同じ**です。
→ [オブジェクトを回す・変換する](/ja/javascript/learn/object/iterate/)

## 無い鍵を渡しても落ちない

```js run
function pick(source, keys) {
  return Object.fromEntries(
    Object.entries(source).filter(([key]) => keys.includes(key)),
  );
}

const user = { id: 1, name: 'あ' };

console.log(pick(user, ['nothing']));
console.log(pick(user, []));
```
```output
{}
{}
```

**空のオブジェクトが返ります。** 場合分けは要りません。

[bad:ただし「無い鍵を指定した」ことにも気づけません。]
鍵の名前を打ち間違えると、静かに空になります。

## 使い分け

| したいこと | 書き方 |
|---|---|
| 決まった鍵を1〜2個除く | **分割代入の残余** |
| 鍵を配列（変数）で渡す | `entries()` + `filter()` |
| 決まった鍵だけ残す（少数） | `const { id, name } = user` して組み直す |

分割代入は**書いた鍵の名前が変数になる**ので、
[bad:除きたい鍵が多いと、使わない変数が並びます]。

```js bad
const { secret, token, password, ...rest } = user;
```

3つとも使いません。**この形になったら `omit()` に切り替えてください。**

## いちばんの使い道：外に出さない

```js run
function omit(source, keys) {
  return Object.fromEntries(
    Object.entries(source).filter(([key]) => !keys.includes(key)),
  );
}

const user = { id: 1, name: 'あ', passwordHash: 'xxx', token: 'yyy' };

console.log(omit(user, ['passwordHash', 'token']));
```
```output
{ id: 1, name: 'あ' }
```

> **「除く」より「選ぶ」ほうが安全です。**
> `omit()` は、あとから鍵が増えたときに**その新しい鍵が漏れます。**
> 外へ返すデータは `pick()` で**残すものを書く**ほうが事故が起きません。

```js run
function pick(source, keys) {
  return Object.fromEntries(
    Object.entries(source).filter(([key]) => keys.includes(key)),
  );
}

const user = { id: 1, name: 'あ', passwordHash: 'xxx', newSecret: 'zzz' };

console.log(pick(user, ['id', 'name']));
```
```output
{ id: 1, name: 'あ' }
```

**`newSecret` が増えても漏れません。**

## 並び順は元のまま

```js run
function pick(source, keys) {
  return Object.fromEntries(
    Object.entries(source).filter(([key]) => keys.includes(key)),
  );
}

const user = { id: 1, name: 'あ', role: 'admin' };

console.log(Object.keys(pick(user, ['name', 'id'])));
```
```output
[ 'id', 'name' ]
```

**渡した順（`name`, `id`）ではなく、元の順（`id`, `name`）になります。**
`entries()` が元のオブジェクトを走査しているからです。

順番も指定したいなら、鍵の側から組み立ててください。

```js run
function pickInOrder(source, keys) {
  return Object.fromEntries(
    keys.filter((key) => Object.hasOwn(source, key)).map((key) => [key, source[key]]),
  );
}

const user = { id: 1, name: 'あ', role: 'admin' };

console.log(Object.keys(pickInOrder(user, ['name', 'id'])));
```
```output
[ 'name', 'id' ]
```

## 配列に対して使う

一覧を返すときは `map()` と組み合わせます。

```js run
function pick(source, keys) {
  return Object.fromEntries(
    Object.entries(source).filter(([key]) => keys.includes(key)),
  );
}

const list = [
  { id: 1, name: 'あ', secret: 'x' },
  { id: 2, name: 'い', secret: 'y' },
];

console.log(list.map((user) => pick(user, ['id', 'name'])));
```
```output
[ { id: 1, name: 'あ' }, { id: 2, name: 'い' } ]
```

## よくある間違い

### 手で組み立てて、無い鍵を作ってしまう

```js bad
const user = { id: 1, name: 'あ' };
const picked = {};

for (const key of ['id', 'nothing']) {
  picked[key] = user[key];
}

console.log(picked);
console.log('nothing' in picked);
```
```output
{ id: 1, nothing: undefined }
true
```

**元に無い鍵が、値 `undefined` で増えています。**
`in` で調べると `true` になるので、[bad:「あるが空」と誤解されます]。

`Object.hasOwn()` で確かめてから入れるか、`entries()` で絞る形にしてください。
→ [オブジェクトの基本](/ja/javascript/learn/object/basics/)

## 複製されるのは1段だけ

```js run
function pick(source, keys) {
  return Object.fromEntries(
    Object.entries(source).filter(([key]) => keys.includes(key)),
  );
}

const user = { id: 1, profile: { city: '東京' } };
const picked = pick(user, ['profile']);

picked.profile.city = '大阪';

console.log(user.profile.city);
```
```output
大阪
```

**取り出した中身は、元と同じオブジェクトを指しています。**
書き換えると元も変わります。

深く複製したいなら `structuredClone()` を使ってください。
→ [オブジェクトを結合する](/ja/javascript/how-to/object/merge/)

## まとめ

- 除くだけなら**分割代入の残余**（`const { secret, ...rest } = user`）
- 鍵を変数で渡すなら `entries()` + `filter()` + `fromEntries()`
- 無い鍵を渡しても落ちない。**打ち間違いにも気づけない**
- **外へ返すなら「選ぶ」。** 「除く」は鍵が増えたときに漏れる
- 複製されるのは[num:1]段だけ。入れ子は元と共有される
