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 の型に対する認識が違ったらしい

Last updated at Posted at 2023-05-22

きっかけ

「型を確かめるぜ」ということでこの記事を書いたところ、「それ規格においては型って言わないで?」とコメントで指摘を受け発覚。

やろうとしていたのは、何らかのオブジェクトについて、「それが Array とか Blob とか何なのかを確かめたい!」ってこと。なぜなら typeof だけだと、number や string はわかるけど、Array や Blob などは全部 object って出てきてしまうから。

「この object をもっと詳しく確かめたい!」というのが先の記事の内容になるわけです。ところが、ECMAScript 上では Array型 Blob型 は存在しない ので、全部まとめて型と表現したのは、たしかに誤りだったのです。

改めてしっかり調べ、発見したことを書いていきます。

本当の型は 7種 (+1) だけ

※ 個数は ECMAScript 2024 時点

typeof 演算子によって、任意のオブジェクトのプリミティブ型を知ることができます。

このプリミティブ型が、規格上の本当の型と呼べるものです。

undefined, null, boolean, number, bigint, string, symbol の 7つの型が存在し、それ以外の Array とかは「その他のオブジェクト」ということになります。

冒頭に述べた「Array型 Blob型 は存在しない」というのはこのことです。

function型も存在しない

typeof に何らかの関数を渡してやると、function と返ってきます。しかし、ここだけちょっと例外的で、function 型も存在せず、オブジェクトの 1種です。

Array は「標準組み込みオブジェクト」

MDN で Array のページを見てみましょう。

確かに、「Array型」とはどこにもありません。ドキュメントのカテゴリを見てみると、どうやらこれらは「型」でなく「標準組み込みオブジェクト」という区分で呼ぶことができそうです。

下部に仕様書 (ECMAScript) へのリンクが貼られています。覗いてみましょう。

Arrays are exotic objects that give special treatment to a certain class of property names. See 10.4.2 for a definition of this special treatment.

「See 10.4.2」とあって、その 10.4章は・・・「Built-in Exotic Object Internal Methods and Slots」。つまり、「ビルトイン (= 標準で組み込み) のオブジェクト」のようですね (雑解釈)。

その他の標準組み込みオブジェクトもついでに見てみます。

関数もオブジェクトの一種なので、encodeURL() などの標準関数も「標準組み込みオブジェクト」として載っています。

Blob は・・・API?

再び MDN、今度は Blob を見てみます。

おや、カテゴリが「標準組み込みオブジェクト」ではありません。仕様書の欄は・・・?

3. The Blob Interface and Binary Data

ECMAScript ではなく W3C というところでの規定のようです。

Web API の 1つ、File API の規定上において、ファイルデータ (バイナリデータ) のやりとりをするインターフェースとなるオブジェクト、的な。

JavaScript を策定しているとこの話

Ecma International という団体により、JavaScript の文法は規定 (標準化) されています。この団体が発行している仕様書は、ECMAScript 20?? と呼ばれます。(?? は発行年が入り、仕様書のバーションを示している。)

さて、ECMAScript では JavaScript の文法を規定していますが、Web API は規定されていません。Web API は、主に W3C と WHATWG という団体によって規定されています。

・・・なんだか色々でてきてややこしいですね。

  • 文法の規定は:
    • こう書くと変数になる、関数になる、演算する、それからこう書くとこう動くオブジェクトが最初からある (など)
  • Web API の規定は:
    • こういう関数 (またはオブジェクト) があって、そこにこういう引数を入れると、こういうデータやりとりがされる

ブラウザは、ECMAScript に示されている文法に沿って、JavaScript を解釈するように作られます。そこに加えて、Web API で規定されている関数やオブジェクトが、規定の通りに実装されます。

こうして、動きのある Web ページだったり、ファイルの読み込みやデータの送受信ができたりする、ブラウザ (JavaScript の実行環境) ができあがるのです。

ちなみに、Ecma International は主に情報関係で、W3C と WHATWG は主に Web 関係で、他にも色々な事項の標準を策定しています。

Ecma International (ECMAScript) により JavaScript の文法は規定されている・・・と記しましたが、CommonJS というプロジェクトによっても JavaScript の規定が作られています。

ブラウザでは ECMAScript を動かすことができ、CommonJS は動きません。

どちらも JavaScript で、基本構文はだいたい同じなのですが、アクセスできる機能などが異なります。誕生した経緯などについては、記事の範囲を超えるので別解説に委ねます。

まとめ

  • 本当の型は、オブジェクト除いて 7種だけ
  • 関数だとか色々な機能を提供してくれるヤツは全部オブジェクト
  • Array とか標準関数とかは「標準組み込みオブジェクト」、あるいは「Web API から提供されているオブジェクト

JavaScript は策定しているところが 1箇所じゃないとかあって、めっちゃややこしい言語ですねぇ・・・。

もう一点 - プリミティブ型が object に化けるとき

プリミティブ値は、メソッドなどを持ちません。

「・・・あれ?じゃあ文字列に "hello".split() とかできるやつは何なの?」

あれは、プリミティブラッパーオブジェクトに暗黙的に変換されてから実行されているものです。

/* これはプリミティブ値 */
let v = "hello";

/* メソッド呼んだりしたら暗黙的に変換 */
v.toString();
// 'hello'
(2024/10/23 編集) これ変換されない例と思ってたけど・・・
/* 変換されない例 (・・・って扱いでいいと思う、多分) */
3.toString();
// Uncaught SyntaxError: Invalid or unexpected token

/* 変換される例 */
let v = 3;
v.toString();
// '3'

(追記)

@juner さんより、コメントにて指摘いただきました。

3. までが数値リテラルと解釈され、その後に toString() が並んで、「なんか文法違うで?」というエラーだったようです。プリミティブラッパーオブジェクトへ変換されないわけでなく、変換の手前の問題だったようです。

(追記ここまで)


プリミティブラッパーオブジェクトに明示的に変換するには以下の通り。

let obj = new Number(3);
obj.toString();
// '3'

プリミティブラッパーオブジェクトについて、より詳しいことは検索してみてください。(気力切れ)

てか、この言語ほんとに型の話ややこしい・・・。

3
2
3

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?