首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
V2EX  ›  问与答

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

  •  
  •   JiaFeiX · 2017-05-19 19:49:55 +08:00用 iPhone 发布 · 3072 次点击
    这是一个创建于 760 天前的主题,其中的信息可能已经有所发展或是发生改变。
    这是在贤心大神的 layim 代码里看到的,开头是 ;!function ( win,undefined ) {}结束还有个 ( window ) 啥意义呢? 是封装吗?

    截图:

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


    结尾部分:

    ![]( http://i1.piimg.com/1949/2ce400a94a6fcc43.png)
    20 回复  |  直到 2017-05-21 01:45:42 +08:00
        1
    JiaFeiX   2017-05-19 19:51:43 +08:00 via iPhone
    为了封装起来调用吗
        2
    atan   2017-05-19 19:59:23 +08:00   ♥ 5
    分号是为了合并压缩的时候和其他函数做分割用的;感叹号是用于立即执行函数的,你可以换成加号减号的,和用括号包裹函数体作用一样
        3
    newworld   2017-05-19 20:02:36 +08:00
    @atan #2 感谢 借楼长知识了 思密达
        5
    JiaFeiX   2017-05-19 22:36:51 +08:00
    @atan

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

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

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

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

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

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

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

    #define false true

    一样
        15
    yyfearth   2017-05-20 08:50:58 +08:00   ♥ 1
    @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 后可以减少代码长度
        16
    MrFireAwayH   2017-05-20 10:18:46 +08:00 via Android   ♥ 1
    @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 又看到你了😝
        17
    JiaFeiX   2017-05-20 12:55:39 +08:00
    @MrFireAwayH 手工感谢, 解释的很清楚。

    另外,有个疑问

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

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

    就是作用域的问题
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2501 人在线   最高记录 5043   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 21ms · UTC 15:10 · PVG 23:10 · LAX 08:10 · JFK 11:10
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1