<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: setTimeout のコールバック関数内でローカル変数を使用する</title>
	<atom:link href="http://www.xuldev.org/blog/?feed=rss2&#038;p=136" rel="self" type="application/rss+xml" />
	<link>http://www.xuldev.org/blog/?p=136</link>
	<description>http://www.xuldev.org/blog/</description>
	<lastBuildDate>Sun, 08 Aug 2010 17:16:33 +0900</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<item>
		<title>By: nanto_vi</title>
		<link>http://www.xuldev.org/blog/?p=136&#038;cpage=1#comment-368</link>
		<dc:creator>nanto_vi</dc:creator>
		<pubDate>Fri, 12 Oct 2007 14:38:12 +0000</pubDate>
		<guid isPermaLink="false">http://www.xuldev.org/blog/?p=136#comment-368</guid>
		<description>ジェネレータを使った別解としてこんなのも考えられますね。基本的な発想はhot_coffeeさんと同じです。
&lt;pre&gt;
function arrayValues(array) {
  for (var i = 0; i &lt; array.length; i++)
    yield array[i];
}
function forEachLater(array, callback, interval) {
  var values = arrayValues(array);
  setTimeout(function () {
    try {
      callback(values.next());
      setTimeout(arguments.callee, interval);
    } catch (ex if ex instanceof StopIteration) {}
  }, interval);
}
forEachLater([&quot;apple&quot;, &quot;orange&quot;, &quot;banana&quot;], print, 1000);
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>ジェネレータを使った別解としてこんなのも考えられますね。基本的な発想はhot_coffeeさんと同じです。</p>
<pre>
function arrayValues(array) {
  for (var i = 0; i &lt; array.length; i++)
    yield array[i];
}
function forEachLater(array, callback, interval) {
  var values = arrayValues(array);
  setTimeout(function () {
    try {
      callback(values.next());
      setTimeout(arguments.callee, interval);
    } catch (ex if ex instanceof StopIteration) {}
  }, interval);
}
forEachLater(["apple", "orange", "banana"], print, 1000);
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gomita</title>
		<link>http://www.xuldev.org/blog/?p=136&#038;cpage=1#comment-366</link>
		<dc:creator>Gomita</dc:creator>
		<pubDate>Fri, 12 Oct 2007 02:49:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.xuldev.org/blog/?p=136#comment-366</guid>
		<description>nanto_viさんご指摘ありがとうございます。修正しました。

&gt; 一つ一つ終わってから処理する
あまり自信ないですけど、JS1.7でGenerator使うとこんな感じでしょうか。
&lt;pre&gt;
function generator() {
    var fruits = [&quot;apple&quot;, &quot;orange&quot;, &quot;banana&quot;];
    for (var i = 0; i &lt; fruits.length; i++) {
        alert(fruits[i]);
        yield true;
    }
    yield false;
}
function driveGenerator() {
    if (gen.next())
        window.setTimeout(driveGenerator, 1000);
    else
        gen.close();
}
var gen = generator();
driveGenerator();
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>nanto_viさんご指摘ありがとうございます。修正しました。</p>
<p>> 一つ一つ終わってから処理する<br />
あまり自信ないですけど、JS1.7でGenerator使うとこんな感じでしょうか。</p>
<pre>
function generator() {
    var fruits = ["apple", "orange", "banana"];
    for (var i = 0; i < fruits.length; i++) {
        alert(fruits[i]);
        yield true;
    }
    yield false;
}
function driveGenerator() {
    if (gen.next())
        window.setTimeout(driveGenerator, 1000);
    else
        gen.close();
}
var gen = generator();
driveGenerator();
</pre>
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: hot_coffee</title>
		<link>http://www.xuldev.org/blog/?p=136&#038;cpage=1#comment-365</link>
		<dc:creator>hot_coffee</dc:creator>
		<pubDate>Thu, 11 Oct 2007 19:21:59 +0000</pubDate>
		<guid isPermaLink="false">http://www.xuldev.org/blog/?p=136#comment-365</guid>
		<description>一つ一つ終わってから処理するときはこうしてます。
&lt;pre&gt;
function setFruitsAlert(fruits) {
   i = 0;
   function g() {
      if(i &lt; fruits.length) {
         window.setTimeout(function(fruits) {
            alert(fruits[i]);
            i++;
            g();
         }, 1000);
      }
   }
   g();
}

var fruits = [&quot;apple&quot;, &quot;orange&quot;, &quot;banana&quot;];

setFruitsAlert(fruits);
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>一つ一つ終わってから処理するときはこうしてます。</p>
<pre>
function setFruitsAlert(fruits) {
   i = 0;
   function g() {
      if(i &lt; fruits.length) {
         window.setTimeout(function(fruits) {
            alert(fruits[i]);
            i++;
            g();
         }, 1000);
      }
   }
   g();
}

var fruits = ["apple", "orange", "banana"];

