3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScript 基礎まとめ —他言語経験者向けクイックリファレンス

3
Posted at

JavaScript 基礎まとめ — 他言語経験者向けクイックリファレンス

1. JavaScriptの特徴と概要

特徴 内容
型システム 動的型付け(実行時に型が決まる)
パラダイム マルチパラダイム(関数型 + オブジェクト指向 + イベント駆動)
実行環境 ブラウザ(V8, SpiderMonkey 等)/ サーバー(Node.js, Deno, Bun)
標準仕様 ECMAScript(ES2015 以降が現代 JS の基盤)
モジュール ES Modules(import/export)が標準。Node.js では CommonJS(require)も健在

ブラウザでは DOM 操作・イベント処理・Web API(Fetch, Canvas, WebSocket 等)にアクセスできる。
Node.jsではファイルシステム、ネットワーク、OS 操作など、サーバーサイドの処理が可能。


2. 環境構築

Node.js のインストール

# nvm(Node Version Manager)を使うのが定番
# macOS / Linux
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
nvm install --lts
node -v  # v22.x.x

# Windows は nvm-windows を使う
# https://github.com/coreybutler/nvm-windows/releases

パッケージマネージャ

# npm(Node.js に同梱)
npm init -y          # package.json を生成
npm install lodash   # パッケージを追加

# pnpm(高速・ディスク効率が良い。実務で採用が増えている)
npm install -g pnpm
pnpm init
pnpm add lodash

package.json が依存関係の管理ファイル。node_modules/ に実体が入る。


3. Hello World

ブラウザ

<!DOCTYPE html>
<html lang="ja">
<head><meta charset="UTF-8"><title>Hello</title></head>
<body>
  <p id="output"></p>
  <script>
    // コンソールに出力
    console.log("Hello, World!");

    // DOM に書き込み
    document.getElementById("output").textContent = "Hello, World!";
  </script>
</body>
</html>

Node.js

// hello.js
console.log("Hello, World!");
node hello.js
# => Hello, World!

4. 変数・データ型

let / const / var

const PI = 3.14;    // 再代入不可。基本はこれを使う
let count = 0;      // 再代入可。ブロックスコープ
var legacy = "old"; // 関数スコープ。使わない

// const はオブジェクトのプロパティ変更は許可する
const obj = { a: 1 };
obj.a = 2;       // OK
// obj = {};     // TypeError: Assignment to constant variable.

プリミティブ型

typeof 42;            // "number"   ── 整数・浮動小数点の区別なし
typeof 42n;           // "bigint"   ── 任意精度整数
typeof "hello";       // "string"
typeof true;          // "boolean"
typeof undefined;     // "undefined"
typeof null;          // "object"   ── 歴史的バグ。実際は null 型
typeof Symbol("id");  // "symbol"

数値の注意点

0.1 + 0.2 === 0.3;          // false(IEEE 754 浮動小数点)
Number.isInteger(1.0);       // true
Number.MAX_SAFE_INTEGER;     // 9007199254740991(2^53 - 1)
parseInt("0xFF", 16);        // 255
parseFloat("3.14abc");       // 3.14
Number.isNaN(NaN);           // true(グローバルの isNaN() より厳密)

文字列

const name = "World";

// テンプレートリテラル(バッククォート)
const greeting = `Hello, ${name}!`;

// 複数行もそのまま書ける
const multiline = `
  1行目
  2行目
`;

// よく使うメソッド
"abcabc".includes("bc");     // true
"abcabc".indexOf("bc");      // 1
"abcabc".replaceAll("bc", "XX"); // "aXXaXX"
"  hello  ".trim();           // "hello"
"a,b,c".split(",");           // ["a", "b", "c"]

等値比較

// == は型変換あり(使わない)
0 == "";       // true
null == undefined; // true

// === は型変換なし(常にこちらを使う)
0 === "";      // false
null === undefined; // false

5. 条件分岐

if / else

const status = 404;

if (status === 200) {
  console.log("OK");
} else if (status === 404) {
  console.log("Not Found");
} else {
  console.log("Other");
}

switch

