jQuery源码学习一

学习前端也有一段时间了,闲暇之余决定进一步学习,从jquery源码学习开始。

嗯,打开jquery.js,嗯,太多了,一脸懵!

一步一步来吧!

刚开始看了艾伦 Aaron老师的文章入门引导一下。

首先是看jQuery源码分析系列(01) : 整体架构这篇。

提前声明:后文所展示的jquery版本为3.3.1,后文不再强调,理解不对的地方万望告知

总结一下:

ps:文中写到了jQuery.fn但是并没有写怎么来的,搞得是我一头懵.于是去jquery.js文件中搜索一下,可以看到有这么一段

很明显Jquery.fn就是jQuery.prototype。

一、如何做到既能隔离作用域还能使用jQuery原型对象的作用域呢?

var aQuery = function(selector, context) {
       return  new aQuery.prototype.init(selector);
}
aQuery.prototype = {
    init: function(selector) {
        //此处的this指的时init方法的实例,即new aQuery.prototype.init(selector)
    	this.name = selector;
        return this;
    },
    name: function() {
        return this.age
    },
    age: 20
}

//将aQuery原型对象上的init方法的原型对象设置为aQuery的原型对象。
//这样就init的实例就可以访问到aQuery原型对象上的方法.
aQuery.prototype.init.prototype = aQuery.prototype;

var a = aQuery(1);
var b = aQuery(2);
console.log(a.name,a.age)//1,20
console.log(b.name,b.age)//2,20

二、插件接口,extend方法

推荐这篇文章 分析了一下JQuery中的extend方法实现原理,很详细的介绍了extend的用法.

extend方法中使用了isPlainObject方法。

源码解析如下

/*
	jQuery.fn === jQuery.prototype;
	在jquery对象上和jquery.prototype上增加一个extend方法
	什么是目标对象和源对象?
	将obj2合并到obj1,则obj1是目标对象,obj2是源对象
*/
jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[ 0 ] || {},//目标对象
		i = 1,//记录源对象在实参中的开始位置
		length = arguments.length,//实参长度
		deep = false;//是不是深拷贝

	// 判断是一个参数是true的时候为深拷贝
	if ( typeof target === "boolean" ) {
		//是深拷贝
		deep = target;

		// 修改目标对象为第二个实参.
		target = arguments[ i ] || {};
		//源对象在实参中的开始位置为2
		i++;
	}

	//如果传入的目标对象不是一个对象并且不是函数时,则置为空对象.
	if ( typeof target !== "object" && !isFunction( target ) ) {
		target = {};
	}

	// 当实参只有一个对象的时候,默认把jQuery对象作为目标对象
	if ( i === length ) {
		target = this;
		i--;
	}
	//循环源对象
	for ( ; i < length; i++ ) {

		// 当源对象不为null时
		if ( ( options = arguments[ i ] ) != null ) {

			// 遍历当前源对象
			for ( name in options ) {
				src = target[ name ];//目标对象的该属性
				copy = options[ name ];//源对象的该属性

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// 如果是深拷贝,判断copy是对象还是数组,如果既不是纯粹的对象也不是数组则直接走else if
				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
					( copyIsArray = Array.isArray( copy ) ) ) ) {
                    //如果是一个数组
					if ( copyIsArray ) {
						copyIsArray = false;
                        //复制目标对象的值
						clone = src && Array.isArray( src ) ? src : [];

					} else {
                        //如果是对象
                        //复制目标对象的值
						clone = src && jQuery.isPlainObject( src ) ? src : {};
					}

					// 递归调用extend方法,将源对象合并到clone上并赋值给目标对象.
					target[ name ] = jQuery.extend( deep, clone, copy );

				// 浅拷贝则直接将源对象的属性值赋值给目标对象
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// 返回目标对象.
	return target;
};
//判断指定参数是否是一个纯粹的对象,所谓"纯粹的对象",就是该对象是通过"{}"或"new Object()"创建的。
	isPlainObject: function( obj ) {
		var proto, Ctor;

		// 如果参数为假值,或者{}.toString.call(obj)判断不是对象则返回false
		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
			return false;
		}
		//Object.getPrototypeOf(obj);
		proto = getProto( obj );

		//如果是使用Object.create(null)创建的对象也是纯粹的对象.proto值为null
		if ( !proto ) {
			return true;
		}
        //直接return Object.getPrototypeOf(obj).constructor === Object效果和下面两句是一样的
        // return Object.getPrototypeOf(obj).constructor === Object
        //如果obj的原型对象的引用是Object,则是纯粹的对象,即Object.getPrototypeOf(obj).constructor === Object
		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
	},

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值