31
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScirpt/TypeScriptで最低限知っておきたいこと 随時更新

Last updated at Posted at 2025-03-09

これは何?

JavaScriptを使おうと思ってみたものの歴史が長いため,特殊な仕様だったり,よくわからない言葉がたくさんある気がする。
最近は生成AIでなんとなく動くものは作れてしまうが,もやもやが晴れないので一念発起して気になっていることをちゃんと調べてまとめてみた。

これからJavaScript,TypeScriptを学習しようとする方や,自分のようになんとなく動くものは作れるけどもやっとすることがある方の助けになれば良いなと思う。

なぜ,今JS/TSを学ぶ気になったのか

  • VSCodeの拡張のロジックはJS/TSで書かれるから
  • (GitHub Actionsの拡張作りたいみたいなのもあったりするが)
  • フレームワークの移り変わりは早いが

ESModuleとCommonJS

フロントエンドではimportを使っているのにnode.js(バックエンド)ではrequireが使われていて,同じ言語なのにライブラリを使用する構文に違いがあるのだ?と不思議な気持ちになったことはあるだろうか。

これはESModuleCommonJSという二種類のモジュールシステムが存在しているためだ。
基本的に新しいESModuleを使う方が主流にはなってきているが,一部のライブラリがESModule(import)に対応していない場合にはCommonJS(require)を使うこともある。

これらの違いについて公式ドキュメントをもとに記載した。

ESModule(importを使う方)

ECMScriptの第6版(2015)に追加された機能。

Some of its major enhancements included modules, class declarations, lexical block scoping, iterators and generators, promises for asynchronous programming, destructuring patterns, and proper tail calls. The ECMAScript library of built-ins was expanded to support additional data abstractions including maps, sets, and arrays of binary numeric values as well as additional support for Unicode supplementary characters in strings and regular expressions. The built-ins were also made extensible via subclassing. The sixth edition provides the foundation for regular, incremental language and library enhancements. The sixth edition was adopted by the General Assembly of June 2015. 引用元

ECMAScript(エクマスクリプト)は、Ecmaインターナショナルにおいて標準化されたJavaScriptの国際規格である。https://ja.wikipedia.org/wiki/ECMAScript

  • Node.js ESM Documentationのサンプルコードにあるようにimport {}を使ってライブラリを読み込み,export {}を使ってライブラリを外部からアクセス可能にする。
addTwo.mjs
// addTwo.mjs
function addTwo(num) {
 return num + 2;
}
export { addTwo };
app.mjs
// app.mjs
import { addTwo } from './addTwo.mjs';
console.log(addTwo(4)); // 6と出力

CommonJS(requireを使う方)

CommonJS modules are the original way to package JavaScript code for Node.js. Node.js also supports the ECMAScript modules standard used by browsers and other JavaScript runtimes.
Node.js v23.9.0 documentationより

CommonJSはNodo.jsで作成されたコードをパッケージ化する昔ながらの方法といったところでしょう。

同ドキュメントのサンプルコードを見ると,require()を使ってライブラリを読み込み,export.要素名で外部からアクセス可能にすることがわかります。

