今天我们来分析一下jquery的源码,从关于初始化jquery这个函数开始。版本:3.4.1
代码是从一个匿名执行函数开始的,我们直接找到jQuery函数,因为我们使用jq的时候都是$("#id")这样开头,在jquery里,$=jQuery。
所以我们直接先找jQuery这个函数。
在代码的148行,这个jQuery其实是个变量,然后赋值了一个函数,这个函数就是我们jQuery的入口点,我们定位到这个init函数这里来看看代码,由于代码太多,我把代码化简来讲解。
1
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context );
}
2 //jQuery.fn赋值原型链
jQuery.fn = jQuery.prototype = {
jquery: version
}
3
init = jQuery.fn.init = function( selector, context, root ){
//init函数的具体操作
}
init.prototype = jQuery.fn;//将init原型链赋值jQuery.fn,jQuery.fn已经赋值了jQuery的原型链
第一行定义一个jQuery变量来接受jQuery.fn.init函数的实例化。
第二行定义jQuery.fn来接收jQuery的原型,并写入了一些变量和函数。
第三行定义init这个变量等于jQuery.fn.init在赋值一个init操作的函数。
所以当第一行new jQuery.fn.init就得到其实jQuery本身,其实就等于:jQuery = new jQuery(selector, context)。
之所以要这样做,就是为了得到jQuery的原型链,因为原型链上有我们大多数的jQuery函数,比如addClass(),html(),等等,几乎jQuery所有的函数都是在原型链上的。
还有一个原因就是为了用共同的this对象,jQuery会把我们每次需要操作dom元素存在this对象里。 我们回到jQuery调用形式的时候,大家一般都是用$调用的,这个操作符又在哪里呢?
在源码的结尾处,源码开始的定义了一个jQuery变量来接收了jQuery自身实例的对象。
所以我们直接使用window.jQuery=jQuery,一个全局的jQuery对象来可以访问了,如果使用$符号形式访问,就在=window.$,就可以了。
这些window.$或者window.jQuery 都是由用户自己设置,你可以改成其他变量名也可以。
其实我认为jQuery在代码入口使用了太多原型链的赋值,我这里修改了一些代码,让代码只执行了一个原型链赋值。
我将jQuery改为了SmhJquery,入口代码如下:
也是执行了一次原型链的赋值,也是同样的调用的init这个函数,但是这里却没有返回任何东西,请看下图。
返回实例对象在这里进行了,我定义了一个函数名为$,里面就是返回SmhJquery的实例,然后再赋值,这样就跟jQuery一样的效果,我是多定义了一个函数来返回,jQuery是用原型链的赋值来进行返回,其实都可以,我只是为了让大家了解。
但是为什么我还要去执行init这个函数,其实我是可以不执行的,也能得到原型链,但是init函数里是把我们要操作的dom对象存入this,所以不得不执行。
jQuery是把得到原型链和存入需要操作的dom都在一个函数里完成,我则是分开完成的。
完整代码:(SmhJquery)
(function (window) {
var SmhJquery = function (selector) {
SmhJquery.fn.init(selector);
};
SmhJquery.fn = SmhJquery.prototype = {
smhjquery: "3.4.1",
init: function (selector) {
if (selector === "undefined") {
this.length = 0; return this;
}
if (selector.nodeType == 1) {
this[0] = selector;
} else {
this[0] = document.getElementById(selector);
}
this.length = 1;
},
css: function (selector) {
console.log(this[0]);
}
};
SmhJquery.fn.extend = function (obj) {
for (var i in obj) {
this[i] = obj[i];
}
};
SmhJquery.fn.extend({
smh: function () {
console.log("smh");
},
addclass: function (value) {
var elem, i = 0;
while ((elem = this[i++])) {
elem.setAttribute( "class",value);
}
return this;
}
});
SmhJquery.fn.extend({
smh1: function () {
console.log(this);
}
});
function $(option) {
return new SmhJquery(option);
}
window.SmhJquery = window.$ = $;
}(window))
$("d").addclass("su").smh1();//函数调用