いつだったか翔泳社が Kindle セールをやっていて、目にとまった『Effective JavaScript JavaScriptを使うときに知っておきたい68の冴えたやり方』を購入して読んでいる。

Effective JavaScript JavaScriptを使うときに知っておきたい68の冴えたやり方
- 作者: Devid Herman
- 出版社/メーカー: 翔泳社
- 発売日: 2013/04/13
- メディア: Kindle版
- この商品を含むブログ (3件) を見る
大学の研究や仕事で JavaScript さんとふれあう機会はあったのだけど、いまいち理解してない感じで、コーディングしていていつももやもやしていた。仕事でぱぱーっとコーディングしてるだけでは、挙動が分からな いという奥深さ(意味不明さとも言うのかも)に興味を持っていたので、非常に楽しく読んでいる。「なんか JavaScript って Lisp に近いモノを感じるなぁ」と最近思っていたんだけど、さらにその思いは強くなった(Lisp 大して知らないけど)
せっかくブログを始めたし内容をメモしておこうと思う(すぐ忘れるし)。幸い、この本は項目に別れて書かれていメモしやすい。
第一章:JavaScript に慣れ親しむ
項目1:どの JavaScript を使っているのかを意識しよう
その名の通り。歴史的?政治的?経緯から、巷にいろいろな JavaScript 実装があふれているので、どのバージョンの仕様向けなのか、どの実装向けなのか、意識して書くようにしよう。
できれば strict モードを使う。strict モードを有効にする strict ディレクティブ("use strict;")は、ファイルの先頭か関数の先頭でしか認識されない(変数スコープの挙動に近い)。この性質のために、複数の js ファイルを連結すると問題が起こる場合がある。そのため、即時関数式(IIFE, Immedeiately Invoked Function Expression)で包んでローカルスコープを作った方がいい。
// file1.js function() { "use strict";
// ... code ... }();
ちなみに、strict ディレクティブが文字列なのは後方互換性のため。strict ディレクティブが実装されていない JavaScript 実装の場合では文字列を評価するだけなので問題が起こらない(こういう後方互換性への思いやりの精神は大事にしたい)
項目2:JavaScript の浮動小数点数を理解しよう
JavaScript にいわゆる Int 型はない。数を表すのは Number 型で中身はIEEE754 の倍精度浮動小数点数である(いわゆる Double 型)。
ちなみに、倍精度浮動小数点数は 53 ビット精度の整数を表現することができる。IEE754 の倍精度は、
- 符号:1ビット
- 指数部:11ビット
- 仮数部:52ビット
なので、仮数部と符号ビットを利用して 53 ビット精度の整数が表現できる(小数点位置53 桁の移動は11ビット内で表現できるし)。一つ前の記事で「以前、調べたときに『64 bit 浮動小数数点数で 64 bit 整数のすべてを表現できる』って結論付けたの間違いだな」って書いたけど、『32 bit 整数のすべてを表現できる』って結論付けたことを思い出したので、昔の俺は間違ってなかった。
ビット毎の数値演算を行うときは「ビッグエンディアンの2の補数表現(いわゆるInt 表現)」に変換されてから演算が行われる点に注意する。ビット毎の数値演算しか行われない変数は、最適化のため内部的に Int 表現で保持されていたりするらしい。
項目3:暗黙の型変換に注意しよう
JavaScript は演算子に合うように値の型を勝手に変換してくる。この動作を『型に値を強制(coerce)する』という。変換規則が細かくて、いちいち覚えてられないので、邪悪そうな実例と根拠だけ列挙しておこう。
3 + true; // => 4
true が Number 型の 1 に変換されるので 4 になる
1 + 2 + "3"; // => "33"
加算は左結合なので、1 + 2 => 3。Number と String の加算では Number が String に強制されるので 3 + "3" => "33" になる
1 + "2" + 3; // => "123"
1 + "2" => "12" となり、"12" + 3 となる。3 は String に強制されるので "123" になる
めんどくさいのが NaN。IEEE の Not a Number に対応している値。規格上の定義が「それ自身と等しくない値」なので、
var x = NaN; x === NaN // => false
となる。標準の isNaN() もあてにならない(Nan に型を強制してしまう)ので、NaN かどうかを調べるには「自身と比べて等しくない」という性質を利用する。
var x = NaN; x !== x // -> true
オブジェクトはたいてい String か Number に型を強制される事が多く、その際、toString() と valueOf() が呼ばれる。ただし、そのオブジェクトがどちらに値を強制されるかは不明(プロパティ順だったか?知っていたら教えてほしい)。
最後はブール値に値が強制される話。以下の値はすべて false に強制される。逆に下記以外はすべて true となる。
false, 0, -0, "", NaN, null, undefined
0 や "" が false と評価される点に注意しなければならない。以下のようにして isUndefined を定義すると 0 や "" が undefined として判定されてしまう
define isUndefined(x) { return !x } isUndefined(1); // => false isUndefined(undefined); // => true isUndefined(0) // => true isUndefined(""); // => true
ほんとうは3章の途中まで読み終わっていて、1章のまとめを書きたかったのだけど疲れたのでここまで。なるべく、小さいことを積み重ねて大きくしていこうと思う。