概要
JavaScriptの型変換には、暗黙的と明示的があります。具体的には、Number(value)のような関数が明示的な変換にあたります。暗黙的な変換は、異なる型をオペランドでつなぐ処理でどちらかの型に合わせるように変換するようなものとなります。例えば、Stringは数値を期待されるような場合にはNumber型に変換されます。なので、JavaScriptでは型の不正による予期せぬエラーはほとんどの場合で回避されます。
===と==の違い
===を使って比較すると、暗黙的な変換はせずに型も含めた比較になります。逆に==の比較では、必要に応じて暗黙的な変換をした上で比較を行います。実際に比較をしてどのようになるかは、下記のテーブル表が参考になります。https://dorey.github.io/JavaScript-Equality-Table/
StringとNumber
オペランドによりStringからNumberに暗黙的に変換される処理は、Number関数で変換するのと同じプロセスになります。Number関数は、数字を含むStringであれば正しく変換されますが、数字ではない文字列である場合は、NaN(not a number)を返します。Stringに明示的に変換する場合にはString関数を使用します。
1 * '2'
// 2
1 * Number('2')
// 2
Number('012')
// 12
Number('abc')
// NaN
String('abc')
// abc
オペランドが-, *, /, %の場合には、Stringは暗黙的にNumberに変換されますが、+の場合にはNumberがStringに変換されるような挙動となります。
3 - '1'
// 2
3 * '3'
// 9
4 / '2'
// 2
5 % '2'
// 1
1 + '2' + 1
// 121
Boolean型と空文字列をNumberに変換すると下記のようになります。
Number(true)
// 1
Number(false)
// 0
Number("")
// 0
Boolean
Booean型の変換では、下記の値がJavaScriptではfalseとなります。ちなみに、ifやelse ifの比較や||,&&の演算子があると必要に応じて暗黙的の変換が行われます。
Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false
逆に下記がtrueに変換されるものとなります。
Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
Boolean(function() {}) // true
Object(Array含む)
Object型は、暗黙的な変換では[object Object]という文字列に変換されます。Object型はtoString()を継承しており、暗黙的な変換ではこれが呼び出されます。なので、ObjectのtoString関数を上書きすることで、適切な文字列を返すようにすることができます。また、数値への変換の場合には、valueOf()を継承することで変換時に呼び出されるようにもできます。
const foo = {};
console.log("test " + foo);
// test [object Object]
const baz = {
toString:() => "I'm obuject baz"
};
console.log("test " + baz);
// test I'm obuject baz
const hoge = {
valueOf:() => 2
};
console.log(3 * hoge);
// 6
Array型は、暗黙的な変換では、,(カンマ)区切りに連結した文字列に変換されます。
console.log("me" + [1,2,3]);
// me1,2,3
まとめ
JavaScirptの暗黙的、明示的な型変換について整理してみましたが、非常に便利な機能である反面で想定外の動きをする原因にもなったりするので、しっかり理解して実装する必要があると改めて実感しました。
参考
What you need to know about Javascript’s Implicit Coercion
https://dev.to/promhize/what-you-need-to-know-about-javascripts-implicit-coercion-e23
JavaScript type coercion explained
https://medium.freecodecamp.org/js-type-coercion-explained-27ba3d9a2839