jquery 中 (function( window, undefined ) {})(window)写法详解(转)
最常见的闭包 (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 形参);我们还要尽量避免使用字符串常量。
因此,在jquery中经常会将$.extend()和$.fn.extend()放到类似于上面的写法中,即(function($,undefined))(jQuery)。那么内部的$都指向jQyery。
-----------------
(function(undefined){
//do something
})() //1
在闭包行参使用undefined而不是从外部1处传入参数,这样做是考虑到在undefined在外部被赋值情况,那么这时候在闭包内部使用undefined就会出现问题了,那么就需要
if(typeof undefined === 'undefined') {
//
} 17jquery.com
判断。在外部不传参数情况下,闭包内部使用形参在没有赋值时undefined将会保持原本含义,这是由JavaScript 作用域规则决定。
为了不让内部的undefined不会被污染,在形参中默认加上undefined,所以在jquery等js库源代码会看到
(function(window,undefined){
//todo something
})()
这样代码。在形参中传入默认window也是;类似一样的原理。
最后可以测试下:
var undefined = 123;
(function(undefined){
console.info(undefined);
})() //在参数中传入undefined和不传情况下会输出什么?
jquery 中 (function( window, undefined ) {})(window)写法详解(转)的更多相关文章
- Jquery中find与each方法使用详解
本文实例讲述了jQuery中find与each方法用法.分享给大家供大家参考.具体如下: 一.find()方法 jquery选择器非常强大,利用css的命名规约,可以更快更方便的找出想要的元素. 图解 ...
- JavaScript文件中; !function (win, undefined) {}(window);的意义
+function (){}-function (){}!function (){}~function (){}(function (){})() 这种写法可以保证匿名函数立即运行且运行一次 传入的 ...
- jQuery中$.ajax()和$.getJson()同步处理详解
一.前言 为什么需要用到同步,因为有时候我们给一个提交按钮注册提交表单数据的时候,在提交动作之前会进行一系列的异步ajax请求操作,但是页面js代码会按顺序从上往下面执行,如果你在这过程中进行了异步操 ...
- jQuery中mouseleave和mouseout的区别详解
很多人在使用jQuery实现鼠标悬停效果时,一般都会用到mouseover和mouseout这对事件.而在实现过程中,可能会出现一些不理想的状况. 先看下使用mouseout的效果: <p> ...
- .htaccess中的apache rewrite规则写法详解
.htaccess中的apache rewrite写法: 1 RewriteEngine On 2 RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$ 3 Rewr ...
- Jquery中attr与prop的区别详解
prop()函数的结果: 1.如果有相应的属性,返回指定属性值. 2.如果没有相应的属性,返回值是空字符串. attr()函数的结果: 1.如果有相应的属性,返回指定属性值. 2.如果没有相应的属性, ...
- .htaccess中的apache rewrite规则写法详解(未完)
转:http://www.cnblogs.com/adforce/archive/2012/11/23/2784664.html http://blog.csdn.net/Long_Xiao_Yun/ ...
- jquery源码中的(function(window, undefined){})(window)【转】
(function( window, undefined ) {})(window);这个,为什么要将window和undefined作为参数传给它? (function( $, undefined ...
- JS 关于(function( window, undefined ) {})(window)写法的理解
JS 关于(function( window, undefined ) {})(window)写法的理解 [网络整理] (function( window, undefined ) {})(windo ...
- window.onload和JQuery中$(function(){})的区别即其实现原理
一.区别 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. 在Jquery中$(function(){ })和$(document).ready(function(){ ...
随机推荐
- Qt Project的持续集成方案
作者:齐亮链接:http://www.zhihu.com/question/24314354/answer/27547787来源:知乎著作权归作者所有,转载请联系作者获得授权. PETER HARTM ...
- WPF笔记(1.6 数据绑定)——Hello,WPF!
原文:WPF笔记(1.6 数据绑定)--Hello,WPF! 这个一节都是在讲一个数据绑定的示例.功用:输入姓和名,点击Add按钮,ListBox增加一条记录,永远是字符串“name: nick”:L ...
- 用来控制 XML 序列化的属性
通过将下表中的属性应用于类和类成员,可以控制 XmlSerializer 序列化或反序列化该类的实例的方式.若要了解这些属性如何控制 XML 序列化,请参见使用属性控制 XML 序列化. 这些属性还可 ...
- 2015第10周日CSS—3
CSS各种居中方法 CSS的居中有水平居中和垂直居中,这两种居中又分为行内元素居中和块级元素居中,不同的居中用不同方法. 水平居中 1.行内元素水平居中(文本,图片) 给父层设置 text-align ...
- 使用 ServKit(PHPnow) 搭建 PHP 环境[图]
http://servkit.org/guide 搭建 PHP 其实不很难,只是有点繁琐.要是自己搭建一次 PHP + MySQL 环境很是费时.更糟的是,很多新手在配置 PHP 时常常出现这样那样的 ...
- 动态创建和移除HTML标签
1.w3school定义 添加新内容的四个 jQuery 方法: append() - 在被选元素的结尾插入内容 prepend() - 在被选元素的开头插入内容 after() - 在被选元素之后插 ...
- 搜索和搜索形式(SEARCHING and its forms)
什么是搜索? 在计算机科学中,搜索就是在一个事物的集合中找到具有特定特征的一项的过程.这些集合中的元素可能是排好序的数据库中的记录,简单数组中的数据,文件中的文本,树中的节点,几何图形中的点和边或者是 ...
- javadoc 生成帮助文档时,注意以下几点
参考:http://www.w3school.com.cn/tags/tag_pre.asp javadoc 生成帮助文档时,注意以下几点: 1.函数功能描述的结尾一定要有句号,英文句号或中文句号均可 ...
- IP、路由配置
IP地址组成: 网络地址主机地址32位二进制 A类: 255.0.0.0, 8: 0 000 0001 - 0 111 1111 127个A类,127用于回环,1-126 2^7- ...
- Class对象
(一) 获得Class对象的四种方式 第1种方法:Object.getClass() 第2种方法:.class语法 第3种方法:Class.forName() 第4种方法:包装类的TYPE域 impo ...