in 演算子とは何か
in 演算子は、あるキー(プロパティ名)がオブジェクトに「存在するか」を調べるための演算子です。結果は真偽値(true/false)。存在確認に特化していて、値が何であるか(undefinedかどうか)とは関係なく、「キーがあるか」を判定します。
const user = { name: "太郎", age: 20 };
console.log("name" in user); // true
console.log("city" in user); // false
JavaScript存在確認の意味(undefined との違いを深掘り)
「キーがあるか」と「値があるか」は別物です。in は「キーの有無」を見ます。値が undefined でもキーが存在すれば true になります。一方、obj.key === undefined は「値が未定義か」を見るだけで、キー自体の有無は判別できません(値が undefined として設定されている場合と、キーが存在しない場合を区別できない)。
const obj = { a: undefined };
console.log("a" in obj); // true(キーは存在)
console.log(obj.a === undefined); // true(値が未定義)
console.log("b" in obj); // false(キーがない)
console.log(obj.b === undefined); // true(キーがない場合も undefined と比較で true)
JavaScriptここが重要です:キーの有無を正しく判定したいなら in。値が未設定かどうかだけを判定したいなら比較(=== undefined)を使います。
プロトタイプまで含めた探索(hasOwnProperty との違い)
in は「そのオブジェクト自身のプロパティ」だけでなく、プロトタイプチェーン上にある継承プロパティも存在として数えます。対して hasOwnProperty は「自分が持つプロパティに限定」します。
const parent = { shared: 1 };
const child = Object.create(parent); // parent を継承
child.own = 2;
console.log("own" in child); // true(自分のプロパティ)
console.log("shared" in child); // true(継承プロパティも含む)
console.log(child.hasOwnProperty("shared")); // false(自分のではない)
JavaScriptここが重要です:継承を含めて「使えるキーか」を確認するなら in、自分が持つデータに限定して確認したいなら hasOwnProperty を使い分けます。
配列と in(数値インデックスの扱い)
配列でも in は使えます。配列のインデックス(0, 1, 2…)が“キーとして存在するか”を判定します。delete で要素を消すと“穴”になり、インデックスキーが消えるので in が false を返します。splice で取り除くと詰められるため、該当インデックスの存在も変わります。
const arr = [10, 20, 30];
console.log(0 in arr); // true
console.log(3 in arr); // false
delete arr[1];
console.log(arr); // [10, <1 empty item>, 30]
console.log(1 in arr); // false(キーが消えた=穴)
arr.splice(1, 1); // 詰める
console.log(arr); // [10, 30]
console.log(1 in arr); // true(今は 30 が入っている)
JavaScriptここが重要です:配列の“存在判定”をしたいときは in が有効ですが、要素が「空の値」か「存在しない」かの違いに注意しましょう。
ブラケット記法との組み合わせ(動的キーの存在確認)
in の左側は文字列(またはシンボル)です。変数に入ったキー名で存在確認したいときはブラケット記法の発想で「動的キー」を扱います。
const user = { name: "太郎", "fav-color": "blue" };
const key = "fav-color";
console.log(key in user); // true(動的キー)
console.log("fav-color" in user); // true(文字列リテラル)
JavaScriptここが重要です:obj.key と key in obj は別概念です。前者は固定キーにアクセス、後者はキー文字列(変数の中身)で存在判定。
in とオプショナルチェーン(安全なアクセスの設計)
存在確認をした上で値を読むなら、in と通常アクセス(obj[key])を組み合わせるか、存在が曖昧なネストにはオプショナルチェーン ?. を使います。
const user = { profile: { city: "東京" } };
// inで確認してから読む
if ("profile" in user) {
console.log(user.profile.city); // プロパティが存在する前提なら安全
}
// ネストが不明なら ?. を使う
console.log(user.profile?.city); // 東京
console.log(user.address?.city); // undefined(途中がなければ止まる)
JavaScriptここが重要です:in は「キーがあるか」を判定する道具、?. は「途中がなければそこでやめる」ための道具。場面に応じて使い分けると、実行時エラーを避けられます。
宣言された変数やクラスへの in(対象の違い)
in は「オブジェクトのプロパティ」を調べる演算子です。変数(識別子)そのものやクラス名に対しては使えません。グローバルオブジェクト(ブラウザなら window)に対しては、グローバルに公開されたプロパティの存在確認に使えます。
// 変数に対しては in は使えない(オブジェクトではないため)
// console.log("x" in x); // エラー
// グローバルオブジェクトのプロパティ確認
window.temp = 123;
console.log("temp" in window); // true
JavaScriptここが重要です:in の右側は必ず「オブジェクト」。存在確認したい対象がプロパティであることを意識しましょう。
まとめ
in 演算子は「キーが存在するか」を判定するための道具で、値が undefined かどうかとは独立しています。プロトタイプ継承も含めて存在を調べるため、継承を含めて“使えるキーか”を確認したい場面に向いています。自分のプロパティだけに限定したいなら hasOwnProperty を使い、配列ではインデックスキーの存在と“穴”の有無を見分けられます。動的キーの存在確認やネストの安全なアクセスと組み合わせることで、誤判定と実行時エラーを抑え、意図通りのロジックを書けるようになります。
