<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[刘新修]]></title> 
<link>http://pic1.liuxinxiu.com:80/index.php</link> 
<description><![CDATA[刘新修的个人博客 (Liuxinxiu'S Blog)]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[刘新修]]></copyright>
<item>
<link>http://pic1.liuxinxiu.com:80/s//</link>
<title><![CDATA[js中(function(){…})()立即执行函数写法理解]]></title> 
<author>刘新修 &lt;admin@yourname.com&gt;</author>
<category><![CDATA[H5/JS/CSS]]></category>
<pubDate>Mon, 24 Aug 2015 04:59:36 +0000</pubDate> 
<guid>http://pic1.liuxinxiu.com:80/s//</guid> 
<description>
<![CDATA[ 
	<p>javascript和其他编程语言相比比较随意，所以javascript代码中充满各种奇葩的写法，有时雾里看花，当然，能理解各型各色的写法也是对javascript语言特性更进一步的深入理解。</p><div>&nbsp;</div><div>( function()&#123;&hellip;&#125; )()和( function ()&#123;&hellip;&#125; () )是两种javascript立即执行函数的常见写法，最初我以为是一个括号包裹匿名函数，再在后面加个括号调用函数，最后达到函数定义后立即执行的目的，后来发现加括号的原因并非如此。要理解立即执行函数，需要先理解一些函数的基本概念。</div><div>&nbsp;</div><div>函数声明、函数表达式、匿名函数</div><div>&nbsp;</div><div>函数声明：function fnName () &#123;&hellip;&#125;;使用function关键字声明一个函数，再指定一个函数名，叫函数声明。</div><div>&nbsp;</div><div>函数表达式 var fnName = function () &#123;&hellip;&#125;;使用function关键字声明一个函数，但未给函数命名，最后将匿名函数赋予一个变量，叫函数表达式，这是最常见的函数表达式语法形式。</div><div>&nbsp;</div><div>匿名函数：function () &#123;&#125;; 使用function关键字声明一个函数，但未给函数命名，所以叫匿名函数，匿名函数属于函数表达式，匿名函数有很多作用，赋予一个变量则创建函数，赋予一个事件则成为事件处理程序或创建闭包等等。</div><div>&nbsp;</div><div>函数声明和函数表达式不同之处在于，一、Javascript引擎在解析javascript代码时会&lsquo;函数声明提升&rsquo;（Function declaration Hoisting）当前执行环境（作用域）上的函数声明，而函数表达式必须等到Javascirtp引擎执行到它所在行时，才会从上而下一行一行地解析函数表达式，二、函数表达式后面可以加括号立即调用该函数，函数声明不可以，只能以fnName()形式调用 。以下是两者差别的两个例子。</div><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span>fnName();&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">function</span><span> fnName()&#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;</span></li><li><span>&#125;&nbsp;&nbsp;</span></li><li class="alt"><span><span class="comment">//正常，因为&lsquo;提升&rsquo;了函数声明，函数调用可在函数声明之前</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp; </span></li><li class="alt"><span>fnName();&nbsp;&nbsp;</span></li><li><span><span class="keyword">var</span><span> fnName=</span><span class="keyword">function</span><span>()&#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;</span></li><li><span>&#125;&nbsp;&nbsp;</span></li><li class="alt"><span><span class="comment">//报错，变量fnName还未保存对函数的引用，函数调用必须在函数表达式之后</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span><span class="keyword">var</span><span> fnName=</span><span class="keyword">function</span><span>()&#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;alert(<span class="string">'Hello World'</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&#125;();&nbsp;&nbsp;</span></li><li class="alt"><span><span class="comment">//函数表达式后面加括号，当javascript引擎解析到此处时能立即调用函数</span><span>&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">function</span><span> fnName()&#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;alert(<span class="string">'Hello World'</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&#125;();&nbsp;&nbsp;</span></li><li class="alt"><span><span class="comment">//不会报错，但是javascript引擎只解析函数声明，忽略后面的括号，函数声明不会被调用</span><span>&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">function</span><span>()&#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;console.log(<span class="string">'Hello World'</span><span>);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li><span>&#125;();&nbsp;&nbsp;</span></li><li class="alt"><span><span class="comment">//语法错误，虽然匿名函数属于函数表达式，但是未进行赋值操作，</span><span>&nbsp;&nbsp;</span></span></li><li><span><span class="comment">//所以javascript引擎将开头的function关键字当做函数声明，报错：要求需要一个函数名</span><span>&nbsp;&nbsp;</span></span></li></ol></div><div>在理解了一些函数基本概念后，回头看看( function()&#123;&hellip;&#125; )()和( function ()&#123;&hellip;&#125; () )这两种立即执行函数的写法，最初我以为是一个括号包裹匿名函数，并后面加个括号立即调用函数，当时不知道为什么要加括号，后来明白，要在函数体后面加括号就能立即调用，则这个函数必须是函数表达式，不能是函数声明。</div><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span>(</span><span class="keyword">function</span><span>(a)&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;console.log(a);&nbsp;&nbsp; <span class="comment">//firebug输出123,使用（）运算符</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;)(123);&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp; </span></li><li class="alt"><span>(<span class="keyword">function</span><span>(a)&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;console.log(a);&nbsp;&nbsp; <span class="comment">//firebug输出1234，使用（）运算符</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;(1234));&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp; </span></li><li class="alt"><span>!<span class="keyword">function</span><span>(a)&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;console.log(a);&nbsp;&nbsp; <span class="comment">//firebug输出12345,使用！运算符</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;(12345);&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp; </span></li><li class="alt"><span>+<span class="keyword">function</span><span>(a)&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;console.log(a);&nbsp;&nbsp; <span class="comment">//firebug输出123456,使用+运算符</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;(123456);&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp; </span></li><li class="alt"><span>-<span class="keyword">function</span><span>(a)&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;console.log(a);&nbsp;&nbsp; <span class="comment">//firebug输出1234567,使用-运算符</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;(1234567);&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp; </span></li><li class="alt"><span><span class="keyword">var</span><span> fn=</span><span class="keyword">function</span><span>(a)&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;console.log(a);&nbsp;&nbsp; <span class="comment">//firebug输出12345678，使用=运算符</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;(12345678)&nbsp;&nbsp;</span></li></ol></div><div><div>可以看到输出结果，在function前面加！、+、 -甚至是逗号等到都可以起到函数定义后立即执行的效果，而（）、！、+、-、=等运算符，都将函数声明转换成函数表达式，消除了javascript引擎识别函数表达式和函数声明的歧义，告诉javascript引擎这是一个函数表达式，不是函数声明，可以在后面加括号，并立即执行函数的代码。</div><div>&nbsp;</div><div>加括号是最安全的做法，因为！、+、-等运算符还会和函数的返回值进行运算，有时造成不必要的麻烦。</div><div>&nbsp;</div><div>不过这样的写法有什么用呢？</div><div>&nbsp;</div><div>javascript中没用私有作用域的概念，如果在多人开发的项目上，你在全局或局部作用域中声明了一些变量，可能会被其他人不小心用同名的变量给覆盖掉，根据javascript函数作用域链的特性，可以使用这种技术可以模仿一个私有作用域，用匿名函数作为一个&ldquo;容器&rdquo;，&ldquo;容器&rdquo;内部可以访问外部的变量，而外部环境不能访问&ldquo;容器&rdquo;内部的变量，所以( function()&#123;&hellip;&#125; )()内部定义的变量不会和外部的变量发生冲突，俗称&ldquo;匿名包裹器&rdquo;或&ldquo;命名空间&rdquo;。</div><div>&nbsp;</div><div>JQuery使用的就是这种方法，将JQuery代码包裹在( function (window,undefined)&#123;&hellip;jquery代码&hellip;&#125; (window)中，在全局作用域中调用JQuery代码时，可以达到保护JQuery内部变量的作用。</div></div>
]]>
</description>
</item><item>
<link>http://pic1.liuxinxiu.com:80/s//#blogcomment</link>
<title><![CDATA[[评论] js中(function(){…})()立即执行函数写法理解]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://pic1.liuxinxiu.com:80/s//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>