最近尝试研究某 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 对象吗?
问题有点多,请赐教。
1
chemzqm 2016-11-01 18:06:15 +08:00
UMD 封装,可以支持全局方式加载,以及 AMD 和 CMD 方式加载
https://github.com/umdjs/umd |
2
cheetah 2016-11-01 18:08:16 +08:00
factory 就是
``` function($) { /* code1 */ } ``` 这个匿名函数 |
3
wesley 2016-11-01 18:10:34 +08:00
前 3 个问题:
这段代码 (function(par1, par2) { /* code3 */ }(par3, par4)); 写成这种形式你就明白了 function xxx(par1,par2){ ....... } xxx(par3, par4); |
4
palmers 2016-11-01 18:34:10 +08:00
>
五、 05 行的 factory(require('jquery')) 看不懂 这个是将 jquery 模块化使用支持。 我是参考 Node.js 模块化想的,我想应该不会错的。 |
5
beginor 2016-11-01 18:50:38 +08:00 via Android
umd,同时适应 amd 和 cjs
|
6
des 2016-11-01 19:18:28 +08:00 via Android
简单的说下吧,第九、十行是一个包裹函数,期待一个 jq 对象,用来拓展$.fn
第三、五行分别是不同的封装用来获取 jQuery 对象,并注入到 factory 中,也就是前面的包裹函数。 第七行是直接从全局拿 jQuery ,然后注入。 至于第五行的 module.exports 和 require 你去了解一下 AMD/UMD 的写法就清楚了 |
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 */ } 导出成模块。 |
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 传进去。 |
9
ryanzyy 2016-11-02 12:35:17 +08:00
楼上回答地非常详细
补充一句 "从整体上了解整段代码" --> 这段代码的服务对象是你. 让你在任何地方都能使用这个 module. 包括你最终在浏览器里运行的产品以及你的测试代码 ref: http://bob.yexley.net/umd-javascript-that-runs-anywhere/ |