jQuery源码分析随笔
一次在写jquery插件的经历,让自己发现了js水很深,自己很菜。然后慢慢发现js包括了原型、闭包、作用域等一些很常用的知识点。
首先jquery源码的主要结构
下面就是在做分析jquery源码时自己的一些备注
1 (function(window){ 2 var jQuery = function(select){ 3 //privatefunc(); 4 return new jQuery.fn.init(select); 5 //这边必须new一个对象(这时this指向init对象),不然return jQuery.fn.init(select);中this指向jQuery.fn,而jQuery.fn其实是个定义了很多方法的集合 6 } 7 8 jQuery.test = function(){//静态方法 9 console.log('call test method'); 10 } 11 12 var privatefunc = function (){//内部方法,不能再 外面调用,需要让外部调用及jquery的做法:window.privatefunc = privatefunc;这也是闭包 13 console.log(this) 14 console.log('call privatefunc method'); 15 } 16 17 jQuery.fn = jQuery.prototype = { 18 init:function(select){ 19 console.log(this) 20 var _this = this; 21 if(!select){ 22 return this; 23 } 24 _this.ele = document.documentElement.querySelectorAll(select); 25 _this.length = _this.ele.length; 26 return _this; 27 }, 28 show: function(){ 29 if(this.length===0){ 30 return; 31 } 32 for(var i=0;i<this.length;i++){ 33 this.ele[i].style.display = 'block'; 34 } 35 console.log('call show method') 36 return this; 37 }, 38 hide: function(){ 39 if(this.length===0){ 40 return; 41 } 42 for(var i=0;i<this.length;i++){ 43 this.ele[i].style.display = 'none'; 44 } 45 console.log('call hide method') 46 return this; 47 }, 48 click: function(){ 49 console.log('call click method') 50 return this; 51 }, 52 each: function(fn){ 53 for(var i=0;i<this.length;i++){ 54 fn.call(this.ele[i], i, this.ele[i]) 55 } 56 }, 57 morefunc: function(){ 58 59 } 60 61 } 62 63 jQuery.fn.init.prototype = jQuery.fn; 64 65 window.jQuery = jQuery; //将jQuery赋值给window.jQuery,全局变量。这样外部就可以直接访问jQuery函数了 66 67 })(window,undefined)
下面我从自己一开始比较疑惑的几个点进行分析
1、jQuery 到底是什么?
通常$('div')返回的是new jQuery.fn.init( selector, context )这个对象,也就是init这个函数对象,这里面会查询div标签的dom对象数组、length还有jquery的实例方法。
2、jQuery.fn和jQuery的区别?
jQuery.fn是个方法的集合,通过jQuery.fn.init.prototype = jQuery.fn,这样jQuery.fn.init就包含了jQuery的所有实例方法,jQuery.fn也就是jQuery的所有实例方法。
jQuery.fn.init.prototype==jQuery.prototype==jQuery.fn
3、jQuery为什么要调用jQuery.fn.init来实例化?
jQuery的初始化可以$('div')、new $('div')。为了能通过$('div')方便的进行初始化,就需要在构造方法中返回new jQuery.fn.init(select)来巧妙的实现他。
jQuery.fn.init刚好具备了jquery的所有的实例方法。
比如在jQuery构造方法中直接return this或者new jQuery(),很明显这是没办法实现的。
4、存在的疑问
jQuery.fn这个变量总是让人很绕。如果直接换成jQueryFn不知道可不可以,也许是为了写插件时把jQuery.prototype提供出去吧。
jQuery.fn.plugin = plugin;
5、总结
首先创建一个闭包,在里面申请一个变量jQuery,然后挂载window下,让闭包外的作用域也能进行访问;
其次创建一个jquery别名的jquery.fn=jquery.prototype,并将jquery.fn.init.prototype = jquery.fn;
最后$('.div')的方法返回new jquery.fn.init()的实例。这样这个实例也拥有了jquery.fn的方法。
1 (function(window, undefined){ 2 var jquery = function(selected, content){ 3 return jquery.fn.init(); 4 } 5 //方便后续我们初始化jquery对象时$('div')而不用new jQuery('div')来初始化 6 jquery.fn.init.prototype = jquery.fn; 7 8 })(window)