两个大的信息来源:teacher与segmentfault论坛,以此分为两大板块javascript
第一大板块:一个普通的自调用函数==》加了各类参数的自调用函数==》参数的两个做用==》类比到jQuery的源代码封装==》结论java
第二大板块:论坛的问题==》论坛的被采纳的回答==》简易版的回答,回答中解释了为何要加上window,jquery,undefined.jquery
演变历程chrome
1.原函数segmentfault
(function(){ console.log(1) })()
2.加window参数浏览器
(function(window){ console.log(window) })(window)
此时的window不是全局变量,而是局部变量,虽然去打印的话,出来的效果是同样的。框架
形参的位置能够是其余任意字符,反正传进去的实参是window。
好比:函数
(function(w){ console.log(w) })(window)
3.函数执行-------做用一性能
(function(window){ //函数内部是隔离的区域 console.log(window) })(window)
函数执行过程当中,若是能在参数处找到window,那么就不会去全局做用域中找,因此结果就是:效率高,提高性能。(效率高==提高性能,多了一句废话,可是也有助于理解)测试
4.代码压缩-------做用二
(function(w){ //函数内部是隔离的区域 console.log(w) })(window)
说明:代码打包上传的时候,或者说代码发布的时候,也就是网站上线的时候,代码会被压缩,此时原本的形参是window,会被压缩成一个字符w,这样字符变少了,就节省了空间。
5.是否能够不添加?天然是能够的
(function(){ //函数内部是隔离的区域 console.log(window) })()
说明:此时没有传window实参,形参也没有传,可是内部依然能够访问到window,由于window是全局变量,在哪里均可以访问到。
注意:此时寻找window去全局做用域中找,因此效率低一些;而且压缩的时候window不会被压缩,由于压缩了浏览器就不认识了啊,无法解析了,因此这样的参数就无法压缩。
类比到jQuery
jQuery的封装:jQuery源代码的最外层就是这样作的
1.jQuery源代码的最外层就是这样作的:传入window与undefined
(function(window,undefined){ //函数内部是隔离的区域 console.log(window) })(window)
2.一个事实:早期的浏览器中undefined能够修改,新版本浏览器不能修改了
undefined=123; console.log(undefined);//结果是123;如今的结果仍是undefined
3.jQuery源代码作法的优势:
更严谨,不管是什么浏览器,里边的undefined都不会被更改。由于函数寻找的时候会优先找到做为参数传过来的undefined,而不会去全局找。
当心得:学任何技术不要局限于怎么用,而要刨根问底的看是怎么实现的。这样进步会更快。
window做为实参的用意:提升性能;方便代码压缩。
undefined做为形参的用意:防止undefined的值被修改(早期的低版本浏览器中)。最新的浏览器已经把这个bug修复了。
问题:像下边这样的代码为何要把window, jQuery对象传进去
(function (window, $, undefined) { play=function(){ $("#demo").val("This is a demo."); } window.wbLogin = play; })(window, jQuery);
为何要传入 jQuery
经过定义一个匿名函数,建立了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏全局的命名空间。这点很是有用也是一个 JS 框架必须支持的功能,jQuery 被应用在成千上万的 JavaScript 程序中,必须确保 jQuery 建立的变量不能和导入他的程序所使用的变量发生冲突。
为何要传入 window
经过传入 window 变量,使得 window 由全局变量变为局部变量,当在 jQuery 代码块中访问 window 时,不须要将做用域链回退到顶层做用域,这样能够更快的访问 window;这还不是关键所在,更重要的是,将 window 做为参数传入,能够在压缩代码时进行优化,看看 jquery-1.6.1.min.js:
(function(a,b){})(window); // window 被优化为 a
为何要传入 undefined
在自调用匿名函数的做用域内,确保 undefined 是真的未定义。由于 undefined 可以被重写,赋予新的值。
undefined = "now it's defined";
alert( undefined );
浏览器测试结果:
浏览器 测试结果 结论
ie11 undefined 不能改变
firefox22 undefined 不能改变
chrome31 undefined 不能改变
opera12 undefined 不能改变
一句话,使全局变量以参数形式变成自执行函数内部的局部变量。
至于为何这么作,提升程序效率。为何能提升效率,得从javascript的机制提及,所谓的scope chain做用域链,在当前做用域中若是没有该属性(局部变量)则向上一层做用域中寻找,一直到最上层,也就是window。也就是说全局变量和下级做用域都是window的一个属性,向下依此类推。
另外jQuery传入后将参数写成$能够保证在此函数内$为jquery而不是其余相似使用$符号的库。
undefined同理,因为没有传入第三个参数,天然就是undefined。因为javascript中undefined是一个变量,能够被改变,因此这样能够保证undefined判断时的准确性。有时判断时使用typeof xxx === 'undefined'也是由于这个缘由。