jQuery源码初探(1)
来源:互联网 发布:c语言大括号的用法 编辑:程序博客网 时间:2024/06/05 20:31
前言
本人也是刚入坑的一枚小白,到现在差不多快一年了啊…
对于前端的同志来说,jQuery应该是再熟悉不过了吧,因为就目前来看,80%左右的网站或多或少的都直接或间接引用jQuery,可以毫不客气地说它目前来说最流行的,面向对象的JavaScript框架,因为平时使用频率很高,所以也就萌生了阅读源码的想法,并结合自己的目前知识,照着源码一点点的分析吧…
(ps:本人前端小白,也是最近才开始阅读源码,边读边写,所以如果有分析不对或者分析不当的地方,还请谅解,也会很乐意接收大家的批评和指正..)
下面进入正题吧
注
1. 本文分析jQuery版本为3.0.0版本,在官网上下载对应未压缩版即可(jQuery官网)
2. 转载请注明出处
ok;打开jQuery-3.0.0的源码我们发现,一开始就是这么一段代码
( function( global, factory ) { "use strict"; if ( typeof module === "object" && typeof module.exports === "object" ) { module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); }; } else { factory( global ); }}( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { /******此处省略若干行*******/}));
一开始看的时候,可能会找不到 function( window , noGlobal){} 这个函数的结束部分,其实,这个函数是jQuery的主体,贯穿整个jQuery的框架,我们所使用的所有的jQuery方法都是写在这个部分。
我们先抛开里面的代码不看,只看外部的框架,我们可以将其简化为
( function( global, factory ) { /******此处省略若干行*******/}( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { /******此处省略若干行*******/}));
这种写法叫做IIFE (immediately-invoked function expression),也叫‘’立即执行函数‘’,‘’即时执行方法‘’等,意思就是函数会在创建完成的时候自动执行一次,一般来说写法有主要有两种写法:
- 第一种:就如同jQuery写法一样
( function( a , b , c ){ /***执行的代码***/ }( 参数1 , 参数2 , 参数3 ) );
- 第二种
( function( a , b , c ){ /***执行的代码***/ })( 参数1 , 参数2 , 参数3 );
这两种写法 参数1,参数2,参数3分别对应的匿名函数的 a , b , c;
ok,问题来了,为什么jQuery要采用IIFE?那么使用IIFE有什么好处?
因为在ES6以前,JS是没有块级作用域的概念,只有函数作用域,作为一种对块级作用域的模拟就只能用function模拟,就是为了使模块相互独立,降低模块间的耦合性,避免全局作用域的污染和全局变量的冲突。
举个例子
/**用IIFE创建一个闭包**/ var foo = (function(){ var txt = "hello"; return { get: function(){ return txt }, set: function( val ){ txt = val } } })(); console.log( foo.get() ); // 'hello' foo.set( 'world' ); console.log( foo.get() ); // 'world' foo.txt; //'undefinded' console.log( txt ) // 'ReferenceError : txt is not defined'
可以看出,我们就是可以通过 导出方法 从函数外部的外部去更改 改变函数内部变量的值,所以就可以利用这个特点来隔离作用域,模拟一种“私有”的效果,jQuery正是利用这一点,在我们调用jQuery代码时,保护jQuery内部变量。(ps:如果有不熟悉的同学,可以去看看作用域链和闭包的相关知识哈~)
好的,我们回到上面jQuery的部分,
( function( global, factory ) { /******此处省略若干行*******/}( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { /******此处省略若干行*******/}));
在函数 参数 global 中 , jQuery采用了 一个三元运算符去赋值
typeof window !== "undefined" ? window : this
首先用 typeof 来判断 当前的 window 存不存在 , 如果存在 , 就将 window对象传入 , 否在就传入this对象。jQuery之所以这么写,是因为 global 如果是在浏览器环境就是 window , 如果不是在浏览器环境则是其他的全局对象,这样 传递this可以保存当前的上下文环境;
接下来理一理这一部分代码。
我直接截取了源码的一段
首先我们 看这个判断 :
if ( typeof module === "object" && typeof module.exports === "object" )
结合注释,我们 能大概看懂, 这一段判断是 为了 兼容 commonjs 或者 类似 commonjs 规范的一些框架;
了解过node.js的同学应该能看出来 module.exports 是 node.js 中用来创建模块的方法,那么可以理解为如果这个条件成立,那么 首先判断当前的环境是否支持 global.document 属性 , 也就是window.document 属性 , 如果支持 , 我们调用
`factory( global, true ) { /* jQuery code * / }`
将 jQuery 的方法绑定到当前模块上,
如果 window.document 不存在呢? 直接调下面的方法
function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); };
该方法抛出一个异常 , 告诉用户 jQuery 需要 window.document 环境 , 并依旧返回 factory( w ) 方法(ps:其实 我也不知道 为什么 不支持 ,还要返回 factory( w ) 方法 , 0.0 );
如果
if ( typeof module === "object" && typeof module.exports === "object" )
这个条件不成立,也就是我们 一般 遇到的情况,(一般情况下,typeof module 都是 ‘undefined’),
这样就好办了,直接调用 factory( global ) 将 jQuery 方法引入到我们当前的执行环境中…
不知不觉也码了不少字了,开篇部分就先到这里吧,后面我继续学习,在继续更新吧~ :)
- jQuery源码初探(1)
- jQuery源码初探(2)
- jQuery源码初探(3)
- jQuery源码初探(4)
- PostgreSql初探(1)-源码安装
- Spark Streaming源码初探 (1)
- minidlna源码初探(一)
- jquery初探
- jQuery初探
- jquery初探
- JQuery 初探
- 初探JQuery
- JQuery初探
- jQuery源码解析(1)
- JQuery初探---Jquery/Ajax
- spark 1.3.1 master 源码初探01
- [java学习]java容器源码初探(1)
- googletest初探(一) 源码中的例子
- 设计模式之模板模式
- Tomcat性能调优, 启动出现警告问题 [minSpareThreads did not find a matching property.]
- 第十六章 什么是例行性工作排程(定时任务)
- 数组素数排序(作业)
- Java时间转换格式大全
- jQuery源码初探(1)
- 第十六章 仅运行一次的工作排程(at)
- svn图标会存在延迟怎么办?还有不出现图标怎么办?
- Caffe GNU error
- 日志分片工具cronolog
- 第十六章 循环运行的例行性工作排程
- 用Python做测试——利用模块进行集中管理
- spring cloud网关zuul源码之Filter管理
- 第十六章 可唤醒停机期间的工作任务(anacron)