js 文件里,匿名函数开头有个 ;! 意义是什么?

2017-05-19 19:49:55 +08:00
 JiaFeiX
这是在贤心大神的 layim 代码里看到的,开头是 ;!function ( win,undefined ) {}结束还有个 ( window ) 啥意义呢? 是封装吗?

截图:

开头部分:
![]( http://i1.piimg.com/1949/18b3450b8154251e.jpg)


结尾部分:

![]( http://i1.piimg.com/1949/2ce400a94a6fcc43.png)
4298 次点击
所在节点    问与答
20 条回复
JiaFeiX
2017-05-19 19:51:43 +08:00
为了封装起来调用吗
atan
2017-05-19 19:59:23 +08:00
分号是为了合并压缩的时候和其他函数做分割用的;感叹号是用于立即执行函数的,你可以换成加号减号的,和用括号包裹函数体作用一样
newworld
2017-05-19 20:02:36 +08:00
@atan #2 感谢 借楼长知识了 思密达
JiaFeiX
2017-05-19 22:32:07 +08:00
JiaFeiX
2017-05-19 22:36:51 +08:00
@atan

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

最后括号里的 window 意义是什么? 看到 jquery 也是这样的, ( win,undefined ) 为什么是这两个参数呢?
JiaFeiX
2017-05-19 22:41:23 +08:00
JiaFeiX
2017-05-19 22:43:10 +08:00
@atan

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

这个函数,是不是吧 window 对象给装进去 作为函数的参数了?
hahamy
2017-05-19 22:51:52 +08:00
@JiaFeiX 是的
var a = function(win, undefined){};
a(window);
JiaFeiX
2017-05-19 23:26:59 +08:00
@hahamy

window 是指的一个 整个 window 对象都传进去了? 为什么这么做呢?
littleylv
2017-05-19 23:29:17 +08:00
谷歌:闭包
broven
2017-05-19 23:49:55 +08:00
明确依赖吧, 告诉你这个闭包里,明确的依赖了某一个对象,window 对象同理。
yangff
2017-05-20 00:45:04 +08:00
而且因为 undefined 可能不是 undefined ……
比如
(function (undefined) { console.log(undefined); }) (1)
atan
2017-05-20 01:51:16 +08:00
window 参数的目的是将本来 window 这个全局对象变成自执行函数内部的局部对象;
undefined 是确保自执行函数内部的 undefined 是真的未定义,万一被重写了赋了其他值
geelaw
2017-05-20 05:47:43 +08:00
@atan
@broven
@yangff

我认为这里 window 传入的作用是减少代码长度,因为参数名叫 win。

另外我无法理解为什么有人要把 undefined 改成不是 undefined,这听起来就像是在 C++ 里面写

#define false true

一样
yyfearth
2017-05-20 08:50:58 +08:00
@JiaFeiX @atan @yangff
这样做主要目的是为了更好的 minify 代码压缩 同时减少兼容性问题

; 为了保障文件在合并的时候没有换行的问题
!function(){} +function(){} 作用和 (function(){}()) 一样立即执行函数 一般是 minify 后的代码有这样用

(function(global, undefined){} (window 或者 this)) 这样做有 2 个好处
一个是保证 global 和 undefined 不随便被改掉 以及不同平台兼容性问题
同时 minify 过后 window 和 undefined 这样在参数里面变成了局部变量 可以被更短的名字替换
比如变成 !function(g, u){} (window 或者 this) 这样就省了很多字节

@geelaw undefined 那个好像是个历史遗留问题 这样做可以保证不被篡改
同时这样写就和 win 一样 minify 后可以减少代码长度
MrFireAwayH
2017-05-20 10:18:46 +08:00
@yyfearth 你的说法是对的

+function (){}
-function (){}
!function (){}
~function (){}
(function (){})()

这种写法可以保证匿名函数立即运行且运行一次

传入的 window 对象从全局变成了局部对象 优点有

1. 运行更快了
2. 可以随意改名 比如 a, 这样便于压缩
3. 可以传入其他库而不导致冲突

举例子
(function ($, w, d, undefined){

$(document).addClass('test');

})(jQuery, window, document);

这样的情况下 JQ 可以无痛使用 也不需要使用 noConflict 方法避免冲突

至于传递 undefined 是因为 ES3 时代这个玩意儿是可以被修改的……真的有人会去做比如 undefined = true 这样的事情 所以说额外定义一个真正的 undefined 可以保证匿名函数内部的 undefined 是真正的 undefined(好累……😪)

最后……

@geelaw 又看到你了😝
JiaFeiX
2017-05-20 12:55:39 +08:00
@MrFireAwayH 手工感谢, 解释的很清楚。

另外,有个疑问

> 传入的 window 对象从全局变成了局部对象 优点有 运行更快了

运行的更快了, 原理是什么?
AnonymousID
2017-05-20 14:44:54 +08:00
@JiaFeiX 将 window 变为局部对象后,当在局部作用域内查找 window 时就直接能找到,如果不传入那么会顺着作用域链向上找,所以缩短了作用域链,缩短了查找过程,所以更快了,不知这样理解对不对
HYSS
2017-05-20 15:12:37 +08:00
@atan 想问下你是从哪知道的
MrFireAwayH
2017-05-21 01:45:42 +08:00
@AnonymousID 你说的很有道理

就是作用域的问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/362526

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX