家でJavascriptの本を見かけたから、パラパラと見直してみた。確か自分はプログラミングを最初rubyで学んで、その後Javascriptって面白いんじゃない?みたいな感じで勉強しようと思ってこの本を買った気がする。 本はJavascript本格入門。
ここでは、基礎的でもちょっと気になるだろう部分を書いていこうと思う。
変数にはvarをつけよう
varをつけなくても使うことができるけど、それはグローバル変数として扱われてしまう。グローバル変数ばかりだとわけがわからなくなるのでやめよう。
アンカータグにスクリプトを埋め込む
何か作る時にアンカータグに直接埋め込むようなことはしないと思うけど、こんな書き方もJavasriptはできる。
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <a href="Javascript:window.alert('Hello World');">ダイアログを表示</a> </body> </html>
<a href="Javascript:window.alert('Hello World');">ダイアログを表示</a>
こんな記述があるけど、上記のコードはクリックすると実行することができるんです。
あくまでちょっとスクリプトを埋め込むための記法だから、実際のプロジェクトではまあ見ないよね。
no script
Javascriptは、今ではどのブラウザでも使えるようなもんだしなかなか見ないけど、<noscript>~</noscript>
の中に記述された内容は、 ユーザーの使用しているブラウザがスクリプトに対応していない場合や、 スクリプトを実行しない設定にしている場合などに表示させることができる。
<script type="text/javascript"> <!-- today = new Date(); document.write(today); //--> </script> <noscript> <p>このページではJavaScriptを使用しています。</p> </noscript>
小数点を含む計算には注意
小数点の計算を行う時になんか期待する答えと違うなあ、難しい計算じゃあないんだけどなあ・・・と思ったことはないでしょうか。これはJavascriptは内部的に数値演算を10進数ではなく2進数でおこなっているため誤差が出ちゃってる状態ですね。
試しにブラウザのコンソールから小数点の計算をしてみるとちょっとおかしいですよね。これを正しく計算するのはちょっと面倒で以下のように計算しなくてはいけない。
- 値を整数に直して計算する
- 1の結果を小数点に戻す
面倒ですが、期待する結果が出力されていますね。
厳密に比較したい
等価演算子(==)で左辺と右辺を比較する場合以下のような現象が起きます。
型の違いがあるのにも関わらず、true
となってしまいます。これでは厳密に比較する場合に困るので厳密等価演算子(===)を使う。
今度はfalse
になりましたね。
functionが読み込まれるタイミング
functionの宣言前に関数を使っている以下のコードは実行できるだろうか?
console.log('三角形の面積:' + triangle(5,2)) function triangle(base, height) { return base * height / 2; }
上記のように書いたファイルをブラウザで実行してみると、ちゃんと結果がでます。
関数の宣言前にその関数を使うことができるなんて不思議だなあ・・・と思うけど、function命令はコードを解析/コンパイルするタイミングで関数を登録しているんです。だから後ろに書いてもその関数を使うことはできるんですね。何気なく書いているけど、まあ知っておくとしっくりくるよね。
なので、関数を変数として扱っているこんなスクリプトは実行不可能。
console.log('三角形の面積:' + triangle(5,2)) function triangle(base, height) { return base * height / 2; }
エラーが起きるはずです。
引数の数をチェックしない
これって実行するとどうなると思いますか?引数の数が違うから実行できないですかね?
function print(text) { console.log(text); } print('1番目のテキスト', '2番目のテキスト');
これは実行すると1番目のテキスト
という文字だけが出力されます。引数の数にあっていなくても最初に渡したものは出力されるんですよ。で、これが内部的にはどうなっているかというと引数として渡したテキストはargumentsオブジェクトというものに保存されるんですね。
だからこういう書き方もできる。
function print(text) { console.log(arguments[0]); console.log(arguments[1]) } print('1番目のテキスト', '2番目のテキスト');
これを実行すると2つのテキストが出力されます。引数情報を管理するargumentsオブジェクトなんてものがあるなんてコードには書いてないからなかなか分かんない。
引数の数のチェックをしたい
さっき書いた通り、javascriptでは引数の数をチェックしてくれないので、数を仮引数と本引数で合わせたいときはargumentsオブジェクトを使ってチェックします。
function print(text) { if (arguments.length != 1) { console.log('引数の数が違うよ!(例外処理とかここに入れるといいでしょう。)'); return; } console.log(text); } print('1番目のテキスト', '2番目のテキスト');
こんな風にarguments.length
で引数の数をチェックすることができます。でも、引数の数があやふやなんてなんだかアプリケーションの設計ミスのような気がしなくもない。場合によっては使えそう。
calleeプロパティ
あまり見かけることはないけど、これも面白い。関数などの処理の中で自分自身を再帰的に呼び出すことができる。
function factorial(n) { if (n != 0) { return (n * arguments.callee(n - 1))}; return 1; } console.log(factorial(5)); // => 120
arguments.callee
でfactorial
関数を何度も呼び出して54321の計算をしている。ちょっとややこしいけど、使いこなせたらなんかかっこいい。
関数も関数の引数として渡せる
function arrBridge(data, f) { for (var key in data) { f(data[key]); } } function printElement(v) { console.log(v + 1); } arr = [1,2,3]; arrBridge(arr, printElement);
arrBridge
にprintElement
という関数を渡して、arrBridge
の中でその関数を使っています。こんな風に関数を引数に渡して使うことができてしまうんです。
クロージャ
そこまで聞くような言葉ではないかもしれないけど、場合によってはクロージャを使ってスマートに書くことができたりする。
function closure(init) { var counter = init; return function() { return ++counter } } var myClosure = closure(1); console.log(myClosure()); console.log(myClosure()); console.log(myClosure());
これは、引数に与えた数字に1をプラスするプログラムだけど、結果として2,3,4という数字が出力される。同じ記述なのに、値が保持されてincrementされているのが不思議ですよね。これは、変数myClosureが返り値を関数として受け取り、そしてその関数が変数counterを保持しているから。counterの値は保持されるから何回呼び出してもそれに++された値が返るんです。使いこなすのは難しそうだよねー。
まとめ
Javascriptの基礎的な部分でもちょっと気になるような部分をまとめておいた。何もかも忘れてしまった未来の自分に役立ったらいいかな。

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2016/09/30
- メディア: 大型本
- この商品を含むブログを見る