文档章节

(function (window, undefined){})(window)

i
 imhan
发布于 2015/10/12 15:40
字数 908
阅读 13
收藏 0

 (转)最常见的闭包 (Closure) 范式大家都很熟悉了:

123 (function() {// ...})();

很简单,大家都在用。但是,我们需要了解更多。
首先,闭包是一个匿名函数 (Anonymous function), 即是 (function() {}) 这部分。之所以要给 function 添加括弧是为了让它形成一个表达式 (expression), 有了表达式,并且确定它的类型是个函数 (Function 实例), 就可以直接调用它。所以,后面的一对括弧是可以工作的,它的意义是:我要调用 (call) 这个函数。

既然是函数调用,那就可以像一般的函数那样,在调用时传入参数。这就是本次讨论的话题。

传入 window 参数

 

123 (function(win) {// ...})(window);

这样做最直观的好处是书写便利:少写几个字。你可以在闭包内任何地方使用 win, 它都会指向 window 对象。另外,它有利于压缩减少最终代码的体积,经过压缩后 (如 Google Closure Complier), 所有的 win 都会被替换成形如 a 这样的简单变量。win 用得越多,减少的字节数也越多。

不过,便利的同时也会带来陷阱。在 IE 上,window 总是指向当前窗口对象,这个没有问题,但是在某些场景下,使用闭包内的 win 变量会导致拒绝访问错误 (Access denied). 重现方式大致是这样的:当页面引用其他域名的脚本,并且该脚本调用了闭包内的 window.document, 而且这个闭包代码是来自另一个域名的脚本。在这种情况下,使用 win 会保持对 window 最早的引用,通过另一个域的脚本访问 win 会导致 IE 认为脚本产生了跨越冲突,从而拒绝了对 win.document 的访问。解决办法是不使用形参 win, 而是直接使用 window. 需要说明的是,给闭包传入 document 也会导致 IE 出现同样的问题。

传入 undefined

其实把 undefined 作为形参就,实参就可以不用传了,因为 JavaScript 中访问未传入的参数就会得到 undefined. 因此,你可以这样写:

123 (function(undefined) {// ...})();

和上面的讨论一样,你可以在闭包内任何地方使用 undefined, 可以少写几个字(如果把 undefined 换成更短的名字),也可以在减少压缩后体积。

另一个的优势是,你可以认为它是个变量,把它当变量来使用,它的值恒等于 (===) 真正的 undefined. 当外部代码意外地定义了 undefined 的时候——不常见,但确实可能会发生——你可以正常地使用真正的 undefined, 而不会被外部的 undefined 意外影响. 这是由 JavaScript 作用域规则决定的。
无论是否使用这个 undefined 参数,都应该避免使用 undefined 的字符串常量,如:

123 if(typeofmyVar === 'undefined') {// bad part...}

因为如果你把字符串写错了,机器不会告诉你,而且会产生一个难以检查出来的bug. 幸运的是,对于 JavaScript 来说,JsLint 可以帮你做这个校验。当 myVar 已定义的时候(通过形参或 var 声明),上面的代码改成这样会更易于调试:

123 if(myVar === undefined) {// good part...}

结论

从上面两个例子来看,我们建议不要传入 window, 但是可以安全地使用第二种方式 (写 undefined 形参);我们还要尽量避免使用字符串常量。
最后,最重要的是,这只是两个特定对象和类型的讨论,举一反三,你会更了解 JavaScript


© 著作权归作者所有

i
粉丝 0
博文 5
码字总数 1691
作品 0
朝阳
私信 提问
分析(function(window, undefined) {})(window)

有的时候,我们会在JS框架中看到这行 (function(window, undefined) {})(window) ,它是做什么用的,我们来分析下它 首先这就是一个匿名函数,立即执行它 (function(window, undefined) { }...

青丘
2018/07/30
0
0
像数学公式一样彻底简单理解JavaScript函数调用与this 指针

一直以来,大家都对函数的调用有很多的疑惑,特别是this指针的指向。 其实理解了核心的原理之后,就很容易理解,甚至就是套用数学公式一样! 核心原理 让我们看看原始的函数调用语句,也就是c...

文叔叔
05/14
0
0
JavaScript中this的指向问题归纳总结

前言 js中this指向问题是个老生常谈的问题了,下面这篇文章再来给大家介绍下,大家可以看看,更深入的了解了解,下面话不多说了,来一起看看详细的介绍吧 thisthis:上下文,会根据执行环境变化...

peakedness丶
2018/12/09
68
0
JavaScript之apply、call详解

call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向。 call 和 apply二者的作用完全一样,只是接受参数的方式不太一样。...

飛飛飛jjs
2016/11/22
0
0
JavaScript实现多态和继承的封装操作示例

封装Encapsulation 如下代码,这就算是封装了 继承Inheritance 前端全栈学习交流圈:866109386,面向1-3经验年前端开发人员,帮助突破技术瓶颈,提升思维能力 运行结果如下:多态Polymorphism ...

peakedness丶
2018/11/29
11
0

没有更多内容

加载失败,请刷新页面

加载更多

总结:TCP/IP协议

一、介绍 TCP协议属于OSI七层模型中的传输层协议,提供处于网络连接中的两台计算机之间的数据 传输。   在传输层有两个性质不同的协议:TCP(Transmission Control Protocol,传输控制协议...

浮躁的码农
31分钟前
3
0
一言不合就删库跑路?万名贡献者和阿里巴巴开源的二三事

9 月 27 日云栖大会,阿里巴巴宣布贾扬清担任开源技术委员会负责人。 有人问:开源是为了什么? 从个人视角看,可以证明自己的专业能力,获得行业认可; 从企业视角看,可以建立技术影响力,...

大涛学弟
42分钟前
4
0
JAVA编程注意事项(性能篇)

1. 尽量在合适的场合使用单例 使用单例可以缩短加载的时间,提高加载的效率,单例主要适用于以下三个方面: 第一,控制资源的使用,通过线程同步来控制资源的并发访问; 第二,控制实例的产生...

你好夜故事
43分钟前
5
0
List 前端 AngularJS JS 对IP排序

数据格式 $scope.dataList=[ {"ip":"192.168.10.10", "port":"8080",...}, { "ip":"192.168.10.12", "port":"8080",... } ,.....] 调用 $scope.ipSortForward($scope.dataList,"ip") 核心代码......

最菜最菜之小菜鸟
44分钟前
4
0
浅析Cassandra LeveledCompactionStrategy

前言 Cassandra是基于LSM架构的分布式数据库。LSM中有一个很重要的过程,就是压缩(Compaction)。默认的压缩策略是SizeTieredCompactionStrategy,今天主要说一下另一种压缩策略LeveledComp...

阿里云官方博客
48分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部