BLOG.tass.io

JavaScriptで「プリミティブ型の数値」のメソッドを呼ぶ

2014-04-06

ちょっとした読み物ですが、A Drip of JavaScriptに面白い記事がありましたので、意訳ですが紹介します!

“A Drip of JavaScript"は、毎回おもしろい記事が配信されています。
ぜひこちらのメルマガに登録してみてくださいな。
筆者のジョシュアのTwitterもフォローおすすめです!


JavaScriptではほぼ全てがオブジェクト

JavaScriptではほとんど全てのものが、オブジェクトのように動作します。

例えばコレ

var numOfIs = "Odin".match(/i/).length;

// 出力結果: 1
console.log(numOfIs);

var strOfTrue = true.toString();

// 出力結果: true
console.log(strOfTrue);

ここでは2つの例をあげてます。

プリミティブな文字列'Odin'が、match()メソッドを持っていて呼び出すことができています。
固定の文字列だけど、ちゃんとオブジェクトなのです。

プリミティブなBool値である true さえも、ちゃんとtoString()メソッドを持っていて呼び出せています。
ヘエー!( ゚ Д゚)

数値もオブジェクト?

それでは、プリミティブな数値型はどうでしょう?

// SyntaxError: Unexpected token ILLEGAL
var meaningOfLife = 42.toString();

アウチ!シンタックスエラーになってしまいました。
さすがに駄目なのでしょうか?

しかし、ドットではない呼び出し方を使うと…

var meaningOfLife = 42["toString"]();

// 出力結果: "42"
console.log(meaningOfLife);

呼べました!٩(๑❛ᴗ❛๑)۶
どちらも同じように"toString"という名前のメンバーにアクセスしているはずなのですが、何が違うのでしょう?

ちょっと別の例で。 ドットでもメソッド呼び出しができる数値もあります。

var platform = 9.75.toString();

// 出力結果: "9.75"
console.log(platform);

呼べるんですねー。
いったいなにが起こっているのでしょうか?

数値とドットの解釈

これは、JavaScriptエンジンがコードを解析する際の「ドットの解釈」が関連しています。

42.toString()の場合は、ドットの意味するところが 潜在的に曖昧 です。
『小数点の区切り』 を意味しているのか、
『オブジェクトのメンバへのアクセス』 を意味しているのか2通りの解釈ができてしまいます。
JavaScriptは”整数に続くドットは浮動小数点の部分を表すもの”として優先的に解釈をしようとするので、
42.toString()はドットに続くものが数字ではないと判断し、シンタックスエラーを発生させていたのでした。

9.75.toString()の場合は、先に浮動小数点の一部が出現しているので、2つ目のドットはオブジェクトメンバのアクセスだと断定できます。
そのため、シンタックスエラーにならずに正常動作したというわけです。

パーサーが混乱しない数値オブジェクトの扱い方

では、パーサーがドッド表記を間違えないためにはどんな書き方をすれば良いのでしょうか?
以下に3つの方法を取り上げます。

// 方法(1)
var meaningOfLife = 42..toString();

ドットドット!
これは構文的に42.0.toString()と同等なので、正常に動作します。
ですが、意味が読み取りづらいですし、ちょっと気持ち悪いですね…。

// 方法(2)
var meaningOfLife = 42 .toString();

?!こちらは一見しただけでは混乱してしまいます。
ドットの前に空白文字を置いただけですが、何が起こっているのでしょう?

これは、 「整数部分と小数部分の間には空白文字を含めることができない」 というJavaScriptの構文を利用することで、ドットに続くのはオブジェクトのメンバーと断定させています。
でもこの表記ではコードが読みづらくなり、他の開発者が誤って「あれ?無駄な空白があるよ?」と誤認して、修正しちゃいそうですよね…。
これは実際のプロダクトコードで使うのはやめたほうがよさそうです(;^ω^)

// 方法(3)
var meaningOfLife = (42).toString();

これまでの例を見てきたのでもうおわかりかと思いますが、カッコがパーサーが混乱するのを防いでくれています(^o^)/

これが、プロダクトコードで使う場合のお気に入りの方法です。
他の例にくらべて読みやすいですし、意図したとおりにtoString()が正常に呼び出されます。

もし使うことがあれば(まずないと思いますがw)、ご参考までに。

元記事:A Drip of JavaScript
A Drip of JavaScript #34: Numbers and JavaScript’s Dot Notation
http://us6.campaign-archive1.com/?u=2cc20705b76fa66ab84a6634f&id=3a857e5967


Michael Kuroneko

Written by Michael Kuroneko. Follow me on twitter, github.