吉本集の個人ブログ
Web制作の技術について書いています。たまに日記も書きます。

【JS入門】データには型がある(プリミティブ型について)

2018年1月12日 / category : javascript

プログラムで扱うデータには型がある。

前回の記事で次のコードは推奨されないと解説して終わりました。

sample.js
var str;
str = 'お腹減った';
str = 1000;
console.log(str);

コンソール画面ではエラーは出ておらず問題ないように思います。
では、なぜ推奨されないか。

プログラムで扱うデータには、型(データ型)というものがあります。簡単にいうと、その値はどういうデータなのか分別するものです。
型には大きく分けて2種類の型があります。プリミティブ型とオブジェクト型です。

プリミティブ型について

プリミティブ型とは、プロパティやメソッドを保持しないデータです。
と、言ってもまだ難しいかもしれません。もう少し違う表現をすると、これ以上値を変更することができない不変な値(データ)です。
具体的に見ていきましょう。
JavaScript言語で定義されているプリミティブ型はES6以前までは5つ、ES6になってから1つ追加され6つになりました。

・String型(文字列)
・Number型(数値)
・Boolean型(真偽値)
・Undefined型(undefined)
・Null型(null)
・Symbol型(シンボル):(ES6からできた新データ型)

String型(文字列)

テキストデータがString型です。上で記述したコードでも使用しました。

var str = 'お腹減った';

「お腹減った」というテキストデータをstr変数に代入していますので、str変数の値(データ)はString型ということになります。
型を確かめる方法として、typeof演算子があります。(演算子という言葉が出てきましたが、これはまた別の記事で解説します。)

sample.js
var str;
str = 'お腹減った';
console.log( typeof str );

コンソール画面を開くと、「string」と出ているかと思います。typeof演算子でそのデータ(変数の場合は、代入されている値)が何型なのかを出力してくれます。
これでstr変数の値(データ)はString型ということが確認できました。
ちなみに、変数に代入せずに、次のような記述で値(データ)の型を調べることができます。

sample.js
console.log( typeof 'お腹減った' );

変数に代入した時と同じ結果になったと思います。
プリミティブ型はこれ以上値を変更することができない不変な値(データ)と先に述べました。
「あ」というString型のテキストデータは「あ」以外のデータに変更できません。

Number型(数値)

文字から推測できると思いますが、Number型は数値データです。

sample.js
console.log( typeof 0 );
console.log( typeof 100 );
console.log( typeof -100 );
console.log( typeof 0.5 );

上のコードをコンソール画面で確認すると、全て「number」と出力されているはずです。これら数値データは全てNumber型です。
数値以外に、Number型とされるデータが2つあります。NaNとInfinityです。
NaNとは、非数を表す値です。プログラムでNaNを使用することはあまりないですが、NaN(非数)はNumber型ということを覚えておきましょう。
Infinityとは、無限大を表す数値です。こちらもNumber型になります。

Boolean型(真偽値)

値(データ)としては、true,falseの2つになります。
真偽値とはどういうものかというと、true=真、false=偽を表します。具体的にコードを見ていきます。

sample.js
console.log( 0 === 0 );

コンソール画面を見ると「true」が表示されていると思います。
「===」は演算子です。左辺のデータと右辺のデータが同じものか異なるものかを比較します。
同じデータであれば、true(真)、異なるデータであれば、false(偽)を返します。
上の例を見ると、左辺のデータ「0」と右辺のデータ「0」を比較しています。ともに0という同じデータを比較しているので、true(真)となります。
では、このtrueの型を調べて見ます。

sample.js
console.log( typeof 0 === 0 );

上のコードだと、falseが表示されます。これは意図した結果ではありません。
なぜfalseが表示されてしまったかというと、「===」の演算子が優先され、左辺・右辺がそれぞれ

左辺:typeof 0
右辺:0

となります。
「typeof 0」の結果がnumberですので、
console.log( number === 0 );
という演算子の比較となり、number型は0ではありませんので、falseになってしまう・・・ということなります。
話が脱線してしまいましたが、正しく真偽値を調べるには、次のようなコードとなります。

sample.js
console.log( typeof (0 === 0) );