foo.js
const circle = require('./circle.js');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`); 
circle.js
const { PI } = Math;
exports.area = (r) => PI * r ** 2;
exports.circumference = (r) => 2 * PI * r;

拡張子のあれこれ

JavaScript

  • .js: 基本的なJava Scriptの拡張子

  • .mjs: どのファイルがモジュールで、どのファイルが通常の JavaScript であるかを明確にするためにV8のドキュメントで推奨されている拡張子。.mjsが使用されている場合にはESModuleが使われている。

    .mjsを使うことでサーバが拡張子を正しく判断できなくなる可能性があることに注意する

    ブラウザーでモジュールを正しく動作させるためには、サーバーが Content-Type ヘッダーで JavaScript の MIME タイプ、例えば text/javascript などを含めて提供していることを確認する必要があります。そうしないと、"The server responded with a non-JavaScript MIME type" のような厳格な MIME タイプチェックエラーが表示され、ブラウザーは JavaScript を実行しません。ほとんどのサーバーでは、.js ファイルにはすでに正しい MIME タイプが設定されていますが、.mjs ファイルにはまだ設定されていません。すでに .mjs ファイルを正しく提供しているサーバーには、GitHub Pages や Node.js の http-server などがあります。

  • .cjs: Node.jsでは.cjs拡張子を使っているとCommonJSとして扱われる。

  • .jsx: JavaScriptの拡張であり、JavaScriptファイル内にHTMLのようなマークアップを書けるようにするもの

    // 公式ドキュメントから引用
    export default function TodoList() {
      return (
        // This doesn't quite work!
        <h1>Hedy Lamarr's Todos</h1>
        <img 
          src="https://i.imgur.com/yXOvdOSs.jpg" 
          alt="Hedy Lamarr" 
          class="photo"
        >
        <ul>
          <li>Invent new traffic lights
          <li>Rehearse a movie scene
          <li>Improve the spectrum technology
        </ul>
      );
    }
    
    

TypeScript

上記のTypeScriptバージョンなので割愛

  • .ts
  • .mts
  • .cts
  • .tsx

JSON

{
  "browsers": {
    "firefox": {
      "name": "Firefox",
      "pref_url": "about:config",
      "releases": {
        "1": {
          "release_date": "2004-11-09",
          "status": "retired",
          "engine": "Gecko",
          "engine_version": "1.7"
        }
      }
    }
  }
}
  • 構造化データを表現するための標準のテキストベースの形式
  • JSONのテキストは有効なJavaScriptの式になる ※全てのJavaScriptがJSONになるわけではない
  • JavaScriptと文法は微妙に違う

VSCodeのsettings.jsonはVSCodeがJSONに独自の拡張を加えているらしいので,本来コメントは使えない。
参考

最近,MCPでAIモデルとデータソース間のデータのやり取りがJSONで行われていることもあり,非プログラマの方の間でも多少ホットなデータ保存形式なのではないだろうか。


参考: node.jsでESModuleとCommonJSの優先順位の決まり方

  1. .cjsを使っている→CommonJS,.mjsを使っている→ESModule
  2. .jsの場合: package.jsonを確認する
    • package.jsonなし→CommonJS
    • package.jsonにtypeフィールドなし→CommonJS
    • package.jsonのtypeフィールドに"commonjs"が指定→CommonJS
    • package.jsonのtypeフィールドに"module"が指定→ESModule
  3. .mjs,.cjs,.json,.node,.js以外の拡張子の場合
  • import()を使うならESModule
  • require()を使うならCommonJS

↓せっかくなのでフローチャートにしてみた。

image.png


変数の宣言の違い

未宣言の変数

未宣言の変数は暗黙的にグローバル変数になる。
厳格モード(strict)を使うことにより,誤ってグローバル変数が作成されてしまうことを防げる。

未宣言の変数への代入
厳格モードでは、偶発的にグローバル変数を作成できないようにします。厳格モードでない場合は、代入文で変数名の綴りを間違えるとグローバルオブジェクトに新しいプロパティが作成され、そしてそれは動作し続けます。厳格モードでは、代入文で偶発的にグローバル変数を作成せずにエラーが発生します

function foo() {
  x = 1;
  console.log(x); // 1
}

foo();

console.log(x); // 1

var

varで宣言された変数のスコープは、その現在の実行コンテキストとそのクロージャであり、その中で宣言された関数、あるいは関数の外で宣言された変数の場合はグローバルになります。
このため,ブロック内等のあらゆる場所で変数が上書きされる恐れがあります。

  • グローバルフィールドでvarを使って宣言するとグローバル変数になる。
// この場合xはグローバル変数
var x = 1;

// ブロック内でグローバル変数を上書きしてみる
if (x === 1) {
  var x = 2;

  console.log(x); // 2
}

console.log(x); // 2に上書きされている
  • 関数無いでvarを使って宣言すると関数内でのみ有効な変数になる。
// 関数内でvarを使う
function foo() {
  var x = 1;
  console.log(x); // 1
}

foo();

console.log(x); // ReferenceError: x is not defined 関数内でのみ有効なため
  • 再代入可能
  • 同名の変数がいても問題ない
var x = 1;
var x = 2; // 再代入可能
console.log(x); // 2

let

let を使用することで、それが使用されたブロックの文または式にスコープを限定した変数を宣言することができます。

  • ブロック内変数のため,スコープ外では使えない。

    for (let i = 1; i <= 3; i++) {
      console.log(i);
    }
    console.log(i) // ReferenceError: i is not defined
    

    比較のためvarで置き換えてみるとスコープ外でも変数が有効なのがわかる。

    for (var i = 1; i <= 3; i++) {
      console.log(i);
    }
    console.log(i) // 4
    
  • 同名変数の再宣言を禁止

    let x = 1;
    let x = 2; // SyntaxError: redeclaration of let x
    

const

letの定数バージョン

  • ブロック内変数
  • 上書き禁止
  • 再宣言禁止

関数の書き方

function宣言

おそらく,最も普通の書き方

function sum(a, b) { 
  return Number(a) + Number(b)
}
result = sum(1, 2)

Functionコンストラクタを使う(非推奨)

eval()のようにコンストラクタを呼び出すことで動的に関数を生成できるのが特徴
(現代であえて使うユースケースは思いつかないのでこんなのあるんだ〜くらいに思っておけばよさそう)

const sum = new Function("a", "b", "return a + b");
result = sum(1, 2)

関数式

function宣言と違い,関数式は無名関数を生成する。

const sum = function (a, b) {
  return (a + b)
};
result = sum(1, 2);

callback関数で使う

コールバック関数は、引数として他の関数に渡され、外側の関数の中で呼び出されて、何らかのルーチンやアクションを完了させる関数のことです。
 Callback function

以下の例はボタン要素に対してクリックイベントが発生した場合に実行する処理を関数式で記述したもの。

button.addEventListener("click", function (event) {
  console.log("button is clicked!");
});

function宣言を使う処理よりも簡潔にかける

function handleClick(event) {
  console.log("button is clicked!");
}

// addEventListener に関数名を渡す
button.addEventListener("click", handleClick);

後述するアロー関数式を使うのが現在では一般的だと思われる。

即時実行関数(IIFE)を使用する例

無名関数を作成してそのまま実行することが可能。
再利用しないことを前提にした書き方になる。

(function () {
  console.log(1 + 2);
})();

// こっちでも良い
!function () {
  console.log(1 + 2);
}();

即時実行関数を使用することでグローバルスコープを汚さずに処理が実行できるのがメリットになる。

昔はJavaScriptのIIFEとモジュールパターンのようにカプセル化のために使用されていたらしい。
現在はclassが使えるので特にこの使い方はしないと思うが参考までに

アロー関数式

アロー関数式は、従来の関数式の簡潔な代替構文ですが、意味的な違いや意図的な使用上の制限もあります。

基本的には関数式を使った書き方の省略形くらいに思っておけば良さそう

const sum = (a, b) => {return a + b};
result = sum(1, 2)

関数式と同様に,callback関数で使用するのがメインの使い方になる

button.addEventListener("click", (event) => {
  console.log("button is clicked!");
});

既に省略した書き方だが,省略記法がある。
e.g. 引数eventを使わないなら省略可能で,処理が1行なら{}も省略可能。

button.addEventListener("click", () => console.log("button is clicked!"));

パッケージマネージャ

npmとyarnの違い

  • npmがnode.jsの公式パッケージマネージャ
  • yarnはMetaが作った代替品

yarnの方が高性能という認識で良さそう。

npmとnpxの違い

npx is a command-line utility that comes with npm 5.2 and higher, and is used to execute packages

npx allows you to run packages without installing them globally, making it easier to use packages without cluttering your global package space.

npmと違ってパッケージをインストールせずに直接実行可能なため,npmと違ってglobaフィールドを汚さずに実行できるのが嬉しい。


セミコロンを文末につけるべきか

JavaScript では、命令は文 (statement) と呼ばれ、セミコロン (;) によって区切られています。
文が単独の行で書かれている場合、文の後にセミコロンは必要ではありません。しかし、行の中に複数の文が必要な場合は、セミコロンで区切る必要があります。
ECMAScript も文末に自動的にセミコロンを挿入するルールがあります (ASI)。(詳しくは、JavaScript の 字句文法についての詳細なリファレンスを参照してください。)
必須ではないとしても、文の後に常にセミコロンを記述することをお勧めします。これによって、コード中にバグが発生する機会を減らすことができます。
文法とデータ構造

自分は以下のように考えている。

  • 自動挿入されるらしいが,想定外のバグが発生する可能性がありそうなのでフォーマッタでつける

    prettierの場合はデフォルトでセミコロンを入れるようになっているが明示的に指定するなら以下

    .prettierrc
    {
      "semi": true
    }
    
  • LLMにコードを食わせる際には;があることで文の区切りがわかりやすいなどのメリットはありそう

31
46
2

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
31
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?