まず初めに
最近よく、
<a href="javascript:void(0)" onclick="なんちゃらー">リンク</a>
というHTMLのコードを見かけるようになりました。
しかし、void関数の意味を理解せずに適当に使っている人が多く、
<a href="javascript:void(0);alert('hogehoge');" onclick="~">リンク</a>
のような、全くもって意味の無い使い方をしている方も見受けられます。
なので、本記事では__void関数の仕組み、利用目的、利用方法などについて解説したいと思います__。
void関数ってなんぞや?
まず、void関数について説明したいと思います。
void関数は、引数に何を渡しても必ずundefinedを返す関数です。
説明は以上です。
、というのも、void関数は非常に単純な関数で、「真のundefined」を取得する事を目的に作られています。
いや真のundefinedってなんだよ
実は、古いJavaScriptエンジンのundefinedにはreadonly属性が付いておらず、自由に上書き可能なのです。
console.debug( undefined ); // undefined
let undefined = 1234;
console.debug( undefined ); // 古いjsエンジンだと、「1234」と表示される
これは困りましたね。。
「定義されていない」という事を表すundefinedを勝手に上書きされてしまったら、定義されていないかどうか判別するのにいちいちtypeof演算子を利用しないといけなくなってしまいます。
そこで登場したのがvoid関数です。
この関数は、undefinedでは無く、本当の意味での「真のundefined」を返してくれます。
でも何のためにaタグでJavaScriptURIを実行する際にvoid関数を使うんだよ
ここを理解していない方が多いみたいです。
javascript: から始まる URI をサポートしたブラウザに於いて、それは、URI 内のコードを評価し、戻り値が undefined でなければ、返された値にページコンテンツを置き換えます。void 演算子は、undefined を返すために使用できます。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/void
はい、こーいう事です。
つまり、__aタグのリンク先がJavaScriptURIの時、その式がundefined以外を返した場合に、その内容をブラウザ上に表示するという仕様__なのです。
具体的には、
<script>
function hogehoge() {
// 何かの処理
return "成功";
}
</script>
<a href="javascript:hogehoge();" onclick="alert('クリックされました!');">
example
</a>
こんなコードがあった時に、IEなどの一部のブラウザでは「example」をクリックした際、アラートが表示された上でドキュメントが「成功」という2文字だけに置き換わってしまいます。その際、「example」のボタンなども全て削除されて上書きされます。
意味不明な仕様ですよね。
既に、ChromeなどのChromiumベースのブラウザでは廃止されました。
でも、今回は紹介出来ませんが、この仕様が役に立つ場合もあります。
誤用
冒頭でお見せした、このコード
<a href="javascript:void(0);alert('hogehoge');" onclick="~">リンク</a>
の何がダメなのか、お分かりになりましたでしょうか?
このaタグのhref先の式が実行された時に返される値は、最後のalert関数の戻り値の「true」です。
なので、JavaScriptURIに対応しているバージョンのIEでこのコードを実行すると、画面の左上に小さくtrueと表示されてしまいます。
では、どうすれば良いのか、、。
と言われましても、__普通にundefined__を返せば良い話です。
おっと、NGワードを使ってしまいました。
NGワードとは、__「普通に」__です。
というのも、昔のJavaScriptエンジンではundefinedを上書き出来てしまうとお伝えした通り、undefinedが別の値に上書きされてしまっていたら、このコード
<a href="javascript:undefined" onclick="~">リンク</a>
はundefinedでは無く、その「別の値」を返してしまい、画面の左上に小さく何か表示されてしまいます。
なので、void関数は__真のundefined__を返すためにあると考えれば、冒頭のコードは
<a href="javascript:void(alert('hogehoge'));" onclick="~">リンク</a>
このように直す事が出来るはずです。
最後に
正直、JavaScriptURIは今更使用するべきではありません。
というのも、XSSの脆弱性の原因になりやすいからです。
XSS対策で有名な、Content-Security-Policyヘッダーを利用したりすると、もはやJavaScriptURIは評価すらされなくなります。