ECMAScript 5の新機能

2021/02/14更新

目次

概要

ECMAScript 5(ES5)は、2009年に公開されたJavaScriptの標準仕様である。ES5で新たに登場した機能は、今となってはどのブラウザも対応し、見慣れたものとなったが、ここに改めてまとめておく。

なお、ES5の次の仕様として、ECMAScript 2015(ES6、ES2015)、ECMAScript 2016(ES7、ES2016)、ECMAScript 2017(ES8、ES2017)が登場している。

新しい機能

strictモード

これまで曖昧にされてきた処理に対して、明確に禁止にしたり、エラーを発生させたりすることで、ミスとして気づきやすくし、また将来の新しいJavaScriptへの移行をスムーズにするためにstrictモードが導入された。

関数冒頭で'use strict';と記述すると、その関数スコープ内がstrictモードになる。

const myFunc = function() {
    'use strict';
      :
};

strictモードの下では、従来と比較して以下のような変化が起きる。これらは、いずれも意図しない変数やオブジェクトの変更や汚染を防止するのに役立つ。

  • 未宣言の変数への代入ができなくなる。

  • 0で始まる旧式の八進数リテラルが使えなくなる。

  • 削除不可や変更不可のプロパティに対する削除や代入文が、明確にエラーとなる。

  • with文の使用は禁止となる。

  • arguments.calleeの使用が禁止となる。

  • グローバル関数とインスタンスメソッド以外の関数内でのthisundefinedとなる。

  • オブジェクトリテラル内で同名のプロパティの複数定義が禁止される。

  • 関数引数名の重複が禁止される。

  • 単純変数に対するdeleteができなくなる。

進化した記法

オブジェクトリテラルの末尾にカンマを残してしまうと従来は文法エラーとなっていたが、これが許容される(無視される)ようになった。

const obj = {
    hoge: 1234,
    fuga: 5678, // ← この最後のカンマがOKになった。
};

文字列の1文字ずつを取得するのに、従来はcharAt(n)などを使っていたが、配列のように[n]を使ってアクセスできるようになった。ただし、取得のみで変更するには使えない。

const char = 'ABCDE'[3]; // 'D'

アクセサプロパティ

常にゲッター関数・セッター関数を通して値の取得・設定が行なわれる、アクセサプロパティを定義できるようになった。

データプロパティとアクセサプロパティを参照。

その他

グローバルのundefinedは、これまで別の値を代入してしまうことができたが、書き込み禁止となった。ただし、予約語ではないため、ローカル変数などの名前にすることは引き続き可能である(当然、推奨はされない)。

undefined = 'hoge'; // エラー

追加されたメソッド

Object

Objectには、オブジェクトやプロパティを作成したりするための関数が多数追加されている。

別記事「JavaScriptのプロパティとプロトタイプ」も参照されたい。

// プロトタイプを指定して空のオブジェクトを作成
// (=コンストラクタを通さないインスタンスを作成)
const obj = Object.create(MyClass.prototype);
console.log(obj instanceof MyClass); // true

// オブジェクトのプロトタイプを取得
console.log(Object.getPrototypeOf(obj) === MyClass.prototype); // true

// 属性を細かく指定してプロパティを定義
Object.defineProperty(obj, 'hoge', {
    value: 100,
    enumerable: false,
    writable: true
});

// 自分自身の列挙可能プロパティの名前の配列を返す
const enumProps = Object.keys(obj);

// 列挙不可能なものも含めた自分自身の全てのプロパティの名前の配列を返す
const allProps = Object.getOwnPropertyNames(obj);

// プロパティの定義情報を返す
const descr = Object.getOwnPropertyDescriptor(obj, 'hoge');
console.log(descr.enumerable);

Object.keys()は、ES2015以降では、for-of文と組み合わせると便利に使うことができる。

Object.defineProperty()と同様にして、複数のプロパティを同時に定義できるObject.defineProperties()が存在する。さらに、後のES2017では、Object.getOwnPropertyDescriptor()と同様にして、全てのプロパティの定義情報を一度に取得できるObject.getOwnPropertyDescriptors()が登場した。