const fruit = "apple";

switch (fruit) {
  case "apple":
    console.log("りんご");
    break;
  case "banana":
    console.log("バナナ");
    break;
  default:
    console.log("不明");
}

三項演算子

const age = 20;
const label = age >= 18 ? "成人" : "未成年";

Nullish Coalescing (??)

// null または undefined のときだけ右辺を使う
const value = null ?? "default";   // "default"
const zero = 0 ?? "default";      // 0(|| だと "default" になる)

// || は falsy(0, "", false, null, undefined, NaN)すべてで右辺を使う
const legacy = 0 || "default";    // "default"

Optional Chaining (?.)

const user = { address: { city: "Tokyo" } };

// プロパティが存在しなければ undefined を返す(例外は投げない)
user.address?.city;     // "Tokyo"
user.phone?.number;     // undefined

// メソッド呼び出し
user.greet?.();         // undefined(メソッドが無ければ何もしない)

// 配列アクセス
const arr = [1, 2, 3];
arr?.[10];              // undefined

6. ループ

// 基本の for
for (let i = 0; i < 5; i++) {
  console.log(i); // 0, 1, 2, 3, 4
}

// for...of(配列・イテラブルの値を列挙)
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
  console.log(fruit);
}

// for...in(オブジェクトのキーを列挙。配列には使わない)
const config = { host: "localhost", port: 3000 };
for (const key in config) {
  console.log(`${key}: ${config[key]}`);
}

// while
let n = 5;
while (n > 0) {
  console.log(n--);
}

// Array.forEach(戻り値なし。break できない点に注意)
fruits.forEach((fruit, index) => {
  console.log(`${index}: ${fruit}`);
});

7. 配列・オブジェクト

配列メソッド

const nums = [1, 2, 3, 4, 5];

// map: 各要素を変換して新しい配列を返す
const doubled = nums.map((n) => n * 2);
// [2, 4, 6, 8, 10]

// filter: 条件に合う要素だけの配列を返す
const evens = nums.filter((n) => n % 2 === 0);
// [2, 4]

// reduce: 畳み込み
const sum = nums.reduce((acc, n) => acc + n, 0);
// 15

// find / findIndex: 最初に条件を満たす要素 / インデックス
nums.find((n) => n > 3);       // 4
nums.findIndex((n) => n > 3);  // 3

// some / every: 一つでも / すべてが条件を満たすか
nums.some((n) => n > 4);   // true
nums.every((n) => n > 0);  // true

// flat / flatMap
[[1, 2], [3, 4]].flat();                 // [1, 2, 3, 4]
[1, 2, 3].flatMap((n) => [n, n * 10]);   // [1, 10, 2, 20, 3, 30]

// チェーン
const result = nums
  .filter((n) => n % 2 === 1)
  .map((n) => n ** 2);
// [1, 9, 25]

スプレッド構文

// 配列のコピー・結合
const a = [1, 2, 3];
const b = [...a, 4, 5];     // [1, 2, 3, 4, 5]

// オブジェクトのコピー・マージ(浅いコピー)
const base = { host: "localhost", port: 3000 };
const merged = { ...base, port: 8080, debug: true };
// { host: "localhost", port: 8080, debug: true }

分割代入(Destructuring)

// 配列
const [first, second, ...rest] = [10, 20, 30, 40];
// first=10, second=20, rest=[30, 40]

// オブジェクト
const { host, port, debug = false } = { host: "localhost", port: 3000 };
// host="localhost", port=3000, debug=false(デフォルト値)

// リネーム
const { host: h, port: p } = { host: "localhost", port: 3000 };
// h="localhost", p=3000

// ネスト
const { address: { city } } = { address: { city: "Tokyo" } };
// city="Tokyo"

// 関数の引数で直接分割
function greet({ name, age }) {
  return `${name} (${age})`;
}
greet({ name: "Taro", age: 25 }); // "Taro (25)"

Map / Set

// Map: 任意のキー型を持てる辞書
const map = new Map();
map.set("key1", "value1");
map.set(42, "number key");
map.get("key1");    // "value1"
map.has(42);        // true
map.size;           // 2

