JavaScript のオブジェクト操作まとめ:Object.keys/entries/values の使い方

JavaScript でオブジェクトの操作は日常的な作業です。Object.keys、Object.entries、Object.values の 3 つのメソッドを使いこなすことで、より効率的なコード記述が可能になります。
特に、配列操作のように map や filter を使いたい場面や、オブジェクトの構造を変更したい場面で、これらのメソッドは威力を発揮します。ES2017 で標準化されたこれらの機能を使って、モダンな JavaScript 開発をスムーズに進めましょう。
背景
オブジェクト操作の重要性
JavaScript において、オブジェクトはデータ構造の基本となる重要な要素です。API からのレスポンス、設定オブジェクト、ユーザーデータなど、あらゆる場面でオブジェクトを扱う必要があります。
しかし、配列と異なり、オブジェクトには map や filter のような便利なメソッドが存在しませんでした。そのため、開発者はオブジェクトの処理に for...in ループや Object.getOwnPropertyNames() などの複雑な手法を使わざるを得なかったのです。
以下の図は、JavaScript におけるオブジェクト操作の重要性を示しています。
mermaidflowchart TD
data[データ取得] --> api[API レスポンス]
data --> form[フォーム入力]
data --> config[設定ファイル]
api --> obj[JavaScript オブジェクト]
form --> obj
config --> obj
obj --> process[データ処理]
process --> display[画面表示]
process --> validation[バリデーション]
process --> storage[データ保存]
図で理解できる要点:
- あらゆるデータソースがオブジェクト形式で JavaScript に取り込まれます
- オブジェクト操作は JavaScript 開発の中核的な作業です
- 効率的なオブジェクト操作により、コード品質と開発速度が向上します
ES2017 で追加された便利なメソッド群
ES2017(ES8)では、オブジェクト操作を大幅に簡素化する 3 つのメソッドが追加されました。
メソッド | 戻り値 | 用途 |
---|---|---|
Object.keys() | キーの配列 | オブジェクトのプロパティ名を取得 |
Object.values() | 値の配列 | オブジェクトの値のみを取得 |
Object.entries() | [キー, 値] ペアの配列 | キーと値を同時に取得 |
これらのメソッドは、関数型プログラミングのパラダイムを JavaScript に持ち込み、より宣言的で読みやすいコードの記述を可能にしました。
従来の for...in ループとの違い
従来の for...in ループと新しいメソッド群の違いを理解することで、適切な使い分けができるようになります。
for...in ループの問題点を示すコード例:
javascriptconst user = { name: 'Alice', age: 30, city: 'Tokyo' };
// 従来の方法
const keys = [];
for (let key in user) {
if (user.hasOwnProperty(key)) {
keys.push(key);
}
}
console.log(keys); // ['name', 'age', 'city']
hasOwnProperty() チェックが必要で、コードが冗長になってしまいます。
ES2017 のメソッドを使用した場合:
javascriptconst user = { name: 'Alice', age: 30, city: 'Tokyo' };
// ES2017 の方法
const keys = Object.keys(user);
console.log(keys); // ['name', 'age', 'city']
シンプルで直感的なコードになり、意図も明確に伝わります。
課題
オブジェクトの各要素にアクセスする際の問題点
JavaScript 開発において、オブジェクト操作で頻繁に発生する課題があります。
配列のような操作ができない問題:
javascriptconst products = {
laptop: 1200,
mouse: 30,
keyboard: 80,
};
// 配列なら簡単にできること
// products.map(price => price * 1.1) // エラー!
オブジェクトには map メソッドが存在しないため、値の変換処理が困難でした。
キーと値の同時取得が複雑な問題:
javascriptconst settings = {
theme: 'dark',
language: 'ja',
notifications: true,
};
// 従来の方法:キーと値を同時に扱うのが煩雑
for (let key in settings) {
console.log(`${key}: ${settings[key]}`);
}
パフォーマンスと可読性の両立
効率的なオブジェクト操作では、パフォーマンスと可読性の両方を考慮する必要があります。
パフォーマンスの課題:
javascriptconst largeObject = {
/* 数千のプロパティ */
};
// 非効率なアプローチ
Object.keys(largeObject).forEach((key) => {
const value = largeObject[key]; // 毎回プロパティアクセス
// 処理...
});
可読性の課題:
javascript// 意図が伝わりにくいコード
const result = {};
for (let key in data) {
if (data[key] > threshold) {
result[key] = data[key] * multiplier;
}
}
型安全性の確保
TypeScript を使用する場合、オブジェクト操作で型安全性を保つことが重要です。
型安全性の問題例:
typescriptinterface User {
name: string;
age: number;
email: string;
}
const user: User = {
name: 'Bob',
age: 25,
email: 'bob@example.com',
};
// Object.keys() の戻り値は string[] なので型情報が失われる
Object.keys(user).forEach((key) => {
// TypeScript エラー:key が User のキーであることが保証されない
console.log(user[key]);
});
解決策
Object.keys() の基本的な使い方
Object.keys() は、オブジェクトの列挙可能なプロパティ名を配列として返します。
基本的な使用方法:
javascriptconst person = {
firstName: 'John',
lastName: 'Doe',
age: 30,
};
const keys = Object.keys(person);
console.log(keys); // ['firstName', 'lastName', 'age']
配列メソッドとの組み合わせ:
javascriptconst config = {
apiUrl: 'https://api.example.com',
timeout: 5000,
retryCount: 3,
};
// 特定の条件に合うキーのフィルタリング
const timeoutKeys = Object.keys(config).filter((key) =>
key.includes('timeout')
);
console.log(timeoutKeys); // ['timeout']
動的なプロパティアクセス:
javascriptconst data = {
user_name: 'alice',
user_email: 'alice@example.com',
user_age: 28,
};
// キーの変換処理
const transformedKeys = Object.keys(data).map((key) =>
key.replace('user_', '')
);
console.log(transformedKeys); // ['name', 'email', 'age']
Object.entries() によるキー・値のペア操作
Object.entries() は、オブジェクトのキーと値のペアを [key, value] 形式の配列として返します。
基本的な使用方法:
javascriptconst scores = {
math: 85,
english: 92,
science: 78,
};
const entries = Object.entries(scores);
console.log(entries);
// [['math', 85], ['english', 92], ['science', 78]]
キーと値の同時処理:
javascriptconst prices = {
apple: 100,
banana: 80,
orange: 120,
};
// 税込み価格の計算
Object.entries(prices).forEach(([item, price]) => {
const taxIncluded = Math.floor(price * 1.1);
console.log(`${item}: ${taxIncluded}円`);
});
オブジェクトの変換処理:
javascriptconst userData = {
name: 'Charlie',
age: 35,
city: 'Osaka',
};
// 新しいオブジェクトの生成
const upperCaseData = Object.fromEntries(
Object.entries(userData).map(([key, value]) => [
key.toUpperCase(),
typeof value === 'string' ? value.toUpperCase() : value,
])
);
console.log(upperCaseData);
// { NAME: 'CHARLIE', AGE: 35, CITY: 'OSAKA' }
Object.values() での値の取得方法
Object.values() は、オブジェクトの値のみを配列として返します。
基本的な使用方法:
javascriptconst inventory = {
laptops: 15,
mice: 200,
keyboards: 50,
};
const quantities = Object.values(inventory);
console.log(quantities); // [15, 200, 50]
値に対する集計処理:
javascriptconst sales = {
january: 150000,
february: 180000,
march: 220000,
};
// 合計売上の計算
const totalSales = Object.values(sales).reduce(
(sum, amount) => sum + amount,
0
);
console.log(`総売上: ${totalSales}円`); // 総売上: 550000円
値の検証処理:
javascriptconst formData = {
username: 'testuser',
password: 'securepass123',
email: 'test@example.com',
};
// すべての値が入力されているかチェック
const allFieldsFilled = Object.values(formData).every(
(value) => value && value.length > 0
);
console.log(`入力完了: ${allFieldsFilled}`); // 入力完了: true
3 つのメソッドの使い分け指針
適切なメソッドの選択により、コードの意図を明確に表現できます。
以下の図は、3 つのメソッドの使い分けを示しています。
mermaidflowchart TD
start["オブジェクト操作の必要性"] --> question{"何が必要?"};
question -->|キーのみ| keys["Object.keys()"];
question -->|値のみ| values["Object.values()"];
question -->|キーと値の両方| entries["Object.entries()"];
keys --> keys_use["プロパティ名の操作<br/>動的アクセス<br/>キーの変換"];
values --> values_use["値の集計<br/>検証処理<br/>配列操作"];
entries --> entries_use["オブジェクト変換<br/>ペア処理<br/>新オブジェクト生成"];
図で理解できる要点:
- キーのみが必要な場合は Object.keys() を使用
- 値のみで十分な場合は Object.values() を選択
- キーと値の両方が必要な場合は Object.entries() が最適
使い分けの実例:
javascriptconst userStats = {
posts: 50,
followers: 120,
following: 80,
};
// キーのみが必要:メニュー項目の生成
const menuItems = Object.keys(userStats);
// 値のみが必要:統計情報の合計
const totalActivity = Object.values(userStats).reduce(
(sum, count) => sum + count,
0
);
// キーと値の両方が必要:表示用フォーマット
const displayStats = Object.entries(userStats)
.map(([key, value]) => `${key}: ${value}`)
.join(', ');
具体例
実際のデータ処理での活用
実際の開発現場でよくある、API レスポンスの処理例をご紹介します。
API から取得したユーザーデータの処理:
javascript// API レスポンス(模擬データ)
const apiResponse = {
user_id: 12345,
user_name: 'developer',
user_email: 'dev@example.com',
user_status: 'active',
last_login: '2023-12-01',
};
Object.keys() を使用したキーの正規化:
javascript// プレフィックスの削除
const normalizedUser = {};
Object.keys(apiResponse).forEach((key) => {
const newKey = key.replace('user_', '');
normalizedUser[newKey] = apiResponse[key];
});
console.log(normalizedUser);
// { id: 12345, name: 'developer', email: 'dev@example.com', status: 'active', last_login: '2023-12-01' }
Object.entries() を使用したより効率的な変換:
javascriptconst transformedUser = Object.fromEntries(
Object.entries(apiResponse).map(([key, value]) => [
key.replace('user_', ''),
value,
])
);
データの検証処理:
javascriptconst requiredFields = ['user_name', 'user_email'];
// 必須フィールドの存在確認
const hasRequiredFields = requiredFields.every((field) =>
Object.keys(apiResponse).includes(field)
);
// 必須フィールドの値の妥当性確認
const hasValidValues = Object.values(apiResponse)
.filter((_, index) =>
requiredFields.includes(Object.keys(apiResponse)[index])
)
.every((value) => value && value.toString().length > 0);
React コンポーネントでの利用例
React 開発における実践的な活用例をご紹介します。
フォームの状態管理:
javascriptimport { useState } from 'react';
function UserForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
phone: ''
});
const [errors, setErrors] = useState({});
// Object.keys()を使用したフィールドのクリア
const clearForm = () => {
const clearedData = Object.keys(formData).reduce((acc, key) => {
acc[key] = '';
return acc;
}, {});
setFormData(clearedData);
};
Object.entries() を使用した動的フォームレンダリング:
javascriptconst renderFormFields = () => {
return Object.entries(formData).map(
([fieldName, value]) => (
<div key={fieldName}>
<label htmlFor={fieldName}>
{fieldName.charAt(0).toUpperCase() +
fieldName.slice(1)}
:
</label>
<input
id={fieldName}
type='text'
value={value}
onChange={(e) =>
setFormData((prev) => ({
...prev,
[fieldName]: e.target.value,
}))
}
/>
</div>
)
);
};
Object.values() を使用したバリデーション:
javascript // フォーム送信時の検証
const handleSubmit = (e) => {
e.preventDefault();
// すべてのフィールドが入力されているかチェック
const allFieldsFilled = Object.values(formData)
.every(value => value.trim().length > 0);
if (!allFieldsFilled) {
alert('すべてのフィールドを入力してください');
return;
}
// フォーム送信処理...
};
return (
<form onSubmit={handleSubmit}>
{renderFormFields()}
<button type="submit">送信</button>
<button type="button" onClick={clearForm}>クリア</button>
</form>
);
}
API レスポンスの変換処理
API からのデータを画面表示用に変換する際の実例です。
商品データの変換処理:
javascript// API レスポンス
const productsResponse = {
electronics: { count: 150, revenue: 500000 },
clothing: { count: 89, revenue: 120000 },
books: { count: 234, revenue: 78000 },
};
Object.entries() を使用したテーブルデータの生成:
javascriptconst tableData = Object.entries(productsResponse).map(
([category, data]) => ({
category: category,
itemCount: data.count,
totalRevenue: data.revenue,
averagePrice: Math.round(data.revenue / data.count),
})
);
console.log(tableData);
// [
// { category: 'electronics', itemCount: 150, totalRevenue: 500000, averagePrice: 3333 },
// { category: 'clothing', itemCount: 89, totalRevenue: 120000, averagePrice: 1348 },
// { category: 'books', itemCount: 234, totalRevenue: 78000, averagePrice: 333 }
// ]
Object.values() を使用した集計処理:
javascript// 全カテゴリの合計データ
const totalStats = Object.values(productsResponse).reduce(
(totals, categoryData) => ({
totalItems: totals.totalItems + categoryData.count,
totalRevenue:
totals.totalRevenue + categoryData.revenue,
}),
{ totalItems: 0, totalRevenue: 0 }
);
console.log(totalStats);
// { totalItems: 473, totalRevenue: 698000 }
フォームデータの検証
実際のフォームバリデーションでの活用例をご紹介します。
複雑なバリデーションルールの実装:
javascriptconst validationRules = {
email: (value) =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
phone: (value) =>
/^\d{10,11}$/.test(value.replace(/[^\d]/g, '')),
name: (value) => value.length >= 2 && value.length <= 50,
age: (value) => value >= 18 && value <= 100,
};
const formData = {
email: 'user@example.com',
phone: '090-1234-5678',
name: 'Test User',
age: 25,
};
Object.entries() を使用したバリデーション実行:
javascriptconst validateForm = (data, rules) => {
const validationResults = Object.entries(rules).map(
([field, validator]) => {
const value = data[field];
const isValid =
value !== undefined && validator(value);
return {
field,
value,
isValid,
error: isValid
? null
: `${field} の形式が正しくありません`,
};
}
);
return validationResults;
};
const results = validateForm(formData, validationRules);
console.log(results);
Object.keys() を使用したエラーフィールドの特定:
javascriptconst getErrorFields = (validationResults) => {
return validationResults
.filter((result) => !result.isValid)
.map((result) => result.field);
};
const errorFields = getErrorFields(results);
if (errorFields.length > 0) {
console.log(
`エラーのあるフィールド: ${errorFields.join(', ')}`
);
}
Object.values() を使用した全体の妥当性確認:
javascriptconst isFormValid = (validationResults) => {
return validationResults.every(
(result) => result.isValid
);
};
const formIsValid = isFormValid(results);
console.log(`フォームは有効: ${formIsValid}`);
まとめ
Object.keys、Object.entries、Object.values の 3 つのメソッドを使いこなすことで、JavaScript のオブジェクト操作が格段に効率的になります。
これらのメソッドの特徴をまとめると以下のようになります:
メソッド | 戻り値 | 主な用途 | パフォーマンス |
---|---|---|---|
Object.keys() | string[] | プロパティ名の操作、動的アクセス | 高速 |
Object.values() | any[] | 値の集計、検証処理 | 高速 |
Object.entries() | [string, any][] | オブジェクト変換、ペア処理 | 中程度 |
ES2017 で導入されたこれらの機能により、従来の for...in ループや複雑な処理が不要になり、より宣言的で読みやすいコードが書けるようになりました。
特に以下の場面では、これらのメソッドの威力を実感できるでしょう:
- API レスポンスの変換処理
- React での動的フォーム生成
- データの集計や検証
- オブジェクトの構造変換
モダンな JavaScript 開発において、これらのメソッドは必須のスキルです。適切な使い分けを心がけて、効率的なコード作成を目指しましょう。
関連リンク
- article
JavaScript のオブジェクト操作まとめ:Object.keys/entries/values の使い方
- article
【実践編】JavaScript の正規表現活用術:効率的に文字列を処理する方法
- article
JavaScript の this キーワードを完全理解!初心者がつまずくポイント解説
- article
【徹底比較】JavaScript での null と undefined の違いと正しい使い分け
- article
JavaScript のクロージャ完全ガイド:スコープとメモリの仕組みを深掘り
- article
【保存版】JavaScript のイベントループとタスクキューを図解で理解する
- article
Python で始める自動化:ファイル操作・定期実行・スクレイピングの実践
- article
生成 AI 時代の新常識!GPT-5 のセキュリティ・倫理・安全設計の最新動向
- article
【実践】NestJS で REST API を構築する基本的な流れ
- article
TypeScript × GitHub Copilot:型情報を活かした高精度コーディング
- article
Motion(旧 Framer Motion)Variants 完全攻略:staggerChildren・when で複雑アニメを整理する
- article
JavaScript のオブジェクト操作まとめ:Object.keys/entries/values の使い方
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- blog
失敗を称賛する文化はどう作る?アジャイルな組織へ生まれ変わるための第一歩
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来