Object.preventExtensions()Object.seal()Object.freeze()を使うと、オブジェクトの変更に対して制限をかけることができる。

// プロパティの追加禁止
const obj = { hoge: 1111 };
Object.preventExtensions(obj);
obj.hoge = 2222; // OK
obj.fuga = 3333; // エラー

// プロパティの削除禁止
Object.seal(obj);
delete obj.hoge; // エラー

// プロパティの変更禁止
Object.freeze(obj);
obj.hoge = 4444; // エラー

Object.seal()は、全てのプロパティのconfigurable属性をfalseにする。Object.freeze()は、全てのプロパティのwritable属性をfalseにする。表にすると、以下のようになる。プロパティの属性も参照。

プロパティの追加

プロパティの削除と属性の変更

プロパティの値の変更

Object.preventExtensions()

禁止

可能

可能

Object.seal()

禁止

禁止

可能

Object.freeze()

禁止

禁止

禁止

それぞれのメソッドが実行されたかどうかを確認できるObject.isExtensible()Object.isSealed()Object.isFrozen()が存在する。

Array

Arrayオブジェクトには、配列操作を便利にするメソッドが多数追加されている。

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

// 配列かどうかの判定
console.log(Array.isArray(arr)); // true

// 値の検索
console.log(arr.indexOf(2)); // 1
console.log(arr.indexOf(6)); // -1

// 全ての要素が条件を満たすかどうか
const isSmall = arr.every(function(val, index, arr) {
    return 10 > val;
}); // true

// 条件を満たす要素が存在するかどうか
const hasEvenNumber = arr.some(function(val, index, arr) {
    return val % 2 == 0;
}); // true

// 各要素についてくり返し
arr.forEach(function(val, index, arr) {
    console.log(val);
});

// 各要素についてくり返し、戻り値から新しい配列を作成
const arr2 = arr.map(function(val, index, arr) {
    return val * 2;
}); // [2, 4, 6, 8, 10]

// 条件を満たす要素からなる新しい配列を作成
const arr3 = arr.filter(function(val, index, arr) {
    return val % 2 == 1;
}); // [1, 3, 5]

// 隣り合う要素ごとに順に処理
const sum = arr.reduce(function(a, b, index, arr) {
    return a + b;
}); // 15
// ※以下が行なわれる。
// 1+2=3   0番目の要素と1番目の要素について処理
// 3+3=6   直前の結果と2番目の要素について処理
// 6+4=10  直前の結果と3番目の要素について処理
// 10+5=15 直前の結果と4番目の要素について処理
// → 15

この他、arr.indexOf()を後ろから探索するarr.lastIndexOf()arr.reduce()を最後の要素から行なうarr.reduceRight()がある。

String

trim()は、文字列の前後の空白を削除した文字列を返す。

// 前後の空白の除去
console.log('   hoge   fuga   '.trim()); // 'hoge   fuga'

Function

Functionオブジェクトには、bind()メソッドが追加されている(未稿)。

Date

Dateオブジェクトには、些細であるが、非常に便利な2つのメソッドが追加されている。

// ISO 8601形式の文字列化
console.log(new Date().toISOString());
// 2020-12-31T23:59:59.999Z

// 現在時刻のUnix Timeの取得
console.log(Date.now());
// 1609459199999

JSON

これまではeval()するかライブラリ等を使うしかなかったJSONに、ついに正式に対応した。

// JSONのパース
const obj = JSON.parse('{"hoge":1234,"fuga":5678}');
console.log(obj.hoge); // 1234
console.log(obj.fuga); // 5678

// JSON化
const jsonstr = JSON.stringify({
    hoge: 1234,
    fuga: 5678
});
console.log(jsonstr); // {"hoge":1234,"fuga":5678}

パースするJSON文字列が不正な場合は、例外が投げられる。

関連記事

外部リンク