jQuery简化版源码浅显解读

1 篇文章 0 订阅
1 篇文章 0 订阅

一、前言

这里主要是为了把学到的原型知识写在这里,所以并不是真正解读jQuery里面的源码,而是把它简化了一下,然后着重讲解里面jQuery的$.fn,$.fn.extend与$.extend。

一、使用立即执行函数定义jQuery

(function(window) {
  var
	version = "3.3.1",
	// 从这里开始定义一个jQuery的变量
	jQuery = function( selector, context ) {
        // jQuery.fn.init其实是一个构造函数
        // 它返回了jQuery的一个实例对象
	    return new jQuery.fn.init( selector, context );
	},
    ...

    window.$ = jQuery;
})(window);

在jQuery源码找到这一段代码,其实它就是使用了立即执行函数,使得对外只暴露$这个变量,防止了造成变量的污染。

然后它使用了jQuery.fn.init这个函数构造了一个jQuery实例对象,那我们接下来看一下这个函数里面是怎么创建对象的。

二、jQuery.fn.init

// 定义jQuery的构造函数
var init = jQuery.fn.init = function (selector) {
	var slice = Array.prototype.slice;
    // 获取到DOM对象
	var dom = slice.call(document.querySelectorAll(selector));
	var i, len = dom ? dom.length : 0;
	for(i = 0; i < len; i++) {
		this[i] = dom[i];
	}
	this.length = len;
	this.selector = selector || '';
};

从上面这部分代码可以看出,jQuery的构造函数是通过querySelectorAll这个函数获取到选中的DOM对象数组(就像我们平常使用$('p'),这样就得到了页面中所有p标签的DOM对象),并且使用length和selector属性分别记下该元素的个数以及它的选择器名。

三、jQuery的原型

我们都知道,js中的原型可以方便我们创建每一个实例后都可以共享同一个方法,这里jQuery也不例外。jQuery也有它的原型。我们来看看jQuery的原型代码实现。

// 定义jQuery的原型
jQuery.fn = jQuery.prototype = {
    // jQuery原型的constructor属性指向jQuery这个构造函数本身
	constructor: jQuery,

   // 定义了jQuery的一些公共方法
	toArray: function() {
		return slice.call( this );
	},
    // 这个就是我们常用的$('p').css('background', 'blue')
    css: function(key, value) {},
    // 这个就是我们常用的$('div').html('我爱js')
    html: function(value) {}
    ...
};

// 还记得上面第二点中说到jQuery构造函数吗
// 那里有一段代码是这样子的
// var init = jQuery.fn.init = function () {...};
// 所以下面这个init其实就是jQuery本身,所以init.prototype的原型指向了jQuery.fn这个对象
init.prototype = jQuery.fn;

我们可以看到,我们平常用到了的css,html等方法,其实就是放置在这个jQuery的原型对象当中。所以我们每次通过$("选择器“”)创建一个实例对象时,它都已经拥有了css,html这些方法。

大家有没想过,为什么不像这样直接把包含了一个公共方法的对象赋值给jQuery的原型呢?

// 为什么不像这样直接把包含了一个公共方法的对象赋值给jQuery的原型呢?
init.prototype = {
	constructor: jQuery,

	toArray: function() {
		return slice.call( this );
	},

    css: function(key, value) {},
    html: function(value) {}
    ...
};

其实这是因为,jQuery源码只会暴露$这个变量出来给我们用,但是我们有可能需要根据实际的开发需求去扩展jQuery的原型,那么这个时候我们只需要使用$.fn.(自己写的扩展方法名)就可以写进去jQuery的原型对象中了。

并且以后构建一个jQuery对象,这个对象都可以使用我们自定义的这个方法。比如:

是不是看起来特别简单呢?

四、$.fn.extend和$.extend

最后,我们来看看$.fn.extend和$.extend这两个扩展插件机制的函数。

看字面的意思,$.fn.extend就是扩展$.fn(即对jQuery的原型进行扩展),而$.extend就是扩展jQuery(extend是扩展的意思嘛~)。(这里我感觉$.fn.extend({ getName: function(){...} })和上面的$.fn.getName = function() {...}是一个意思)

那么我们来看看,$.fn.extend和$.extend的代码实现吧。(这里我只举例传入一个参数的时候的场景,如果传入多个参数的话,那么是进行合并,而不是扩展插件了)

jQuery.extend = jQuery.fn.extend = function() {
		var options, name, src, copy, copyIsArray, clone,
			// 把传进来的第一个参数获取到并赋值给target这个变量
			target = arguments[ 0 ] || {},
			i = 1,
			length = arguments.length,
			deep = false;
		// 省略部分代码
		...
	// 上面定义了i = 1
	// 此时如果参数个数length也是等于1
	// 则使得把this赋值给target
	// 这里的this,如果是$.fn.extend则this是指$.fn(jQuery的原型)
	// 如果是$.extend则this是指$(即jQuery)
	if ( i === length ) {
		target = this;
		i--;
	}

	for ( ; i < length; i++ ) {

		// 由于只传入了一个参数,所以arguments[0]赋值给了options
		if ( ( options = arguments[ i ] ) != null ) {
			for ( name in options ) {
				src = target[ name ];
				// copy就是你自己写的扩展方法
				copy = options[ name ];

				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
					( copyIsArray = Array.isArray( copy ) ) ) ) {
					// 省略部分代码
					...
				} else if ( copy !== undefined ) {
					// 把你自己写的扩展方法赋值给target(即$或者$.fn)
					target[ name ] = copy;
				}
			}
		}
	}
	// 返回$或者$.fn
	return target;
};

这样,我们就可以通过$.extend和$.fn.extend扩展我们的插件了。

比如,我们经常用的$.ajax就是通过$.extend来扩展出来的。

 

五、总结

本次懒得总结,我是看视频之后学到的,顺便看了一下jQuery源码,不过现在很少人用jQuery了,我们公司都已经使用vue开发,而现在,我要继续去开发了,如果各位大神觉得上面有什么错误或者建议,欢迎指出~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值