あるサイトでおもしろコードを見つけました(恥ずかしい間違いなので、サイト名は伏せておきます)。「スタート」「ストップ」ボタンを押すと、2つのボタンが交互に有効・無効に切り替わるサンプルです。
<body> <input type="button" value="スタート" id="start"> <input type="button" value="ストップ" id="stop" disabled> </body> <script language="javascript"> document.getElementById("start").onclick = function() { // 無効化 document.getElementById("start").disabled = "true"; // 有効化 document.getElementById("stop").disabled = ""; }; document.getElementById("stop").onclick = function() { document.getElementById("start").disabled = ""; document.getElementById("stop").disabled = "true"; }; </script> ※これ以降のコードは、以下の2行があると仮定してください。
var elm1 = document.getElementById("…"); var elm2 = document.getElementById("…"); 無効化・有効化の部分のみ抜き出すとこんな感じです。
// 無効化 elm1.disabled = "true"; // 有効化 elm2.disabled = ""; どの部分が面白いか分かりますでしょうか?
disabledプロパティはboolean型です。そのため通常設定する値は、boolean型の「true」か「false」です。つまり素直に書くなら以下になります。
// 無効化 elm1.disabled = true; // 有効化 elm2.disabled = false; 「"true"」などと書いてしまうと文字列型になってしまうため本来はNGです。しかしJavaScriptで文字列型をboolean型に代入しようとすると暗黙的に型変換が起こります。その際、1文字以上の文字列は内容に関わらずtureに、0文字の文字列(空文字)とnullはfalseに変換されます。このコードは文字列型からboolean型に変換する際の特性をうまく利用して、(偶然にも)正しく動いています。
おそらくは知識不足によって生まれたコードなのだと思いますが、いろいろ可能性のある興味深いコードだと思いました。私はこのコードに触発され、いろいろなコードを書いてみました。
一見どちらも空文字に見える。
// 無効化(1文字の文字列なのでtrue) elm1.disabled = " "; // 有効化(空文字なのでfalse) elm2.disabled = ""; 一見どちらもfalse。
// 無効化(1文字以上の文字列なのでtrue) elm1.disabled = "false"; // 有効化 elm2.disabled = false; その他の型からboolean型への変換の特性を利用した分かりにくいコードもいろいろ書いてみました。難読化に使えそうです。
NaNの特性を利用。
// 無効化(NaNはbooleanにするとfalse。その否定なのでtrue) elm1.disabled = !NaN; // 有効化(NaNは何と比較してもfalse) 記号で表現。
// 無効化(オブジェクトなのでtrue) elm1.disabled = {}; // 有効化(空配列なのでfalse) elm2.disabled = []; // 無効化(falseの値を持つBooleanオブジェクトなのでtrue) elm1.disabled = Boolean([]); // 有効化(空配列なのでfalse) elm2.disabled = []; // 無効化(まず、右辺が配列オブジェクトでbooleanに変換するとtrue、その否定でfalse。 // 左辺が配列、右辺がbooleanの比較なので、両辺を数値に変換し比較。両辺とも0なのでtrue。) elm1.disabled = ([] == ![]); // 有効化(両辺を配列として比較している。2つは異なる配列であるためfalse) elm2.disabled = ([] == []); // 無効化(オブジェクトをbooleanに変換するとtrue。両辺ともその否定でfalseなので、式はtrue) elm1.disabled = (!{} == !{}); // 有効化(両辺をオブジェクトとして比較している。2つは異なるオブジェクトであるためfalse) elm2.disabled = ({} == {});配列やオブジェクトは応用すると遊べますね。※配列・オブジェクトの比較結果については、こちら「JavaScript等価演算子(==)」を参考にしてください。 軽いだまし。
// 無効化(長さのある配列であるためtrue) elm1.disabled = [false]; // 有効化(voidはどんな引数を与えてもundefinedを返す。それをboolean型にパースするとfalse) elm2.disabled = void(true); 数値型からboolean型の変換では、「0→false」「0以外→true」になります。この特性を利用。
// 無効化(右辺がtrue) elm1.disabled = 1 + 1; // 有効化(右辺がfalse) elm2.disabled = 1 - 1; boolean型から数値型の変換では、「true→1」「false→0」になります。この特性も利用。
// 無効化 elm1.disabled -= 1; // 有効化 elm2.disabled -= 1; さらにシンプルに。
// 無効化 elm1.disabled--; // 有効化 elm2.disabled--; これは自分でもなかなか秀逸ではないかと思います。JavaScriptの型変換の特性をうまく利用し、ごくシンプルに最少の文字数で表現しています。変に難読化しようとしているわけではなく、JavaScriptの基礎的な部分を把握していれば理解できるコードになっています。
このページの内容は本質的にはdisabledの問題ではなく、単に「boolean型へ変換した際に、trueになる値とfalseになる値」のバリエーションともいえます(最後の2例を除く)。しかしdisabledとからめた事により面白みが増しているように感じます。いかがでしょうか?
2012/10/27
|
Code Tips >