文 / 景朝霞
0 / jQuery源码部分解析
$npm init -y
$npm install jquery
node_modules\jquery\dist\jquery.js
查看jQuery的源码
这是我摘取后,改了一下:
var A = typeof window !== "undefined" ? window : this; var B = function (window, noGlobal){}; (function (global, factorys){ "use strict"; if(typeof module === 'object' && typeof module.exports === 'object'){ // 当前运行JS的环境是支持CommonJS模块规范的 // nodejs/webpack支持CommmonJS模块规范 // 浏览器不支持CommonJS模块规范的 } else { // 浏览器或者webview环境 factory(global);//=> B(window) } })(A, B);
△ jquery源码分析
L1:
利用JS的暂时性死区 :基于typeof
检测一个未被声明的变量,结果是undefined
如果是在浏览器或者webview环境下运行JS,则A=>window
在nodejs下运行JS,则A=>global或者当前模块
在浏览器环境下是把B函数执行factory(global)
var B = function (window, noGlobal){ // 浏览器环境下 // window => window // noGlobal => undefined "use strict"; var jQuery = function (selector, context){}; // ...CODE // 在外面用到这个jQuery方法 if(typeof noGlobal === 'undefined'){ // 把私有的方法暴露到全局对象上 window.jQuery = window.$ = jQuery; } };
△ 把jQuery暴露在全局上:window.jQuery = window.$ = jQuery
$()
就是jQuery()
就是让闭包中的jQuery
方法执行
依葫芦画瓢,在我们自己封装组件时:
1、利用闭包的保护作用,把它们都包起来,这样里面写的变量都是私有,防止全局变量污染
2、暴露的API:支持浏览器 和 CommonJS
规范
(function (){ function ModulePlugin(){} // 防止冲突 var _M = window.M; if(typeof window !== 'undefined'){ window.MP = window.ModulePlugin = ModulePlugin; } if(typeof module === 'object' && typeof module.exports === 'object'){ // COMMONJS规范 } })();
△ 自己写组件时:① 闭包 ② 支持浏览器和CommonJS规范
1 / 释放$和jQuery的使用权限
<script src="../node_modules/jquery/dist/jquery.js">script> <script> (function (){ window.$$ = jQuery.noConflict(); //=> 只释放$的使用权限 window.$jq = jQuery.noConflict(true); //=> ① 释放$的使用权限 ② 释放jQuery的使用权限 })();script>
△ jQuery.noConflict的作用
conflict 英 [ˈkɒnflɪkt , kənˈflɪkt] 美 [ˈkɑːnflɪkt , kənˈflɪkt]
n. 冲突;争执;争论;(军事)冲突;战斗;抵触;矛盾;不一致v. (两种思想、信仰、说法等)冲突,抵触
jQuery.noConflict的作用:
① 释放$的使用权限
② 释放jQuery的使用权限
var jQuery = function (selector, context) { return new jQuery.fn.init(selector, context); }; //...CDOE var _jQuery = window.jQuery, _$ = window.$; jQuery.noConflict = function (deep) { if (window.$ === jQuery) { window.$ = _$; } if (deep && window.jQuery === jQuery) { window.jQuery = _jQuery; } return jQuery; }; // 在浏览器中 noGlobal => undefined if (typeof noGlobal === 'undefined') { window.jQuery = window.$ = jQuery; }
△ 从jQuery.js 中粘贴出来的源码,jQuery.noConflict方法释放$的使用权限
代码自上而下执行时:
① var _jQuery = window.jQuery;
var _$ = window.$;
此时window.jQuery 没有这个属性,则:_jQuery = undefined
此时window.$没有这个属性,则:_$= undefined
② jQuery.noConflict = function ....
在jQuery对象上定义了一个方法noConflict
③ window.jQuery = window.$ = jQuery;
在web浏览器上 noGlobal是undefined,能进入判断体
此时:window.jQuery 和 window.$ 都赋值为 jQuery了
那么,可以直接调用 $ 和 jQuery 了 作用域链查找机制
④ window.$$ = jQuery.noConflict();
调用 jQuery.noConflict 方法,把返回值赋值给 window.$$
=> 形参赋值 deep = undefined
=> 代码执行:
=> window.$ === jQuery
--> true 进入判断体
=> window.$ = _$;
其中 _$ 不是自己私有的变量,查找到:_$=undefined,即:window.$=undefined 使用权被释放了
=> deep && window.jQuery === jQuery
其中deep=undefined,不能进入判断体
=> return jQuery;
即:window.$$ = jQuery
⑤ window.$jq = jQuery.noConflict(true);
调用 jQuery.noConflict 方法,把返回值赋值给 window.$jq
=> 形参赋值 deep = true
=> 代码执行:
=> window.$ === jQuery
--> true 进入判断体
=> window.$ = _$;
其中 _$ 不是自己私有的变量,查找到:_$=undefined,即:window.$=undefined 使用权被释放了
=> deep && window.jQuery === jQuery
其中deep=true, window.jQuery === jQuery
也是true,进入判断体
=> window.jQuery = _jQuery;
其中_jQuery 不是自己私有的变量,查找到:_jQuery = undefined,即:window.jQuery = undefined 使用权被释放了
=> return jQuery;
即:window.$jq = jQuery
jQuery.noConflict 使用场景:
① 同时引入zepto和jQuery
② 引入不同版本的jQuery
③ 咱自己写了个库,占用了jQuery这个属性名
2 / 以同时引入Zepto和jQuery为例
<script src="./zepto.min.js">script> <script src="./jquery.min.js">script> <script> (function (){ window.$$ = jQuery.noConflict(); //=> 只释放$的使用权限 })();script>
△ 项目同时引入zepto和jquery
window.Zepto = Zepto window.$ === undefined && (window.$ = Zepto)
△ 从zepto.js中粘贴出来的源码
var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context );};//...CDOEvar _jQuery = window.jQuery, _$ = window.$;jQuery.noConflict = function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery;};// 在浏览器中 noGlobal => undefinedif(typeof noGlobal === 'undefined'){ window.jQuery = window.$ = jQuery;}
△ 从jQuery.js 中粘贴出来的源码,jQuery.noConflict方法释放$的使用权限
0、window.$ = zepto
在jQuery引入之前,已经把zepto赋值给$了
1、在导入JQ的时候,把现有全局的$
是谁记录下来
var _$ = window.$;
即:_$= Zepto
var _jQuery = window.jQuery
这个时候_jQuery的值是undefined
导入jQuery结束以后,window.jQuery = window.$ = jQuery了
2、如果发现$
使用权和别的类库冲突了,则转让使用权
window.$jq = jQuery.noConflict()
在调用此方法之前:_$=Zepto; _jQuery = undefined; window.jQuery = window.$ = jQuery
① window.$ === jQuery
=> true,进入判断体
window.$ = _$;
即:window.$ = Zepto; 把$的使用权限让出去了
② deep && window.jQuery === jQuery
形参deep没有接收到实参值,即:deep 为 undefined,不进入判断体
③ return jQuery;
, 即:window.$$= jQuery
之后使用 $$ 即表示jQuery了
3 / 咱自己写的模块
(function (){ var utils = {}; var _utils = window.utils, _temp = window._; utils.noConflict = function (deep){ if(window._ === utils){ window._ = _temp; } if(deep && window.utils === utils){ window.utils = _utils; } return utils; }; if(typeof module === 'object' && typeof module.exports === 'object'){ // ... CommonJS 规范下的操作 } else if(typeof window !== 'undefined'){ window._ = window.utils = utils; } })();
△ ① 区分web浏览器还是CommonJS规范的node环境 ② 在web浏览器中转让_和utils的使用权限
从"你"到"更好的你",有无限可能~