JavaScriptはじめの一歩

JavaScriptを勉強したいと思ったのは、静的なHTMLの表現をどれくらい豊かに出来るのか興味があるから。個人的な勉強メモなどをテキストで書いて、閲覧するときはそれをHTMLに変換して読んでいるのだけど、ちょっと使いにくいと感じる面があって、それをもう少し動的なコンテンツに出来ないのかなと。JavaScriptを使ってソースコードの表示非表示や、検索(Pythonのドキュメントに付属する検索みたいなの)を付けるのがさしあたりの目標。

JavaScript言語が採用するプロトタイプベースのオブジェクト指向にも興味があります。Javaなどのクラスベースの言語に比べて、プロトタイプベースのオブジェクト指向言語ではプログラムの書き方がどんな風に変わるのかな。

CodecademyというサイトでJavaScriptの勉強をしています。それから、『パーフェクトJavaScript』を読んでいます。3章まで読みました。

はじめに処理系をインストール。コマンドラインから実行できるRhinoをインストール。さっそくフィボナッチ数列のプログラムを書きました。

function fib(n) {
    if (n == 0 || n == 1)
        return 1;
    else
        return fib(n-1) + fib(n-2);
}

print(fib(30))

実行結果です。

1346269

Rhinoでは、-optを付けると最適化が効いて速くなる。-optに指定する数字は-1から9まで。

文字列リテラルには、ダブルクオートとシングルクオートの両方が使える。

js> "Hello World"
Hello World
js> 'Hello World'
Hello World
js> "Hello 'foo' World"  // エスケープする必要なし
Hello 'foo' World
js> 'Hello "foo" World'  // エスケープする必要なし
Hello "foo" World

typeof演算子で値の型が分かる。

js> typeof 1
number
js> typeof 1.2
number
js> typeof []
object
js> typeof {}
object
js> typeof "foo"
string
js> typeof object
undefined
js> object  
js: uncaught JavaScript runtime exception: ReferenceError: "object" is not defined.
js> typeof(typeof(1))
string

typeofの引数に未定義の変数を書くと、undefinedになるのか。typeofの戻り値はstringらしい。

文字列の練習。

js> var s = "あいうえお";
js> for (var i = 0; i < s.length; i++) print(s[i])
あ
い
う
え
お
js> s[-1]
js> s[0]
あ
js> s[1000]

範囲外アクセスしてもエラーにならない。

Stringについて。

js> String
function String() { [native code for String.String, arity=1] }

js> typeof String
function
js> String("foo")
foo

Stringはfunction。「function String() { ... }」と表示されることから、関数の引数表示は省略されるのだろうか?関数を定義して確かめる。

js> function add(a, b) { return a + b; }
js> add

function add(a, b) {
    return a + b;
}

自分で定義した関数については、引数表示もきちんと行われている。コメントも追加してみる。

js> function sub(a, b) {
  > // subtract
  > return a-b;
  > }
js> sub

function sub(a, b) {
    return a - b;
}

コメントは取り除かれる。

『パーフェクトJavaScript』では行末にセミコロンがあるのに気がついた。セミコロンは省略可能みたいだけど、セミコロンを付けるようにしたほうがいいのかな。

比較演算子==, ===の練習

js> "foo" == new String("foo")
true
js> "foo" === new String("foo")
false
js> "foo" == "foo"
true
js> new String("foo") === new String("foo") 
false
js> var s = new String("foo")
js> s === s
true
js> new String("foo") == new String("foo")
false

うーむ。new String("foo")同士の==による比較はfalseになるのか……。typeofで型を確認する。

js> typeof "foo";
string
js> typeof (new String("foo"));
object

「new String("foo")」の型は、stringではなくてobjectだった。Stringの型はfunctionだったよね。

js> typeof String;
function

substring()の呼び出し

js> "foo".substring(1)
oo
js> "foo".substring(2)
o
js> "foo".substring(3)

js> "foo".substring(4)

js> "foo".substring
function substring() { [native code for String.substring, arity=2] }

js> typeof ("foo".substring)
function
js> var f = "foo".substring
js> f
function substring() { [native code for String.substring, arity=2] }

js> f(1)
object global]

最後の実行結果がわからない。fは文字列として"[object global]"を保持しているみたい。でも、何故? f(1)の実行結果には"oo"を期待していた。

「typeof (new String("foo"))」でobjectが返される。このオブジェクトをstringに変換出来ないだろうか?toString()を使うとstringに変換出来る。

js> var s = new String("foo");
js> typeof s;
object
js> typeof s.toString();
string
js> var t = s.toString();
js> t
foo
js> s.toString() == s.toString();
true
js> s.toString() === s.toString();
true

newを付けずに、String()でもstringに変換することができる。

js> var s = new String("foo");
js> typeof s;
object
js> var t = String("foo");
js> t
foo
js> typeof t;
string

なんだか、newの使いどころがいまいちよく分からない。newの詳しい使い方はこの先のお楽しみ。

toString()で基数変換が出来る。

js> 255.toString(16);
js: "<stdin>", line 143: missing ; before statement
js: 255.toString(16);
js: ............^
js> (255).toString(16);
ff
js> (255).toString(2);
11111111
js> (255).toString(1);
js: illegal radix 1.