如何理解以下这段 Javascript 封装代码? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
jmyz0455
V2EX    Javascript

如何理解以下这段 Javascript 封装代码?

  •  
  •   jmyz0455 2016-11-01 17:56:23 +08:00 2482 次点击
    这是一个创建于 3342 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近尝试研究某 jquery 插件,但是最外层的封装代码看不明白。搜索出来的文章都是各有各说,很难让我从整体上了解整段代码。请教下怎么理解下面这段代码:

    01 (function(root, factory) { 02 if (typeof define === 'function' && define.amd) { 03 define('jqname', ['jquery'], factory); 04 } else if (typeof exports === 'object') { 05 module.exports = factory(require('jquery')); 06 } else { 07 factory(root.jQuery); 08 } 09 }(this, function($) { 10 /* code1 */ 11 })); 

    一、 root 我知道是 Window 对象,那请问 01 行的 factory 对应什么对象? console 输出来是整个 /* code1 */ 的部分,网上一搜 "factory" 都是讲工厂模式的,看后对应题目的代码还是想不明白。

    二、我知道下面这种 IIFE 写法

    (function(){ /* code2 */ }()); (function(){ /* code2 */ })();
    但是把题目的代码简化后如下

    (function(par1, par2) { /* code3 */ }(par3, par4));

    那样写的话,后面的 (par3, par4) 就不是分组操作符了吧?那整段题目为什么要那样写、作用又是什么呢? 三、请问 01 行的两个参数是 "谁" 传进去的?(或者说匿名函数的参数是怎么传进去的?立即执行时函数段从哪里获取参数呢?)

    四、 02 至 08 行我的理解是,检测网页的 Javascript 是使用何种规范。如果是 AMD ,必然会已声明 define 全局变量,然后 03 行会执行模块加载代码;如果是 CMD ,就会执行 05 行来加载模块。这样理解正确吗?

    五、 05 行的 factory(require('jquery')) 看不懂

    六、 07 行的 factory(root.jQuery) 看不懂

    七、 09 行的 this 是指 Window 对象吗?

    问题有点多,请赐教。

    9 条回复    2016-11-02 12:35:17 +08:00
    chemzqm
        1
    chemzqm  
       2016-11-01 18:06:15 +08:00
    UMD 封装,可以支持全局方式加载,以及 AMD 和 CMD 方式加载
    https://github.com/umdjs/umd
    cheetah
        2
    cheetah  
       2016-11-01 18:08:16 +08:00
    factory 就是

    ```
    function($) {
    /* code1 */
    }
    ```

    这个匿名函数
    wesley
        3
    wesley  
       2016-11-01 18:10:34 +08:00
    前 3 个问题:
    这段代码
    (function(par1, par2) {
    /* code3 */
    }(par3, par4));
    写成这种形式你就明白了
    function xxx(par1,par2){
    .......
    }
    xxx(par3, par4);
    palmers
        4
    palmers  
       2016-11-01 18:34:10 +08:00
    >
    五、 05 行的 factory(require('jquery')) 看不懂

    这个是将 jquery 模块化使用支持。

    我是参考 Node.js 模块化想的,我想应该不会错的。
    beginor
        5
    beginor  
       2016-11-01 18:50:38 +08:00 via Android
    umd,同时适应 amd 和 cjs
    des
        6
    des  
       2016-11-01 19:18:28 +08:00 via Android
    简单的说下吧,第九、十行是一个包裹函数,期待一个 jq 对象,用来拓展$.fn
    第三、五行分别是不同的封装用来获取 jQuery 对象,并注入到 factory 中,也就是前面的包裹函数。
    第七行是直接从全局拿 jQuery ,然后注入。
    至于第五行的 module.exports 和 require 你去了解一下 AMD/UMD 的写法就清楚了
    lijsh
        7
    lijsh  
       2016-11-01 22:09:38 +08:00
    你找个好点的编辑器看清楚代码块开合,首先是匿名函数立即调用的问题,整个代码块大概是这样的形式
    (function(root, factory) {
    /* 模块导入的逻辑 */
    } (this, function($) { /* 模块的实际逻辑 */ }));

    这里使用 IIFE 将 this 作为实参传进去作为 root , function($) { /* code1 */ } 这个函数传进去作为 factory (所以你 console 才会输入 code1 ),这个 factory 才是整个插件的实际逻辑。

    至于模块导入,也就是那串 if ... else if ... else 的逻辑,分别对应 amd 、 commonjs 和 window 全局的三种格式,最终都是把 function($) { /* code1 */ } 导出成模块。
    lijsh
        8
    lijsh  
       2016-11-01 22:14:33 +08:00
    补充一下, function($) { /* code1 */ } 里要传进$,明显是 jQuery 了, amd 、 commonjs 和 window 全局三种规范导入 jQuery 模块的方式也并不相同,因此
    if (typeof define === 'function' && define.amd) {
    define('jqname', ['jquery'], factory);
    } else if (typeof exports === 'object') {
    module.exports = factory(require('jquery'));
    } else {
    factory(root.jQuery)
    }
    这一段的大概逻辑是
    if 是 amd 模块规范( define 是个函数),使用 amd 模块规范将 jQuery 传给 function($) { /* code1 */ }
    else if 是 commonjs 规范( exports 是个已定义的 object ),使用 commonjs 规范将 jQuery 传给 function($) { /* code1 */ }
    else 没有模块规范,直接找 window.jQuery 传进去。
    ryanzyy
        9
    ryanzyy  
       2016-11-02 12:35:17 +08:00
    楼上回答地非常详细
    补充一句 "从整体上了解整段代码" --> 这段代码的服务对象是你. 让你在任何地方都能使用这个 module. 包括你最终在浏览器里运行的产品以及你的测试代码
    ref: http://bob.yexley.net/umd-Javascript-that-runs-anywhere/
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2681 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 11:40 PVG 19:40 LAX 03:40 JFK 06:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86