// オブジェクトから一括生成
const fromObj = new Map(Object.entries({ a: 1, b: 2 }));

// イテレーション
for (const [key, value] of map) {
  console.log(`${key}: ${value}`);
}

// Set: 一意な値の集合
const set = new Set([1, 2, 2, 3]);
set.size;     // 3(重複は除去される)
set.add(4);
set.has(2);   // true
set.delete(1);

// 配列の重複除去
const unique = [...new Set([1, 1, 2, 3, 3])];
// [1, 2, 3]

8. 関数

関数宣言 vs アロー関数

// 関数宣言(巻き上げ(hoisting)される)
function add(a, b) {
  return a + b;
}

// 関数式
const subtract = function (a, b) {
  return a - b;
};

// アロー関数(thisを束縛しない。コールバックに最適)
const multiply = (a, b) => a * b;

// 引数が1つなら括弧省略可
const double = (n) => n * 2;

// 複数行の場合は {} と return が必要
const divide = (a, b) => {
  if (b === 0) throw new Error("Division by zero");
  return a / b;
};

デフォルト引数・残余引数

// デフォルト引数
function greet(name = "World") {
  return `Hello, ${name}!`;
}
greet();        // "Hello, World!"
greet("Taro");  // "Hello, Taro!"

// 残余引数(Rest parameters)
function sum(...numbers) {
  return numbers.reduce((acc, n) => acc + n, 0);
}
sum(1, 2, 3, 4); // 10

// 組み合わせ
function createUser(name, role = "user", ...tags) {
  return { name, role, tags };
}
createUser("Taro", "admin", "vip", "early-adopter");
// { name: "Taro", role: "admin", tags: ["vip", "early-adopter"] }

クロージャ

// 外側の変数を「閉じ込めて」持ち続ける
function createCounter(initial = 0) {
  let count = initial;
  return {
    increment: () => ++count,
    decrement: () => --count,
    value: () => count,
  };
}

const counter = createCounter(10);
counter.increment(); // 11
counter.increment(); // 12
counter.decrement(); // 11
counter.value();     // 11

高階関数

// 関数を受け取る関数
function retry(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return fn();
    } catch (e) {
      if (i === maxRetries - 1) throw e;
      console.log(`Retry ${i + 1}/${maxRetries}`);
    }
  }
}

// 関数を返す関数
function withLogging(fn) {
  return (...args) => {
    console.log(`Call: ${fn.name}(${args.join(", ")})`);
    const result = fn(...args);
    console.log(`Result: ${result}`);
    return result;
  };
}

const loggedAdd = withLogging(add);
loggedAdd(2, 3);
// Call: add(2, 3)
// Result: 5

9. クラスとプロトタイプ

class 構文

class User {
  // プライベートフィールド
  #password;

  constructor(name, email, password) {
    this.name = name;       // パブリック
    this.email = email;
    this.#password = password;
  }

  // ゲッター
  get displayName() {
    return `${this.name} <${this.email}>`;
  }

  // メソッド
  verifyPassword(input) {
    return this.#password === input;
  }

  // 静的メソッド
  static fromObject({ name, email, password }) {
    return new User(name, email, password);
  }
}

const user = new User("Taro", "taro@example.com", "secret");
user.displayName;            // "Taro <taro@example.com>"
user.verifyPassword("secret"); // true
// user.#password;           // SyntaxError(外部からアクセス不可)

継承

class AdminUser extends User {
  #role;

  constructor(name, email, password, role = "admin") {
    super(name, email, password);
    this.#role = role;
  }

  get info() {
    return `${this.displayName} [${this.#role}]`;
  }
}

const admin = new AdminUser("Admin", "admin@example.com", "pass123");
admin.info; // "Admin <admin@example.com> [admin]"
admin instanceof User;       // true
admin instanceof AdminUser;  // true

プロトタイプの理解

// class 構文は prototype ベースの糖衣構文
// 全オブジェクトは __proto__([[Prototype]])を通じてチェーンを辿る

class Animal {
  speak() { return "..."; }
}

