<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	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/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>随网之舞匿名函数</title>
	<atom:link href="http://dancewithnet.com/tag/%e5%8c%bf%e5%90%8d%e5%87%bd%e6%95%b0/feed/" rel="self" type="application/rss+xml" />
	<link>http://dancewithnet.com</link>
	<description>WEB Design{HTML:CSS:Javascript:DOM:AJAX:PHP:Usability}/Viewpoint/Photo/Food/Mood</description>
	<lastBuildDate>Mon, 18 Jul 2011 02:45:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>JavaScript的陷阱</title>
		<link>http://dancewithnet.com/2008/10/27/javascript-gotchas/</link>
		<comments>http://dancewithnet.com/2008/10/27/javascript-gotchas/#comments</comments>
		<pubDate>Sun, 26 Oct 2008 16:26:23 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[for]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[null]]></category>
		<category><![CDATA[parseInt]]></category>
		<category><![CDATA[String.replace()]]></category>
		<category><![CDATA[switch]]></category>
		<category><![CDATA[this]]></category>
		<category><![CDATA[undefined]]></category>
		<category><![CDATA[匿名函数]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1366</guid>
		<description><![CDATA[这本来是翻译Estelle Weyl的《15 JavaScript Gotchas》，里面介绍的都是在JavaScript编程实践中平时容易出错或需要注意的地方，并提供避开这些陷阱的方法，总体上讲，就是在认清事物本质的基础样要... ]]></description>
			<content:encoded><![CDATA[<p>这本来是翻译Estelle Weyl的<a href="http://www.evotech.net/blog/2008/10/13-javascript-gotchas/">《15 JavaScript Gotchas》</a>，里面介绍的都是在JavaScript编程实践中平时容易出错或需要注意的地方，并提供避开这些陷阱的方法，总体上讲，就是在认清事物本质的基础样要坚持好的编程习惯，其实这就是Douglas Crockford很久以前提出的JavaScript风格要素问题了，有些内容直接是相同的，具体请看<a href="http://dancewithnet.com/2008/01/26/the-elements-of-javascript-style-part-one/">《Javascript风格要素（1）》</a>和<a href="http://dancewithnet.com/2008/01/30/the-elements-of-javascript-style-part-two/">《Javascript风格要素（2）》</a>。在翻译的过程中，我又看到了贤安去年翻译的<a href="http://realazy.org/blog/2007/08/20/nine-javascript-gotchas/">《JavaScript的9个陷阱及评点》</a>，其内容又有些交叉在一起，所以我就在现有翻译的基础上做了一个简单的拼合，并依据自己的理解增加了一些注释和解释。<span id="more-1366"></span></p>
<ol>
<li><a href="#case-sensitivity">区分大小写：变量名、属性和方法全部都区分大小写</a></li>
<li><a href="#mismatching">不匹配的引号、圆括号或花括号将抛出错误</a></li>
<li><a href="#conditional-statements">条件语句：3个常见陷阱</a></li>
<li><a href="#line-breaks">换行：一直用分号结束语句来避免常见的换行问题</a></li>
<li><a href="#punctuation">标点法：在对象声明的尾部逗号将导致出错</a></li>
<li><a href="#html-id-conflicts">HTML id 冲突</a></li>
<li><a href="#variable-scope">变量作用域：全局变量对局部变量</a></li>
<li><a href="#function-overloading">函数重载：当重载不存在时，覆盖函数</a></li>
<li><a href="#string-replace">区分string.replace()函数不是全局的</a></li>
<li><a href="#parseInt">parseInt应该包含两个参数</a></li>
<li><a href="#this">“this”和绑定问题</a></li>
<li><a href="#default-param-value">为参数设置默认值，以免你遗漏它们</a></li>
<li><a href="#for-statements">for each循环是用于对象而不是数组</a></li>
<li><a href="#switch-statements">switch语句需要点技巧</a></li>
<li><a href="#undefined-vs-null">如果你要检查null，应该先检查undefined</a></li>
<li><a href="#event-handlers">时间处理陷阱</a></li>
</ol>
<h3 id="case-sensitivity">区分大小写</h3>
<p>变量名和函数名都是区分大小写的。就像配错的引号一样，这些大家都知道。但是，由于错误是不作声的，所以这是一个提醒。为自己选择一个命名规则，并坚持它。而且，记住JavaScript中的原生函数和CSS属性都是<a href="http://zh.wikipedia.org/wiki/驼峰式大小写">骆驼拼写法（camelCase）</a>。</p>
<pre><code>getElementBy<strong>Id</strong>(’myId’) != getElementBy<strong>ID</strong>(’myId’); <span>//它应该是“Id”而不是“ID”</span>
getElementById(’my<strong>Id</strong>‘) != getElementById(’my<strong>ID</strong>‘); <span>// “Id”也不等于“ID”</span>

document.getElementById('myId').style.<strong>Color</strong>; <span>//返回 "undefined"</span>
</code></pre>
<h3 id="mismatching">不匹配的引号、圆括号或花括号</h3>
<p>避免陷入不匹配的引号、圆括号或花括号陷阱的最好方式是编码时一直同时写出打开和关闭这两个元素符号，然后在其中间加入代码。开始：</p>
<pre><code>var myString = ""; <span>//在输入字符串值之前写入这对引号</span>
function myFunction(){
 if(){<span>//关闭每个打开的括弧</span>
 }
}
<span>//统计所有的左括号和右括号数量，并且确保它们相等</span>
alert(parseInt(var1)*(parseInt(var2)+parseInt(var3))); <span>//关闭每个打开的圆括号</span>
</code></pre>
<p>每当你打开一个元素，请关闭它。当你添加了关闭圆括号后，你再把函数的参数放进圆括号中。如果有一串圆括号，统计所有打开的圆括号和所有关闭的圆括号，并且确保这两个数字相等。</p>
<h3 id="conditional-statments">条件语句（3个陷阱）</h3>
<ol>
<li>所有的条件语句都必须位于圆括号中。<ins datetime="2008-10-28T18:05:25+80:00">执行语句主体不管是一句还是多句都强烈建议用花括号包围起来，这样能避免很多因修改或嵌套而产生的潜在错误。</ins>
<pre><code>if(var1 == var2){<span>//statement</span>}</code></pre>
</li>
<li>不要犯无意地使用赋值运算符的错误：把第二个参数的值赋给第一个参数。因为它是一个逻辑问题，它将一直返回true且不会报错。
<pre><code>if(var1 = var2){} <span>// 返回true。把var2赋值给var1</span></code></pre>
</li>
<li>JavaScript是弱类型，除了在<a href="http://www.evotech.net/blog/2007/07/javascript-switch-statement-quirks/">switch语句</a>中。当JavaScript在case比较时，它是非弱类型。
<pre><code>var myVar = 5;
if(myVar == '5'){ <span>//返回true，因为JavaScript是弱类型</span>
 alert("hi");  <span>//这个alert将执行，因为JavaScript通常不在意数据类型</span>
}
switch(myVar){
 case '5':
 alert("hi"); <span>//这个alert将不会执行，因为数据类型不匹配</span>
}
</code></pre>
</li>
</ol>
<h3 id="line-breaks">换行</h3>
<p>当心JavaScript中的硬换行。换行被解释为表示行结束的分号。即使在字符串中，如果在引号中包括了一个硬换行，那么你会得到一个解析错误（未结束的字符串）。</p>
<pre><code>var bad  = '&lt;ul id="myId"&gt;
  &lt;li&gt;some text&lt;/li&gt;
  &lt;li&gt;more text&lt;/li&gt;
  &lt;/ul&gt;'; <span>// 未结束的字符串错误</span>

var good = '&lt;ul id="myId"&gt;' +
 ‘&lt;li&gt;some text&lt;/li&gt;‘ +
 ‘&lt;li&gt;more text&lt;/li&gt;‘ +
 ‘&lt;/ul&gt;’; <span>// 正确</span>
</code></pre>
<p>前面讨论过的换行被解释为分号的规则并不适用于控制结构这种情况：条件语句关闭圆括号后的换行并不是给其一个分号。</p>
<p>一直使用分号和圆括号，那么你不会因换行而出错，你的代码易于阅读，且除了那些不使用分号的怪异源码外你会少一些顾虑：所以当移动代码且最终导致两个语句在一行时，你无需担心第一个语句是否正确结束。</p>
<h3 id="punctuation">多余的逗号</h3>
<p>在任何JavaScript对象定义中，最后一个属性决不能以一个逗号结尾。Firefox不会出错，而IE会报语法错误。</p>
<pre><code>var theObj = {
        city : "Boston",
        state : "MA",<span>//IE6和IE7中有“缺少标识符、字符串或数字”的错误，IE8 beta2修正了它</span>
  }</code></pre>
<h3 id="html-id-conflicts">HTML id 冲突</h3>
<p><a href="http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html">JavaScript DOM绑定（JavaScript DOM bindings）</a>允许通过HTML id索引。在JavaScript中函数和属性共享同一个名字空间。所以，当在HTML中的一个id和函数或属性有相同的名字时，你会得到难以跟踪的逻辑错误。然而这更多是一个<a href="http://www.evotech.net/blog/2007/04/css-best-practices/">CSS最佳实践</a>的问题，当你不能解决你的JavaScript问题时，想起它是很重要的。</p>
<pre><code>
&lt;ul&gt;
&lt;li id="length"&gt;1&lt;/li&gt;
&lt;li id="thisLength"&gt;2&lt;/li&gt;
&lt;li id="thatLength"&gt;3&lt;/li&gt;
&lt;/ul&gt;
&lt;script&gt;
var listitems = document.getElementsByTagName('li');
var liCount = listitems.length; <span>//IE下返回的是&lt;li id="length"&gt;1&lt;/li&gt;这个节点而不是所有&lt;li的数量</span>

var thisLength = document.getElementById('thisLength');
    thatLength = document.getElementById('thatLength');
    <span>//IE下会出现“对象不支持此属性和方法”的错误，IE8 beta2下首次加载页面会出错，刷新页面则不会</span>
    <span>//在IE中thisLength和thatLength直接表示以其为id值的DOM节点，</span>
    <span>//所以赋值时会出错，当有var声明时，IE会把其当着变量，这个时候就正常了。</span>
&lt;/script&gt;
</code></pre>
<p> 如果你要标记(X)HTML，绝不要使用JavaScript方法或属性名作为id的值。并且，当你写JavaScript时，避免使用 (X)HTML中的id值作为变量名。</p>
<h3 id="variable-scope">变量作用域</h3>
<p>JavaScript中的许多问题都来自于变量作用域：要么认为局部变量是全局的，要么用函数中的局部变量覆盖了全局变量。为了避免这些问题，最佳方案是根本没有任何全局变量。但是，如果你有一堆，那么你应该知道这些陷阱。</p>
<p>不用var关键字声明的变量是全局的。记住使用var关键字声明变量，防止变量具有全局作用域。在下面例子中，在函数中声明的变量具有全局变量，因为没有使用var关键字声明：</p>
<pre><code>anonymousFuntion1 = function(){
 globalvar = 'global scope'; <span>//全局声明，因为“var”遗漏了</span>
 return localvar;
}();
alert(globalvar); <span>//弹出“global scope”，因为函数中的变量是全局声明</span>

anonymousFuntion2 = function(){
 var localvar = 'local scope'; <span>//使用“var”局部声明</span>
 return localvar;
}();
alert(localvar); <span>//错误 “localvar未定义”。没有全局定义localvar</span>
</code></pre>
<p>作为参数引进到函数的变量名是局部的。如果参数名也是一个全局变量的名字，像参数变量一样有局部作用域，这没有冲突。如果你想在函数中改变一个全局变量，这个函数有一个参数复制于这个全局变量名，记住所有全局变脸都是window对象的属性。</p>
<pre><code>var myscope = "global";
function showScope(myscope){
 return myscope; <span>//局部作用域，即使有一个相同名字的全局变量</span>
}
alert(showScope('local'));

function globalScope(myscope){
 myscope = <strong>window.myscope</strong>; <span>//全局作用域</span>
 return myscope;
}
alert(globalScope(’local’));
</code></pre>
<p>你甚至可以在循环中声明变量：</p>
<pre><code>for(var i = 0; i < myarray.length; i++){}</code></code></pre>
<h3 id="function-overloading">覆盖函数/重载函数</h3>
<p>当你不止一次的声明一个函数时，这个函数的最后一次声明将覆盖掉该函数的所有前面版本且不会抛出任何错误或警告。这不同于其他的编程语言，像Java，你能用相同的名字有多重函数，只要它们有不同的参数：调用函数重载。在JavaScript中没有重载。这使得不能在代码中使用JavaScript核心部分的名字极其重要。也要当心包含的多个JavaScript文件，像一个包含的脚本文件可能覆盖另一个脚本文件中的函数。请使用匿名函数和名字空间。</p>
<pre><code>(function(){
 <span>// creation of my namespace 创建我的名字空间</span>
 if(!window.MYNAMESPACE) {
  window['MYNAMESPACE'] = {};
 }
 <span>//如果名字空间不存在，就创建它</span>
 <span>//这个函数仅能在匿名函数中访问</span>
 function myFunction(var1, var2){
  <span>//内部的函数代码在这儿</span>
 }
 <span>// 把内部函数连接到名字空间上，使它通过使用名字空间能访问匿名函数的外面 </span>
 window['MYNAMESPACE']['myFunction'] = myFunction;
})(); <span>// 圆括号 = 立即执行</span>
<span>// 包含所有代码的圆括号使函数匿名</span>
</code></pre>
<p>这个例子正式为了实现解决上一个陷阱“变量作用域”的最佳方案。匿名函数详细内容请看<a href="http://dancewithnet.com/2008/05/07/javascript-anonymous-function/">《Javascript的匿名函数》</a>。<a href="http://developer.yahoo.com/yui/">YUI</a>整个库只有YAHOO和YAHOO_config两个全局变量，它正是大量应用匿名函数和命名空间的方法来实现，具体请看<a href="http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/">《Javascript的一种模块模式》</a>。</p>
<h3 id="string-replace">字符串替换</h3>
<p>一个常见错误是假设字符串替换方法的行为会对所有可能匹配都产生影响。实际上，JavaScript字符串替换只改变了第一次发生的地方。为了替换所有发生的地方，你需要设置全局标识。同时需要记住String.replace()的第一个参数是一个正则表达式。</p>
<pre><code>var myString = "this is my string";
myString = myString.replace("","%20"); // "this%20is my string"
myString = myString.replace(/ /,"%20"); // "this%20is my string"
myString = myString.replace(/ /g,"%20"); // "this%20is%20my%20string"
</code></pre>
<h3 id="parseInt">parseInt</h3>
<p>在JavaScript得到整数的最常见错误是假设parseInt返回的整数是基于10进制的。别忘记第二个参数基数，它能是从2到36之间的任何值。为了确保你不会弄错，请一直包含第二个参数。</p>
<pre><code>parseInt('09/10/08'); <span>//0</span>
parseInt(’09/10/08′,10); <span>//9, 它最可能是你想从一个日期中得到的值</span>
</code></pre>
<p>如果parseInt没有提供第二个参数，则前缀为 &#8216;0x&#8217; 的字符串被当作十六进制，前缀为 &#8216;0&#8242; 的字符串被当作八进制。所有其它字符串都被当作是十进制的。如果 numString 的前缀不能解释为整数，则返回 NaN（而不是数字）。</p>
<h3 id="this">‘this’</h3>
<p>另一个常见的错误是忘记使用“this”。在JavaScript对象中定义的函数访问这个对象的属性，但没有使用引用标识符“this”。例如，下面是错误的：</p>
<pre><code>function myFunction() {
 var myObject = {
  objProperty: "some text",
  objMethod: function() {
   alert(objProperty);
  }
 };
 myObject.objMethod();
} 

function myFunction() {
 var myObject = {
  objProperty: "some text",
  objMethod: function() {
   alert(this.objProperty);
  }
 };
 myObject.objMethod();
}
</code></pre>
<p>有一篇<a href="http://www.alistapart.com/articles/getoutbindingsituations">A List Apart文章</a>用通俗易懂的英文表达了this绑定的问题。</p>
<p>对this使用最大的陷阱是this在使用过程中其引用会发生改变：</p>
<pre><code>&lt;input type="button" value="Gotcha!" id="MyButton"&gt;
&lt;script&gt;
var MyObject = function () {
    this.alertMessage = "Javascript rules";
    this.ClickHandler = function() {
        <strong>alert(this.alertMessage );</strong>
        <span>//返回结果不是”JavaScript rules”，执行MyObject.ClickHandler时，</span>
        <span>//this的引用实际上指向的是document.getElementById("theText")的引用</span>
  }
}();
document.getElementById(”theText”).onclick =  MyObject.ClickHandler
&lt;/script&gt;
</code></pre>
<p>其解决方案是：</p>
<pre><code>
var MyObject = function () {
    <strong>var self = this;</strong>
    this.alertMessage = “Javascript rules”;
    this.OnClick = function() {
        alert(self.value);
    }
}();
</code></pre>
<p>类似问题的更多细节和解决方案请看<a href="http://realazy.org/blog/2007/07/18/scope-in-javascript/">《JavaScript作用域的问题》</a>。</p>
<h3 id="default-param-value">遗漏的参数</h3>
<p>当给函数增加一个参数时，一个常见的错误是忘记更新这个函数的所有调用。如果你需要在已经被调用的函数中增加一个参数来处理一个特殊情况下的调用，请给这个函数中的这个参数设置默认值，以防万一在众多脚本中的众多调用中的一个忘记更新。</p>
<pre><code>function addressFunction(address, city, state, country){
 <strong>country = country || “US”</strong>; <span>//如果没有传入country,假设 “US”</span>
 span>//剩下代码
}
</code></pre>
<p>你也能通过获取arguments来解决。但是在这篇文章我们的注意力在陷阱上。同时在<a href="http://dancewithnet.com/2008/01/30/the-elements-of-javascript-style-part-two/">《Javascript风格要素（2）》</a>也介绍了||巧妙应用。</p>
<h3 id="for-statements">for关键字</h3>
<p>在JavaScript中关键字for有两种使用方式，一个是for语句，一个是for/in语句。for/in语句将遍历所有的对象属性（attribute），包括方法和属性（property）。决不能使用for/in来遍历数组：仅在当需要遍历对象属性和方法时才使用for/in。</p>
<ol>
<li>for(var myVar in myObject)语句用一个指定变量无任何规律地遍历对象的所有属性。如果for/in循环的主体删除了一个还没有枚举出的属性，那么该属性就不在枚举。如果循环主体定义了新属性，那么循环是否枚举该属性则是由JavaScript的实现决定。</li>
<li>for(var 1=0; i < myArray.length; i++)语句会遍历完一个数组的所有元素。</li>
</li>
</ol>
<p>为了解决这个问题，大体上你可以对对象使用 for &#8230; in，对数组使用for循环：</p>
<pre><code>listItems = document.getElementsByTagName('li');
for (var listitem in listItems){
 <span>//这里将遍历这个对象的所有属性和方法，包括原生的方法和属性，但不遍历这个数组：出错了！</span>
}
<span>//因为你要循环的是数组对象，所用for循环</span>
for ( var i = 0; i < listItems.length; i++) {
 <span>//这是真正你想要的
}
</code></pre>
<p>对象的有些属性以相同的方式标记成只读的、永久的或不可列举的，这些属性for/in无法枚举。实际上，for/in循环<br />
会遍历所有对象的所有可能属性，包括函数和原型中的属性。所有修改原型属性可能对for/in循环带来致命的危害，所以需要采用hasOwnProperty和typeof做一些必要的过滤，最好是用for来代替for/in。</p>
<h3 id="switch-statements">switch语句</h3>
<p>Estelle Weyl写了一篇<a href="http://www.evotech.net/blog/2007/07/javascript-switch-statement-quirks/">switch statement quirks</a>，其要点是：</p>
<ol>
<li>没有数据类型转换</li>
<li>一个匹配，所有的表达式都将执行直到后面的break或return语句执行</li>
<li>你可以对一个单独语句块使用多个case从句</li>
</ol>
<h3 id="undefined-vs-null">undefined ≠ null</h3>
<p>null是一个对象，undefined是一个属性、方法或变量。存在null是因为对象被定义。如果对象没有被定义，而测试它是否是null，但因为没有被定义，它无法测试到，而且会抛出错误。</p>
<pre><code>if(myObject !== null  &#038;&#038; typeof(myObject) !== 'undefined') {
 <span>//如果myObject是undefined，它不能测试是否为null，而且还会抛出错误</span>
}
if(typeof(myObject) !== 'undefined' &#038;&#038; myObject !== null) {
 <span>//处理myObject的代码</span>
}
</code></pre>
<p><a href="http://blog.poundbang.in/post/30056940/javascript-gotcha-undefined-vs-null">Harish Mallipeddi</a>对undefined和null有一个说明。</p>
<h3 id="event-handlers">事件处理陷阱</h3>
<p>刚接触事件处理时最常见的写法就是类似：</p>
<pre><code>window.onclick = MyOnClickMethod</code></pre>
<p>这种做法不仅非常容易出现后面的window.onclick事件覆盖掉前面的事件，还可能导致大名顶顶的IE内存泄露问题。为了解决类似问题，4年前<a href="http://simon.incutio.com/archive/2004/05/26/addLoadEvent">Simon Willison</a>就写出了很流行的addLoadEvent()：</p>
<pre><code>function addLoadEvent(func) {
 var oldonload = window.onload;
 if (typeof window.onload != 'function') {
  window.onload = func;
 }else {
  window.onload = function() {
   oldonload();
   unc();
  }
 }
}
addEvent(window,'load',func1,false);
addEvent(window,'load',func2,false);
addEvent(window,'load',func3,false);
</code></pre>
<p>当然在JavaScript库盛行的现在，使用封装好的事件处理机制是一个很好的选择，比如在YUI中就可以这样写：</p>
<pre><code>YAHOO.util.Event.addListener(window, "click", MyOnClickMethod);</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/10/27/javascript-gotchas/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Javascript的匿名函数</title>
		<link>http://dancewithnet.com/2008/05/07/javascript-anonymous-function/</link>
		<comments>http://dancewithnet.com/2008/05/07/javascript-anonymous-function/#comments</comments>
		<pubDate>Tue, 06 May 2008 17:14:40 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[函数]]></category>
		<category><![CDATA[匿名函数]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1297</guid>
		<description><![CDATA[一、什么是匿名函数？
在Javascript定义一个函数一般有如下三种方式：

函数关键字(function)语句：
function fnMethodName(x){alert(x);}

函数字面量(Function Literals)：
var fnMethodName = function(x){alert(x);}

Functio... ]]></description>
			<content:encoded><![CDATA[<h3>一、什么是匿名函数？</h3>
<p>在Javascript定义一个函数一般有如下三种方式：</p>
<ol>
<li><strong>函数关键字(function)语句</strong>：
<pre><code>function fnMethodName(x){alert(x);}</code></pre>
</li>
<li><strong>函数字面量(Function Literals)</strong>：
<pre><code>var fnMethodName = function(x){alert(x);}</code></pre>
</li>
<li><strong>Function()构造函数</strong>：
<pre><code>var fnMethodName = new Function('x','alert(x);')</code></pre>
</li>
</ol>
<p>上面三种方法定义了同一个方法函数fnMethodName，第1种就是最常用的方法，后两种都是把一个函数复制给变量fnMethodName，而这个函数是没有名字的，即匿名函数。实际上，<a href="http://en.wikipedia.org/wiki/Anonymous_function">相当多的语言都有匿名函数</a>。<span id="more-1297"></span></p>
<h3>二、函数字面量和Function()构造函数的区别</h3>
<ol>
<li>虽然函数字面量是一个匿名函数，但语法允许为其指定任意一个函数名，当写递归函数时可以调用它自己，使用Function()构造函数则不行。
<pre><code>var f = function fact(x) {
  if (x < = 1) return 1;
  else return x*fact(x-1);
};</code></code></pre>
</li>
<li>Function()构造函数允许运行时Javascript代码动态的创建和编译。在这个方式上它类似全局函数eval()。</li>
<li>Function()构造函数每次执行时都解析函数主体，并创建一个新的函数对象。所以当在一个循环或者频繁执行的函数中调用Function()构造函数的效率是非常低的。相反，函数字面量却不是每次遇到都重新编译的。</li>
<li>用Function()构造函数创建一个函数时并不遵循典型的作用域，它一直把它当作是顶级函数来执行。
<pre><code>var y = "global";
function constructFunction() {
    var y = "local";
    return new Function("return y");  <span>//  无法获取局部变量</span>
}
alert(constructFunction()());  <span>// 输出 "global"</span>
</code></pre>
</li>
</ol>
<p>和函数关键字定义相比Function()构造器有自己的特点且要难以使用的多，所以这项技术通常很少使用。而函数字面量表达式和函数关键字定义非常接近。考虑前面的区别，虽然有消息说字面量的匿名函数在OS X 10.4.3下的某些webkit的引擎下有bug，但我们平常所说的匿名函数均指采用函数字面量形式的匿名函数。更多详细内容可以阅读《JavaScript: The Definitive Guide, 5th Edition》的Functions那章。</p>
<h3>三、匿名函数的代码模式</h3>
<p>昨天<a href="http://www.hedgerwow.com">hedger wang</a>在他的blog介绍了<a href="http://www.hedgerwow.com/360/dhtml/js-anonymous-function-patterns.html">几种匿名函数的代码模式</a>：</p>
<p><strong>错误模式</strong>：其无法工作，浏览器会报语法错。</p>
<pre><code>function(){
  alert(1);
}();</code></pre>
<ol>
<li><strong>函数字面量</strong>：首先声明一个函数对象，然后执行它。
<pre><code>(function(){
  alert(1);
} ) ( );</code></pre>
</li>
<li><strong>优先表达式</strong>：由于Javascript执行表达式是从圆括号里面到外面，所以可以用圆括号强制执行声明的函数。
<pre><code>( function(){
  alert(2);
} ( ) );</code></pre>
</li>
<li><strong>Void操作符</strong>：用void操作符去执行一个没有用圆括号包围的一个单独操作数。
<pre><code>void function(){
  alert(3);
}()</code></pre>
</li>
</ol>
<p>这三种方式是等同的，hedger wang因为个人原因比较喜欢第3种，而在实际应用中我看到的和使用的都是第1种。</p>
<h3>四、匿名函数的应用</h3>
<ol>
<li><a href="http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/">《Javascript的一种模块模式》</a>中的第一句话就是“全局变量是魔鬼”。配合var关键字，匿名函数可以有效的保证在页面上写入Javascript，而不会造成全局变量的污染。这在给一个不是很熟悉的页面增加Javascript时非常有效，也很优美。实际上，<a href="http://developer.yahoo.com/yui/">YUI</a>以及其相应的范例中大量使用匿名函数，其他的Javascript库中也不乏大量使用。</li>
<li>Javascript的函数式编程(functional programming)的基石。具体请看<a href="http://www.ibm.com/developerworks/cn/web/wa-javascript.html">《用函数式编程技术编写优美的 JavaScript》</a>和<a href="http://shiningray.cn/functional_javascript_programming.html">《函数式JavaScript编程指南》</a>。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/05/07/javascript-anonymous-function/feed/</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
	</channel>
</rss>

