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 · 2205 次点击
    这是一个创建于 2933 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近尝试研究某 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   ·   实用小工具   ·   5841 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 01:51 · PVG 09:51 · LAX 17:51 · JFK 20:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.