class Dog extends Animal {
  speak() { return "Woof!"; }
}

const dog = new Dog();

// プロトタイプチェーン:
// dog -> Dog.prototype -> Animal.prototype -> Object.prototype -> null
Object.getPrototypeOf(dog) === Dog.prototype;             // true
Object.getPrototypeOf(Dog.prototype) === Animal.prototype; // true

10. 非同期処理

コールバック → Promise → async/await の進化

// ❌ コールバック地獄(歴史的スタイル)
// fs.readFile("a.txt", (err, a) => {
//   fs.readFile("b.txt", (err, b) => {
//     fs.readFile("c.txt", (err, c) => { ... });
//   });
// });

// ✅ Promise チェーン
function fetchData(url) {
  return fetch(url)
    .then((res) => {
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      return res.json();
    });
}

// ✅✅ async/await(最も読みやすい)
async function fetchData(url) {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

Promise の基本

// Promise を自作する
function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

// 使用
await delay(1000);
console.log("1秒経過");

// Promise.all: すべて完了を待つ(1つでも失敗したら reject)
const [users, posts] = await Promise.all([
  fetch("/api/users").then((r) => r.json()),
  fetch("/api/posts").then((r) => r.json()),
]);

// Promise.allSettled: すべての結果を取得(失敗しても他を待つ)
const results = await Promise.allSettled([
  fetch("/api/a"),
  fetch("/api/b"),
]);
// [{ status: "fulfilled", value: ... }, { status: "rejected", reason: ... }]

// Promise.race: 最初に完了(または失敗)した結果を返す
const fastest = await Promise.race([
  fetch("/api/primary"),
  delay(5000).then(() => { throw new Error("Timeout"); }),
]);

async/await とエラーハンドリング

async function getUser(id) {
  try {
    const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return await res.json();
  } catch (error) {
    console.error("Failed to fetch user:", error.message);
    return null;
  }
}

// トップレベル await(ES2022 / Node.js の ESM で利用可能)
const user = await getUser(1);
console.log(user?.name); // "Leanne Graham"

Node.js でのファイル操作(非同期)

import { readFile, writeFile } from "node:fs/promises";

const content = await readFile("input.txt", "utf-8");
await writeFile("output.txt", content.toUpperCase());

11. デファクトスタンダードなフレームワーク

React — UI ライブラリ

コンポーネントベースの UI 構築。宣言的に UI を記述する。

npx create-vite@latest my-app -- --template react
cd my-app && npm install && npm run dev
// src/App.jsx
import { useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

Next.js — React のフルスタックフレームワーク

SSR / SSG / API Routes / ファイルベースルーティングを提供。React で本番アプリを作るならほぼこれ。

npx create-next-app@latest my-next-app
cd my-next-app && npm run dev
// app/page.jsx(App Router)
export default async function Home() {
  const res = await fetch("https://jsonplaceholder.typicode.com/posts?_limit=5");
  const posts = await res.json();

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

Express — Node.js の Web フレームワーク

最小構成の HTTP サーバー。ミドルウェアを積み重ねてリクエストを処理する。

mkdir my-api && cd my-api
npm init -y
npm install express
// index.js
import express from "express";

const app = express();
app.use(express.json());

app.get("/", (req, res) => {
  res.json({ message: "Hello, Express!" });
});

app.listen(3000, () => console.log("http://localhost:3000"));

package.json"type": "module" を追加すると import/export が使える。


12. Express で MVC の簡単な例

実用的な最小構成で MVC パターンを構築する。

ディレクトリ構成

express-mvc/
├── package.json
├── src/
│   ├── app.js            # エントリーポイント
│   ├── routes/
│   │   └── userRoutes.js # ルーティング定義
│   ├── controllers/
│   │   └── userController.js
│   ├── models/
│   │   └── userModel.js
│   └── middleware/
│       └── logger.js

package.json

{
  "name": "express-mvc",
  "type": "module",
  "scripts": {
    "start": "node src/app.js",
    "dev": "node --watch src/app.js"
  },
  "dependencies": {
    "express": "^5.1.0"
  }
}

Model — src/models/userModel.js

// 簡易インメモリストア(実際には DB を使う)
const users = [
  { id: 1, name: "Taro", email: "taro@example.com" },
  { id: 2, name: "Hanako", email: "hanako@example.com" },
];

let nextId = 3;

export const UserModel = {
  findAll() {
    return users;
  },

  findById(id) {
    return users.find((u) => u.id === id) ?? null;
  },

  create({ name, email }) {
    const user = { id: nextId++, name, email };
    users.push(user);
    return user;
  },

  update(id, data) {
    const user = this.findById(id);
    if (!user) return null;
    Object.assign(user, data);
    return user;
  },

  delete(id) {
    const index = users.findIndex((u) => u.id === id);
    if (index === -1) return false;
    users.splice(index, 1);
    return true;
  },
};

Controller — src/controllers/userController.js

import { UserModel } from "../models/userModel.js";

export const UserController = {
  // GET /users
  list(req, res) {
    res.json(UserModel.findAll());
  },

  // GET /users/:id
  show(req, res) {
    const user = UserModel.findById(Number(req.params.id));
    if (!user) return res.status(404).json({ error: "User not found" });
    res.json(user);
  },

  // POST /users
  create(req, res) {
    const { name, email } = req.body;
    if (!name || !email) {
      return res.status(400).json({ error: "name and email are required" });
    }
    const user = UserModel.create({ name, email });
    res.status(201).json(user);
  },

  // PUT /users/:id
  update(req, res) {
    const user = UserModel.update(Number(req.params.id), req.body);
    if (!user) return res.status(404).json({ error: "User not found" });
    res.json(user);
  },

  // DELETE /users/:id
  delete(req, res) {
    const deleted = UserModel.delete(Number(req.params.id));
    if (!deleted) return res.status(404).json({ error: "User not found" });
    res.status(204).end();
  },
};

Router — src/routes/userRoutes.js

import { Router } from "express";
import { UserController } from "../controllers/userController.js";

const router = Router();

router.get("/",     UserController.list);
router.get("/:id",  UserController.show);
router.post("/",    UserController.create);
router.put("/:id",  UserController.update);
router.delete("/:id", UserController.delete);

export default router;

Middleware — src/middleware/logger.js

export function requestLogger(req, res, next) {
  const start = Date.now();

  // レスポンス送信後にログを出力
  res.on("finish", () => {
    const ms = Date.now() - start;
    console.log(`${req.method} ${req.originalUrl} ${res.statusCode} - ${ms}ms`);
  });

  next();
}

App — src/app.js

import express from "express";
import { requestLogger } from "./middleware/logger.js";
import userRoutes from "./routes/userRoutes.js";

const app = express();
const PORT = process.env.PORT || 3000;

// --- ミドルウェア ---
app.use(express.json());
app.use(requestLogger);

// --- ルーティング ---
app.use("/users", userRoutes);

// --- 404 ハンドラ ---
app.use((req, res) => {
  res.status(404).json({ error: "Not Found" });
});

// --- エラーハンドラ ---
app.use((err, req, res, _next) => {
  console.error(err.stack);
  res.status(500).json({ error: "Internal Server Error" });
});

// --- 起動 ---
app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});

動作確認

npm install
npm run dev

# 別ターミナルで
curl http://localhost:3000/users
# [{"id":1,"name":"Taro","email":"taro@example.com"},{"id":2,"name":"Hanako","email":"hanako@example.com"}]

curl -X POST http://localhost:3000/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Jiro","email":"jiro@example.com"}'
# {"id":3,"name":"Jiro","email":"jiro@example.com"}

curl -X PUT http://localhost:3000/users/3 \
  -H "Content-Type: application/json" \
  -d '{"name":"Jiro Updated"}'
# {"id":3,"name":"Jiro Updated","email":"jiro@example.com"}

curl -X DELETE http://localhost:3000/users/3 -w "\n%{http_code}\n"
# 204

以上で JavaScript の基礎を一通りカバーした。TypeScript への移行を考えるなら、この基礎の上に型システムを載せる形になる。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?