JavaScriptにJavaのようなequalsメソッドを作成する
JavaScriptでは等価比較を行う際に、== 、=== の2種類のequalによる比較演算子が用意されており、== の方は、型はチェックせず値が正しいかどうかの判断しかせず、 === の方は型をチェックして値の比較演算を行いますよね。=== の方はより厳密な演算子で、JavaScriptのテクニック本でも === の使用を進めています。 (※PHPでも同じ比較演算子が導入されています。)
var data = "";
// 0でもマッチしてしまう!
if (data == 0) {
console.log("Match");
}
// これだとマッチしないからGood
if (data === 0) {
console.log("Match");
}
このようにequalの数(2個と3個)によって処理がかわるというのは、ミスを誘因しやすく、それによりBugの原因になったりする危険性があるので、不満がありました。構文チェックツール(JSLint)でチェックして、equalのミスコードをチェックするというのも手なのですが、頻繁にチェックするのは面倒です。そもそも間違いやすい比較演算子が問題なんだと思っています。。。(汗)そこでJavaでの等価比較メソッドである、equalsメソッドと同じようなJavaScript用のequalsメソッドを作成することにしました。 === とコーディングする箇所を誤って == としてしまったりするのは人間である以上、起こりえるものなので、別の名称のメソッドを用意して、イージミスを防ぎ素敵なJavaScriptライフを送りたいと思います。
期待する実装形式は下記の感じです
data1の型とdata2型の厳密比較演算を行いたい!
if (data1.equals(data2)) {
// なんらかの処理
}
equalsメソッドの実装内容
個人的によく使用するStringオブジェクトのprototype chainに実装してみます。まずは、this == paramで値の比較を行います。そこで値が同じであれば、次に同じstring型かどうかを、typeof演算子で型のチェックを行います。特に目新しいコードでもなく、普通です。。。
String.prototype.equals = function(param) {
if (this == param) {
return (typeof param === "string" ? true : false);
}
return false;
};
Stringオブジェクトのprototype chainの実装部分でthis === paramと行ったほうが単純そうに思うかもしれませんが、thisはobject型ですので、期待通りの動作はしません。
String.prototype.equals = function(param) {
return (this === param ? true : false);
};
thisとparamがマッチすることはなく、永遠にfalseがかえってしまいます
Rhinoベースでの環境ではちょっと注意が必要
Rhino1.7の環境で確認したのですが、RhinoやRhinoベースのサーバーサイドJavaScriptの環境では、すでにequalsメソッドが存在しているので注意が必要です。動作的には == 比較演算子と同じ、値の比較しか行いません。実際にRhino1.7のソースを解析した結果を晒しますと、下記になります。
src/org/mozilla/javascript/NativeString.javaを参照
このlineの前後に、巨大なswitch case文があり、Rhinoで使用可能なStringオブジェクトのメソッドが定義されています。line:190にequalsメソッドを確認できます
(1) org.mozilla.javascript.NativeScript line: 190 ・ ・ case Id_link: arity=0; s="link"; break; case Id_anchor: arity=0; s="anchor"; break; <b>case Id_equals: arity=1; s="equals"; break;</b> case Id_equalsIgnoreCase: arity=1; s="equalsIgnoreCase"; break; case Id_match: arity=1; s="match"; break; ・ ・
このlineではequalsメソッドの実装内容が記述されています。しかしScriptRuntime.toStringで値を全て、JavaのString型に変換してしまっているので、型の比較は行ってくれません
(2) org.mozilla.javascript.NativeScript line: 367〜374
case Id_equals:
case Id_equalsIgnoreCase: {
String s1 = ScriptRuntime.toString(thisObj);
String s2 = ScriptRuntime.toString(args, 0);
return ScriptRuntime.wrapBoolean(
(id == Id_equals) ? s1.equals(s2) : s1.equalsIgnoreCase(s2));
}




