JavaScriptメモ
概要
完美地図を作ってて気づいたJavaScriptの色々。
- クラスが定義されているか調べる
- IEでは配列の最後に「,」を置けない
- window#onloadイベント時に複数の関数を実行
- for文でも「 i 」は必ず宣言する
- prototypeの罠
クラスが定義されているか調べる
あるクラスが定義されているか調べ、定義されていなかったら読み込む。
if(typeof Prototype == 'undefined') {
document.write('<script type="text/javascript" src="prototype.js"></script>');
}
ちょっと使い方がめんどいけどなんとかなる。
IEでは配列の最後に「,」を置けない
JavaScriptの配列でもFirefoxとSafariでは配列の最後の要素にカンマをおける。これがなぜ良いかは「配列の要素を区切るカンマ、最後の要素の後に置いたら? 」を参照。
ただし、Internet Explorer 6ではエラー。
window#onloadイベント時に複数の関数を実行
window#onload時に動的に生成される複数の関数を実行する。
var initialize_functions = [];
var initializer = function() {
for (var i=0; i<initialize_functions.length; i++) {
initialize_functions[i]();
}
};
Event.observe(window, "load", initializer);
まず、これが良いかどうか別として、グローバル変数にwindow#onload時実行される関数を保持する配列と、実際にwindow#onload時実行される関数を作る。
initializer関数はwindow#onload時に登録された関数をすべて実行する。
initialize_functions.push(
function() {
alert('Hello!!');
}
);
initialize_functions.push(
function() {
alert('World!!');
}
);
こんな感じで登録していく。
for文でも「 i 」は必ず宣言する
ある時、
for (i=0; i<2; i++) {
other_function();
alert(i);
}
と書いて実行してみたら、alertが3回されたあげく、最後に例外が発生した。
なんでかなーと思いつつデバッグしてみたら、other_function()内でもfor(i=0;i<2;i++)みたいなことやってて、変数 i がグローバルで定義されていたため i が毎回リセットされ、おかしなことになっていた模様。
これからはちゃんと面倒がらず、
for (var i=0; i<2; i++) {
other_function();
alert(i);
}
と書くことにする。
20071212追記
varはローカルスコープを持つ変数の宣言なので、上記の例だとforブロック内のスコープではなく、そのfor文が使われている関数内?のローカルスコープになってしまうらしい。
というわけでvarの代わりにletを使うと良いようだ。
for (let i=0; i<2; i++) {
other_function();
alert(i);
}
prototypeの罠
var TestClass = Class.create();
TestClass.prototype = {
pos: {x:0}
};
ってクラスを定義した後に、
var a = new TestClass();
a.pos.x = 500;
var b = new TestClass();
b.pos.x = 1000;
alert(a.pos.x);
で何が出力されるでしょう???
a.pos.xだから、500が出力されると思いきや、答え、「1000」。。。
どうも a.pos と b.pos が同じオブジェクトを指してるようだ。
var TestClass = Class.create();
TestClass.prototype = {
pos: {x:0}
};
で、posを初期化したつもりでしたが、これはTestClass共通のプロトタイプを初期化してることになってしまうんですなー。
初期化するときはちゃんとコンストラクタ内でしましょう…。
var TestClass = Class.create();
TestClass.prototype = {
pos: null,
initialize: function () {
pos = {x=0};
}
};