文 / 景朝霞

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的使用权限


从"你"到"更好的你",有无限可能~

jquery拼接 jquery拼接变量_jquery拼接