javascript-mastery
すべての開発者が習得すべき33以上のJavaScriptの重要概念を網羅したスキルで、[33-js-concepts](https://github.com/leonardomso/33-js-concepts)にインスパイアされています。スコープ、クロージャ、プロトタイプチェーンなどの核心的な概念を体系的に学べます。
description の原文を見る
33+ essential JavaScript concepts every developer should know, inspired by [33-js-concepts](https://github.com/leonardomso/33-js-concepts).
SKILL.md 本文
🧠 JavaScript Mastery
すべての開発者が知っておくべき 33+ の重要な JavaScript コンセプト。33-js-concepts にインスピレーションを受けています。
このスキルをいつ使うか
以下の場合にこのスキルを使用してください:
- JavaScript コンセプトを説明する
- トリッキーな JS の挙動をデバッグする
- JavaScript の基礎を教える
- JS のベストプラクティスについてコードレビューする
- 言語の落とし穴を理解する
1. 基礎
1.1 プリミティブ型
JavaScript には 7 つのプリミティブ型があります:
// String
const str = "hello";
// Number (整数と浮動小数点数)
const num = 42;
const float = 3.14;
// BigInt (大きな整数用)
const big = 9007199254740991n;
// Boolean
const bool = true;
// Undefined
let undef; // undefined
// Null
const empty = null;
// Symbol (ユニークな識別子)
const sym = Symbol("description");
ポイント:
- プリミティブ型は不変
- 値渡し
typeof null === "object"は歴史的なバグ
1.2 型強制
JavaScript は暗黙的に型を変換します:
// 文字列への強制
"5" + 3; // "53" (数値 → 文字列)
"5" - 3; // 2 (文字列 → 数値)
// ブール値への強制
Boolean(""); // false
Boolean("hello"); // true
Boolean(0); // false
Boolean([]); // true (!)
// 等価性での強制
"5" == 5; // true (強制される)
"5" === 5; // false (厳密)
偽値 (全 8 つ):
false, 0, -0, 0n, "", null, undefined, NaN
1.3 等価性演算子
// == (緩い等価性) - 型を強制
null == undefined; // true
"1" == 1; // true
// === (厳密な等価性) - 強制しない
null === undefined; // false
"1" === 1; // false
// Object.is() - エッジケースに対応
Object.is(NaN, NaN); // true (NaN === NaN は false!)
Object.is(-0, 0); // false (0 === -0 は true!)
ルール: 特別な理由がない限り、常に === を使用してください。
2. スコープとクロージャ
2.1 スコープのタイプ
// グローバルスコープ
var globalVar = "global";
function outer() {
// 関数スコープ
var functionVar = "function";
if (true) {
// ブロックスコープ (let/const のみ)
let blockVar = "block";
const alsoBlock = "block";
var notBlock = "function"; // var はブロックを無視!
}
}
2.2 クロージャ
クロージャは、字句スコープを記憶する関数です:
function createCounter() {
let count = 0; // "閉じられた" 変数
return {
increment() {
return ++count;
},
decrement() {
return --count;
},
getCount() {
return count;
},
};
}
const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2
counter.getCount(); // 2
一般的なユースケース:
- データプライバシー (モジュールパターン)
- 関数ファクトリー
- 部分適用
- メモ化
2.3 var vs let vs const
// var - 関数スコープ、ホイスティング、再宣言可能
var x = 1;
var x = 2; // OK
// let - ブロックスコープ、ホイスティング (TDZ)、再宣言不可
let y = 1;
// let y = 2; // Error!
// const - let のようだが、再割り当て不可
const z = 1;
// z = 2; // Error!
// ただし: const オブジェクトは変更可能
const obj = { a: 1 };
obj.a = 2; // OK
obj.b = 3; // OK
3. 関数と実行
3.1 コールスタック
function first() {
console.log("first start");
second();
console.log("first end");
}
function second() {
console.log("second");
}
first();
// 出力:
// "first start"
// "second"
// "first end"
スタックオーバーフロー例:
function infinite() {
infinite(); // ベースケースなし!
}
infinite(); // RangeError: Maximum call stack size exceeded
3.2 ホイスティング
// 変数ホイスティング
console.log(a); // undefined (ホイスティングされたが初期化されていない)
var a = 5;
console.log(b); // ReferenceError (TDZ)
let b = 5;
// 関数ホイスティング
sayHi(); // 動作!
function sayHi() {
console.log("Hi!");
}
// 関数式はホイスティングされない
sayBye(); // TypeError
var sayBye = function () {
console.log("Bye!");
};
3.3 this キーワード
// グローバルコンテキスト
console.log(this); // window (ブラウザ) または global (Node)
// オブジェクトメソッド
const obj = {
name: "Alice",
greet() {
console.log(this.name); // "Alice"
},
};
// アロー関数 (字句的 this)
const obj2 = {
name: "Bob",
greet: () => {
console.log(this.name); // undefined (外側の this を継承)
},
};
// 明示的なバインディング
function greet() {
console.log(this.name);
}
greet.call({ name: "Charlie" }); // "Charlie"
greet.apply({ name: "Diana" }); // "Diana"
const bound = greet.bind({ name: "Eve" });
bound(); // "Eve"
4. イベントループと非同期処理
4.1 イベントループ
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
// 出力: 1, 4, 3, 2
// 理由? マイクロタスク (Promises) はマクロタスク (setTimeout) より先に実行される
実行順序:
- 同期コード (コールスタック)
- マイクロタスク (Promise コールバック、queueMicrotask)
- マクロタスク (setTimeout、setInterval、I/O)
4.2 コールバック
// コールバックパターン
function fetchData(callback) {
setTimeout(() => {
callback(null, { data: "result" });
}, 1000);
}
// エラーファースト規約
fetchData((error, result) => {
if (error) {
console.error(error);
return;
}
console.log(result);
});
// コールバック地獄 (これは避けてください!)
getData((data) => {
processData(data, (processed) => {
saveData(processed, (saved) => {
notify(saved, () => {
// 😱 破滅のピラミッド
});
});
});
});
4.3 Promises
// Promise を作成
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Success!");
// または: reject(new Error("Failed!"));
}, 1000);
});
// Promise を消費
promise
.then((result) => console.log(result))
.catch((error) => console.error(error))
.finally(() => console.log("Done"));
// Promise コンビネータ
Promise.all([p1, p2, p3]); // すべて成功する必要がある
Promise.allSettled([p1, p2]); // すべてを待機、ステータスを取得
Promise.race([p1, p2]); // 最初に解決したもの
Promise.any([p1, p2]); // 最初に成功したもの
4.4 async/await
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error("Failed to fetch");
const user = await response.json();
return user;
} catch (error) {
console.error("Error:", error);
throw error; // 呼び出し元で処理してもらう
}
}
// 並列実行
async function fetchAll() {
const [users, posts] = await Promise.all([
fetch("/api/users"),
fetch("/api/posts"),
]);
return { users, posts };
}
5. 関数型プログラミング
5.1 高階関数
関数を受け取るか返す関数:
// 関数を受け取る
const numbers = [1, 2, 3];
const doubled = numbers.map((n) => n * 2); // [2, 4, 6]
// 関数を返す
function multiply(a) {
return function (b) {
return a * b;
};
}
const double = multiply(2);
double(5); // 10
5.2 純粋関数
// 純粋: 同じ入力 → 同じ出力、副作用なし
function add(a, b) {
return a + b;
}
// 不純: 外部状態を変更
let total = 0;
function addToTotal(value) {
total += value; // 副作用!
return total;
}
// 不純: 外部状態に依存
function getDiscount(price) {
return price * globalDiscountRate; // 外部依存
}
5.3 map、filter、reduce
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 35 },
];
// map: 各要素を変換
const names = users.map((u) => u.name);
// ["Alice", "Bob", "Charlie"]
// filter: 条件に一致する要素を保持
const adults = users.filter((u) => u.age >= 30);
// [{ name: "Bob", ... }, { name: "Charlie", ... }]
// reduce: 単一値に集約
const totalAge = users.reduce((sum, u) => sum + u.age, 0);
// 90
// チェーン
const result = users
.filter((u) => u.age >= 30)
.map((u) => u.name)
.join(", ");
// "Bob, Charlie"
5.4 カリーイングと関数合成
// カリーイング: f(a, b, c) を f(a)(b)(c) に変換
const curry = (fn) => {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return (...moreArgs) => curried(...args, ...moreArgs);
};
};
const add = curry((a, b, c) => a + b + c);
add(1)(2)(3); // 6
add(1, 2)(3); // 6
add(1)(2, 3); // 6
// 関数合成: 関数を組み合わせる
const compose =
(...fns) =>
(x) =>
fns.reduceRight((acc, fn) => fn(acc), x);
const pipe =
(...fns) =>
(x) =>
fns.reduce((acc, fn) => fn(acc), x);
const addOne = (x) => x + 1;
const double = (x) => x * 2;
const addThenDouble = compose(double, addOne);
addThenDouble(5); // 12 = (5 + 1) * 2
const doubleThenAdd = pipe(double, addOne);
doubleThenAdd(5); // 11 = (5 * 2) + 1
6. オブジェクトとプロトタイプ
6.1 プロトタイプ継承
// プロトタイプチェーン
const animal = {
speak() {
console.log("Some sound");
},
};
const dog = Object.create(animal);
dog.bark = function () {
console.log("Woof!");
};
dog.speak(); // "Some sound" (継承)
dog.bark(); // "Woof!" (独自メソッド)
// ES6 クラス (構文糖)
class Animal {
speak() {
console.log("Some sound");
}
}
class Dog extends Animal {
bark() {
console.log("Woof!");
}
}
6.2 Object メソッド
const obj = { a: 1, b: 2 };
// キー、値、エントリ
Object.keys(obj); // ["a", "b"]
Object.values(obj); // [1, 2]
Object.entries(obj); // [["a", 1], ["b", 2]]
// 浅いコピー
const copy = { ...obj };
const copy2 = Object.assign({}, obj);
// フリーズ (不変)
const frozen = Object.freeze({ x: 1 });
frozen.x = 2; // 無視される (または厳密モードではスロー)
// シール (追加/削除不可、変更可能)
const sealed = Object.seal({ x: 1 });
sealed.x = 2; // OK
sealed.y = 3; // 失敗
delete sealed.x; // 失敗
7. モダン JavaScript (ES6+)
7.1 分割代入
// 配列の分割代入
const [first, second, ...rest] = [1, 2, 3, 4, 5];
// first = 1, second = 2, rest = [3, 4, 5]
// オブジェクトの分割代入
const { name, age, city = "Unknown" } = { name: "Alice", age: 25 };
// name = "Alice", age = 25, city = "Unknown"
// 名前の変更
const { name: userName } = { name: "Bob" };
// userName = "Bob"
// ネストされた
const {
address: { street },
} = { address: { street: "123 Main" } };
7.2 スプレッド演算子とレスト
// スプレッド: 反復可能オブジェクトを展開
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 }; // { a: 1, b: 2 }
// レスト: 残りの要素を集める
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4); // 10
7.3 モジュール
// 名前付きエクスポート
export const PI = 3.14159;
export function square(x) {
return x * x;
}
// デフォルトエクスポート
export default class Calculator {}
// インポート
import Calculator, { PI, square } from "./math.js";
import * as math from "./math.js";
// 動的インポート
const module = await import("./dynamic.js");
7.4 オプショナルチェーニングとヌル合体
// オプショナルチェーニング (?.)
const user = { address: { city: "NYC" } };
const city = user?.address?.city; // "NYC"
const zip = user?.address?.zip; // undefined (エラーなし)
const fn = user?.getName?.(); // メソッドがない場合は undefined
// ヌル合体 (??)
const value = null ?? "default"; // "default"
const zero = 0 ?? "default"; // 0 (ヌルではない!)
const empty = "" ?? "default"; // "" (ヌルではない!)
// || との比較
const value2 = 0 || "default"; // "default" (0 は偽値)
クイックリファレンスカード
| コンセプト | ポイント |
|---|---|
== vs === | 常に === を使用 |
var vs let | let/const を優先 |
| クロージャ | 関数 + 字句スコープ |
this | 関数の呼び出し方法に依存 |
| イベントループ | マイクロタスクがマクロタスク優先 |
| 純粋関数 | 同じ入力 → 同じ出力 |
| プロトタイプ | __proto__ → プロトタイプチェーン |
?? vs || | ?? は null/undefined のみチェック |
リソース
制限事項
- このスキルは、タスクがうえで説明したスコープに明確に一致する場合にのみ使用してください。
- 出力を、環境固有の検証、テスト、または専門家によるレビューの代替として扱わないでください。
- 必要な入力、パーミッション、セーフティ境界、または成功基準が不足している場合は、立ち止まって明確化を求めてください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- sickn33
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/sickn33/antigravity-awesome-skills / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。