setFruitsAlert(fruits);
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: os0x</title>
		<link>http://www.xuldev.org/blog/?p=136&#038;cpage=1#comment-363</link>
		<dc:creator>os0x</dc:creator>
		<pubDate>Tue, 09 Oct 2007 03:35:06 +0000</pubDate>
		<guid isPermaLink="false">http://www.xuldev.org/blog/?p=136#comment-363</guid>
		<description>便乗させて頂いて、自分ならこう書くかなと。
&lt;pre&gt;
var fruits = [&quot;apple&quot;, &quot;orange&quot;, &quot;banana&quot;];
for (var i = 0; i &lt; fruits.length; i++) {
  (function(fruit){
    window.setTimeout(function() { alert(fruit); }, 1000);
  })(fruits[i]);
}
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>便乗させて頂いて、自分ならこう書くかなと。</p>
<pre>
var fruits = ["apple", "orange", "banana"];
for (var i = 0; i &lt; fruits.length; i++) {
  (function(fruit){
    window.setTimeout(function() { alert(fruit); }, 1000);
  })(fruits[i]);
}
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: nanto_vi</title>
		<link>http://www.xuldev.org/blog/?p=136&#038;cpage=1#comment-362</link>
		<dc:creator>nanto_vi</dc:creator>
		<pubDate>Mon, 08 Oct 2007 15:28:52 +0000</pubDate>
		<guid isPermaLink="false">http://www.xuldev.org/blog/?p=136#comment-362</guid>
		<description>Firefox 2 以降で JavaScript のバージョンを 1.7 以上に指定すれば、
&lt;pre&gt;
for (var i = 0; i &lt; fruits.length; i++) {
  window.setTimeout(let (fruit = fruits[i]) function() { alert(fruit); }, i * 1000);
}
&lt;/pre&gt;
でもいけますね。(Firefox 3 ならバージョンを明示的に指定しなくても使えたかも)

あるいは、
&lt;pre&gt;
for (var i = 0; i &lt; fruits.length; i++) {
  with ({ fruit: fruits[i] }) {
    window.setTimeout(function() { alert(fruit); }, i * 1000);
  }
}
&lt;/pre&gt;
とすれば Firefox 1.0 でも OK ですし。

いずれにせよ、「コールバック関数が呼び出されたときにはすでにローカル変数 i は破棄されている」というのは間違いで、i の値が 4 になっているから fruits[i] が undefined になっているだけです。</description>
		<content:encoded><![CDATA[<p>Firefox 2 以降で JavaScript のバージョンを 1.7 以上に指定すれば、</p>
<pre>
for (var i = 0; i &lt; fruits.length; i++) {
  window.setTimeout(let (fruit = fruits[i]) function() { alert(fruit); }, i * 1000);
}
</pre>
<p>でもいけますね。(Firefox 3 ならバージョンを明示的に指定しなくても使えたかも)</p>
<p>あるいは、</p>
<pre>
for (var i = 0; i &lt; fruits.length; i++) {
  with ({ fruit: fruits[i] }) {
    window.setTimeout(function() { alert(fruit); }, i * 1000);
  }
}
</pre>
<p>とすれば Firefox 1.0 でも OK ですし。</p>
<p>いずれにせよ、「コールバック関数が呼び出されたときにはすでにローカル変数 i は破棄されている」というのは間違いで、i の値が 4 になっているから fruits[i] が undefined になっているだけです。</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gomita</title>
		<link>http://www.xuldev.org/blog/?p=136&#038;cpage=1#comment-361</link>
		<dc:creator>Gomita</dc:creator>
		<pubDate>Mon, 08 Oct 2007 12:41:02 +0000</pubDate>
		<guid isPermaLink="false">http://www.xuldev.org/blog/?p=136#comment-361</guid>
		<description>そういう手もありましたか。サンクスです。本文へ加筆しました。</description>
		<content:encoded><![CDATA[<p>そういう手もありましたか。サンクスです。本文へ加筆しました。</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Piro</title>
		<link>http://www.xuldev.org/blog/?p=136&#038;cpage=1#comment-360</link>
		<dc:creator>Piro</dc:creator>
		<pubDate>Mon, 08 Oct 2007 08:20:54 +0000</pubDate>
		<guid isPermaLink="false">http://www.xuldev.org/blog/?p=136#comment-360</guid>
		<description>コールバック関数の部分が複雑になる場合は、こっちの方がお勧めかも……
&lt;pre&gt;
for (var i = 0; i &lt; fruits.length; i++) {
    window.setTimeout(function(aArg) { alert(aArg); }, i * 1000, fruits[i]);
}
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>コールバック関数の部分が複雑になる場合は、こっちの方がお勧めかも……</p>
<pre>
for (var i = 0; i &lt; fruits.length; i++) {
    window.setTimeout(function(aArg) { alert(aArg); }, i * 1000, fruits[i]);
}
</pre>
]]></content:encoded>
	</item>
</channel>
</rss>