typeofで調べるデータを()で囲みます。()内の処理はプログラム上、優先されるため()内の比較の結果をtypeof演算子で出力することなります。
0 === 0
これはtrue(真)です。
trueをtypeof演算子で出力すると、booleanが表示されます。
false(偽)をtypeof演算子で出力しても同様の結果になります。

sample.js
console.log( typeof (0 === 1) );

この結果より、true,falseはBoolean型であると確認ができたと思います。

Undefined型(undefined)

undefinedとは、未定義という意味です。データが未定義の場合、そのデータにはundefinedという未定義を表すプリミティブ型のデータが代入され、Undefined型であるということになります。
では、どういうケースがあるでしょうか。具体的にコードをみていきます。

sample.js
var str;
str = 'お腹減った';
console.log( typeof str );

上のコードは先ほども出てきたサンプルコードです。コンソール画面を見るとstringが表示されていると思います。
str変数には「お腹減った」というテキストデータが代入されており、そのテキストデータは、String型ということを先に述べました。
「お腹減った」というテキストデータを代入したのは、2行目のコードです。
1行目の

var str;

この状態ではまだstr変数を定義しただけですので、値(データ)には何も入っていません。
値(データ)が入っていない空の状態ということは、先に述べたように未定義という状態になります。
この未定義という状態が、Undefined型であるということをコードで確かめてみましょう。

sample.js
var str;
console.log( typeof str );

上のコードをコンソール画面で確認するとundefinedが表示されているかと思います。
strという変数を定義しただけで、値(データ)は未定義の状態であるということになります。

Null型(null)

nullとは、何もないという意味です。プログラムで「何もない」とはどういう状態でしょうか。
例えば、次のコードはどうでしょうか。

sample.js
console.log( str );

定義もしていないstrというデータをコンソールで出力してみました。
定義をしていない = 何もない = null
ということにはならないようです。コンソールを見ると「str is not defined」というエラー文が出ていると思います。
この状態は「何もない」という状態ではなく、「定義されていません」ということでエラーになってしまうようです。
ということは「何もない」=「定義はされている」という状態でしょうか。
それであれば、Undefined型で述べた状態になりそうです。

sample.js
var str;
console.log( typeof str );

上のコードは、Undefined型で確かめました。これは、nullではなく、undefinedです。
なぜかというと、strを定義した時点で、自動的にundefinedというプリミティブ型のデータが代入されるためです。
それではnullという状態はどういう状態か。

sample.js
var str;
str = null;
console.log( typeof str );

定義はされているが、nullというプリミティブ型のデータが代入されている状態です。
ただし、コンソール画面を見ると、objectと表示されているかと思います。これはECMAScriptの仕様のバグのようです。

Symbol型(シンボル)

最後のプリミティブ型のデータはシンボルです。これはES6から導入された新しいプリミティブ型のデータです。
使用するケースとして、オブジェクトのプロパティ名で使用することがありそうですが、現段階で説明すると難しくなりそうですので、今後、使用するサンプルと一緒に解説できればと思っています。
ここでは型を確かめるコードのみを記述しておきます。

sample.js
var sym = Symbol('sample');
console.log( typeof sym );

プリミティブ型を解説するので、記事が長くなってしまいましたので、もう一つのオブジェクト型については次の記事で解説しますが、この記事の最初に記述した下記の問いについて

sample.js
var str;
str = 'お腹減った';
str = 1000;
console.log(str);

上のコードが推奨されない理由
他の言語では、型の違う値の変更ができません。上のコードでは、str変数にまずString型のテキストデータ「お腹減った」を代入しています。
この時点で、str変数の値はString型となります。次に、Number型の数値データ1000を代入しています。
str変数の値は既にString型ですが、次にNumber型のデータに変更しようとしています。
JavaScriptの言語は「暗黙的な型変換」を自動的に行ってくれる言語です。簡単にいうと、自動的に型変換を行ってくれる便利な言語ということです。
そのため、エラーが起きず問題なく処理されます。
ただし、意図しない「暗黙的な型変換」を行ってしまうケースも出てくるため、基本的には型変換のないようなプログラムを記述することを推奨します。