JavaScriptについてなかなか覚えられないので、色々と書きなぐっていきます。

入門①

JavaScriptの特徴


1.プロトタイプベースのオブジェクト指向

 Javaはクラスという静的なテンプレートを基にインスタンスを生成するのに対して、
JavaScriptはプロトタイプという共通領域に処理を定義した上でインスタンスを生成し、
クラスも一つのオブジェクトとなる。

Javaのクラスは実体を持たず不変であるのに対して、JavaScriptのクラスは実体があり、
必要に応じて内容を書き換えることができる。


2.ダックタイピング(動的型付けの言語)

Javaのように厳格で静的な型付け言語ではなく、実行時に型の扱いを決定する。
「ダックタイピング」というのは「アヒルのようにガーガー鳴いて歩けばそれはアヒルである」
という言葉に由来するみたい。


3.基本事項

■変数名、関数名、プロパティ名などの識別子の先頭を数字にできない


■ECMAScriptで扱う全ての値は、次の6つの種類の型のいずれかに該当する
・数値型
・論理型
・文字列型
・オブジェクト型
・Null型
・Undefined型
※Null型に関しては、typeof演算子で識別するとオブジェクト型と評価されてしまう


■未初期化の変数と未宣言の変数の挙動の違い
var a;
alert(a); //undefined
alert(aa); //例外が発生
※try~catchで例外処理も可


■プロパティの代入と参照
var obj = {}; //変数objを空オブジェクトで初期化
obj.a = 1; //objのプロパティaに数値を代入
alert(obj.a); //1


■コピーの挙動の違い
数値型・論理型・文字列型は値渡しだが、オブジェクト型は参照渡し

☆プリミティブ型(数値型、論理型、文字列型)の例
var master = 1;
var copy = master; //値渡し
copy = 2;   //copyだけが変更される
alert(master); //1


☆オブジェクト型の例
var master = {a:1}; //masterオブジェクトのプロパティaに対して1を代入
var copy = master; //コピー
copy.a = 2; //コピー(このとき、masterのaにも反映される)
alert(master.a); //2
※オブジェクトリテラルでプロパティを宣言する際、名前と値の間をコロン : で区切ります。


■不正確な結果が返る(2進数で表現できないとき)
インタプリタの内部において、数値は整数と実数の区別がなく、
全てIEEEの倍精度64ビットフォーマットで表現されます。(Javaのdouble型と同じ)

alert(3.3 / 10); //0.32999....9 ← 不正確
alert(33 / 100); //0.33     ← 正確
※正確な値が欲しい場合は、整数同士を演算すると良い


■特殊な値
ⅰ.+Infinity //+∞
ⅱ.-Infinity //-∞
ⅲ.NaN //計算エラー(Not a Number)


■isNaN関数(NaNであるかどうかの判定[==ではNaNは一致しない])
var a = 0/0; //NaN
alert(a == NaN); //false
alert(isNaN(a)); //true


■プリミティブ型に対してプロパティの値を代入
var a = a;
a.a = 1; //エラーとならない
alert(a.a); //undefined
※JavaScriptにはプリミティブ型に対して、それぞれの型に対応するラッパークラスが定義されていて、
裏側ではラッパークラスのインスタンスが自動生成されている(特殊型[Null型、Undefined型]を除く)

内部的には、下記のようなことが起きている
var a = a;
(new Number(a)).a = 1;
alert((new Number(a)).a); //undefined
※プリミティブ型に対してプロパティの値を代入すると、
 アクセスする度に毎回newされて上書きされているため、「undefined」になる


■NumberクラスのAPI
 (toPrecision → 指定した精度で文字列を返す、toExponential → 指数表記で文字列を返す)

var num = 3.1415;
var obj = new Number(num);
alert(obj.toPrecision(3)); //3.14
alert(obj.toExponential()); //3.1415e+0


■エスケープ処理(ダブルクォートとシングルクォートのエスケープ)
※ダブルクォートには\が必要でシングルクォートには必要ない
var str = "

";
var str = '

';


■文字列の演算(+だと文字列生成、-だと数値型に自動変換)
var str = '1' + '2';
var sstr = '1' - '2';
alert(str); //12
alert(sstr); //-1


■nullについて(特殊型(Null型、Undefined型))
var empty = null;
alert(typeof(empty)); //object
empty.a = 1 //エラー(Null型はプロパティを保持できないため)
※null型の使いどころとしては、関数の戻り値として、何も見つからなかった場合に返すと良い


■オブジェクトの定義方法の違いによる早さの違い(FireBugのコンソールで検証)

☆結論
「オブジェクトリテラルで定義した場合、
 インタプリタがプロパティの個数を把握できるので、最適化されて少しだけ処理速度が早くなる」

検証に使ったコード↓

1.Objectインスタンスを生成し、プロパティを追加
console.time('test1');
for(var i = 0; i < 1000000; i++) {
var obj = new Object();
obj.a = 1;
obj.b = 2;
}
console.timeEnd('test1');

2.オブジェクトリテラルで記述
console.time('test2');
for(var i = 0; i < 1000000; i++) {
var obj = {
a : 1,
b : 2
};
}
console.timeEnd('test2');

※結論
オブジェクトリテラルで宣言した方が早い!
test1: 1507ms
test2: 1088ms