パラメータというか、コールバック関数のパラメータにあらかじめ定義されていないものを、外から渡す方法についてです。

イベントハンドラに Event 以外のものを外から渡したい場合とかでも同じですが、ここでは setTimeout の第1引数に渡すコールバック関数を例にします。

とりあえず主題の件をやりたければ、コールバック関数のスコープ外の変数に渡したいものをセットして、それをコールバック関数の内側から参照させればいいです。

例として次のコードを実行すると、1000ミリ秒後に alert で『(^-^)』が表示されます。この場合、str がコールバック関数のスコープ外の変数にあたります。

var str = '(^-^)';

setTimeout(function() {
	alert(str);
}, 1000);

ただしこの方法で渡す値は、実際にコールバック関数が実行された時点における変数の値が使用されるので注意です。

それを確認できるのが次の例です。次のコードを実行すると、1000ミリ秒後に alert で表示されるのは『(^-^)』ではなく『(>_<)』です。

var str = '(^-^)';

setTimeout(function() {
	alert(str); // 実際にこれが実行される時点での str は '(>_<)'
}, 1000);

str = '(>_<)';

setTimeout はnミリ秒後に行う処理を予約する関数です。setTimeoutalert を予約した後、1000ミリ秒後までに str の中身が変化してるので、このようになります。

もし「コールバック関数を仕掛けたタイミングにおける変数の値」を実行時にも使用したい場合は、次のように書きます。次のコードを実行すると、1000ミリ秒後も alert で『(^-^)』が表示されます。

var str = '(^-^)';
setTimeout(createCallback(str), 1000);
str = '(>_<)';

function createCallback(arg) {
	return function() {
		alert(arg);
	}
}

少しややこしいですが、これはalert を行う無名関数』を生成して返却する別の関数 (createCallback) を間に挟んでる形です。

JavaScriptの引数は、Object型ではない限り値渡し = 『値がコピーされた別の変数』扱いです。createCallback で生成した無名関数が参照している arg は、あくまで createCallback が実行されたときに渡された str のコピーなので、こういうことができます。

JavaScriptの値渡しについては、次のページがとても参考になりました。

余談

なんでこんな記事を書いたのかというと、むかしループ内で非同期のコールバック関数に外からループカウンタを渡して、やらかしたことがあるからです。

例として次のコードを実行すると、1000ミリ秒後にalertで『3』が3回表示されます。実際に setTimeout で仕掛けたコールバックが実行されるタイミングでは、すでに i の値がループを走り抜けて3に変化しているためです。

やらかし
for (var i = 0; i < 3; ++i) {
	setTimeout(function() {
		alert(i); // 実行時には i = 3
	}, 1000);
}

でも最近初めて知ったのですが、この場合に限っては let 使えばよかったんですね。let 使えば、こう書いても1000ミリ秒後に alert で『0』『1』『2』と表示されます。ループ1周するたびに別スコープ扱いになるからかな?

let使えばいい
for (let i = 0; i < 3; ++i) {
	setTimeout(function() {
		alert(i); // 実行時には i = 0 -> 1 -> 2
	}, 1000);
}