例えば入力された数字をそのまま比較するなどすると、数字が文字列になっていると予期せぬ挙動をする事があります。
// 引数を比較して大きい方を返す関数 var f = function(a, b) { if(a == b) { return "eq" } else { return (a > b)? a : b; } } // 数字を比較 f(5, 55); // 55 f(6, 55); // 55 // 文字列の数字を比較 f("5", "55"); // "55" f("6", "55"); // "6" ヾ(ヽ*ω*) ヌ!? f("50", "55"); // "55" f("56", "55"); // "56" f("56", "550"); // "56" !!! // 片方が数値の場合 f(5, "55"); // "55" f(6, "55"); // "55" f(50, "55"); // "55" f(56, "55"); // 56 f(56, "550"); // "550"
挙動の秘密は文字列の比較にありそうです。
// 単純な文字列を比較 f("a", "b"); // "b" f("c", "b"); // "c" f("a", "aa"); // "aa" f("b", "aa"); // "b" f("aa", "ac"); // "ac" f("ab", "ac"); // "ac" f("ac", "ac"); // "eq" f("ad", "ac"); // "ad" f("ad", "aca"); // "ad"
String
オブジェクトを見てみる
new String("6") => String {0: "6", length: 1, [[PrimitiveValue]]: "6"} new String("55"); => String {0: "5", 1: "5", length: 2, [[PrimitiveValue]]: "55"}
文字列での比較の場合は、文字列の長さ(length
)は考慮されず、先頭の文字から順番に比較していき、同じ値なら次の文字、不等号が成立した時点でその結果を返しているようです。
"55"
のような文字列化された数字どうしだと自動的に数値化されるのではなく、文字列として比較されるようです。
比較する片方が数値の場合は自動的に数値に変換して比較が行われるようです。文字列化された数字の先頭に0x
がついてると16進数として判断されます。
先頭に0
や半角スペースがあってもこれは無視されるようです。
f(5, "055"); // "055" f(6, "055"); // "055" f(56, "055"); // 56 f(5, " 55"); // " 55" f(6, " 55"); // " 55" f(56, " 55"); // 56
文字列化された方の数字にpx
のような単位が付いていると文字列の方が大きいと判定されるようです。
f(5, "5px"); // "5px" f(6, "5px"); // "5px" f(60, "5px"); // "5px" f(600, "5px"); // "5px" f(6000, "5px"); // "5px"
数値として比較したい場合はキチンと数値化しましょう。というお話でした。
[参考]
JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
- 作者: Douglas Crockford,水野貴明
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/12/22
- メディア: 大型本
- 購入: 94人 クリック: 1,643回
- この商品を含むブログ (190件) を見る