【jquery源码三】jQuery是如何创建方法和扩展方法

【jquery源码】目录表。

前言:jQuery下的方法有很多,而且都很实用。比如each方法,我们可以$.each()这样去使用,也可以$('div').each()这样去使用,两者有什么区别呢?

var jQuery = function( selector, context ) {
	return new jQuery.fn.init( selector, context, rootjQuery );
}
jQuery.each = function(){}

前者是jQuery下的方法,可以直接使用,我们习惯性称为工具方法;

--------

jQuery.fn = jQuery.prototype = {
	constructor: jQuery,
	init: function(){}	
}
jQuery.fn.each = function(){
	
}

后者是jQuery原型下的方法,需要实例jQuery对象后使用,我们习惯性称为jQuert实例对象方法。


一、模拟jQuery创建方法、扩展方法。

(function(window,undefined){  
	var jQ = function(selector){  
		return new jQ.fn.init(selector);  
	};  
	jQ.fn = jQ.prototype = {  
		jquery:'2.0.3',     //jquery版本号信息
		constructor: jQ,    //添加构造器属性
		length:0,			//初始length属性
		selector:'',		//初始selector属性
		init: function(selector){   
			//初始化jQuery对象
		},
		toArray: function(){},
		get: function(){},
		pushStack: function(){},
		each: function(){},
		ready: function(){},
		slice: function(){},
		first: function(){},
		last: function(){},
		eq: function(){},
		map: function(){},
		end: function(){},
		push: function(){},
		sort: function(){},
		splice: function(){} 
	}; 
	jQ.fn.init.prototype = jQ.fn;  
	
	jQ.extend = jQ.fn.extend = function(){
			
	}
	jQ.extend({
		each: function(){},
		type: function(){},
		parseJSON: function(){}
		/*.............*/	
	});
	jQ.fn.extend({
		
		attr: function(){},
		removeAttr: function(){},
		addClass: function(){},
		removeClass: function(){},
		toggleClass: function(){},
		val: function(){},
		css: function(){},
		on: function(){}
		/*.............*/
	});
	  
	window.$$ = jQ;    	
})( window ); 

①、像jQ原型下有一些比较重要的方法,而且不会经常需要修改、优化,或者删除的方法。

②、而如果要继续添加、扩展方法。都是通过extend()去扩展方法。

jQ.extend = jQ.fn.extend = function(){
			
}

③、扩展工具方法

jQ.extend({
    each: function(){},
    type: function(){},
    parseJSON: function(){}
    /*.............*/	
});

④、扩展jQuery对象方法

jQ.fn.extend({
    attr: function(){},
    removeAttr: function(){},
    addClass: function(){},
    removeClass: function(){},
    toggleClass: function(){},
    val: function(){},
    css: function(){},
    on: function(){}
    /*.............*/
});

这样使得代码的更好维护,如果要添加方法只需要在extend中去操作,而不需要在核心代码中去操作。


二、extend扩展方法源码

在研究extend源码之前,来看看extend几种用法。

1、简单的说extend有四种用法:

①、扩展jquery工具方法

②、扩展jQuery实例对象方法

③、浅拷贝

④、深拷贝

2、进行细分的话,extend有以下几种情况

var obj1 = { name:'freddy', hobit:["basketball"], sex:null };
var obj2 = { age:18 };
var obj3 = {};
var obj4 = {};
var obj5 = {};

$.extend({});				//①扩jQuery展工具方法
$.fn.extend({});			//②扩展jQuery实例对象方法
$.extend(obj3,obj1);   			//③浅拷贝
$.extend(obj3,obj1,obj2);  		//③浅拷贝多个对象
$.extend(true,obj4,obj1);               //④深拷贝
$.extend(true,obj4,obj1,obj2);          //④深拷贝多个对象
$.extend(obj5,{name:'nick'},{age:18});  //⑤扩展对象	
console.log(obj3);
console.log(obj4);
console.log(obj5);

对于浅拷贝、深拷贝不熟悉的可以看看我以前的文章【JavaScript】对象引用、浅拷贝、深拷贝详解

3、直接上extend源码(这里的目标对象为“被扩展的对象”或者“拷贝别人”的对象)

jQuery.extend = jQuery.fn.extend = function() {
    var options, name, src, copy, copyIsArray, clone,
	target = arguments[0] || {},   //设置第一个参数为目标对象  
	i = 1,     //i为1是浅拷贝情况下,被拷贝的对象是arguments[1],从二个参数开始
	length = arguments.length,
	deep = false;     //默认是浅拷贝

    //$(true,arr4,arr1) || $(true,arr4,arr1,arr2); 
    if ( typeof target === "boolean" ) {    //深拷贝情况第一个参数为true,布尔类型
	deep = target;    
	target = arguments[1] || {};    //目标对象变成第二个参数了
	i = 2;   //被拷贝对象是arguments[2],从第三个参数开始
    }

    //看目标对象是否是对象
    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {   
	target = {};
    }

    //$.extend({}) || $.fn.extend({})  扩展方法
    if ( length === i ) {    //只有一个参数的情况
	target = this;    //目标对象变成了$ 或者 $.fn
	--i;              //i变成0
    }

    for ( ; i < length; i++ ) {  //for循环用于解决->拷贝多个对象的情况
	
	if ( (options = arguments[ i ]) != null ) {  //如果该参数对象不为undefined或null
			
	    for ( name in options ) {
		src = target[ name ];       //保存目标对象属性
		copy = options[ name ];	    //保存该属性的值

		//如果出现$.extend(obj1,{ name:obj1 }); 跳过本次循环
		if ( target === copy ) {  
			continue;    
		}

		//如果该属性下的值是"对象自变量"或者"数组",就进行深拷贝
		if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {  //深拷贝
		    if ( copyIsArray ) {  //如果该属性下的值是"数组"
			copyIsArray = false;
			clone = src && jQuery.isArray(src) ? src : [];    

		    } else { //如果该属性下的值是"对象自变量"
			clone = src && jQuery.isPlainObject(src) ? src : {};
		    }

		    target[ name ] = jQuery.extend( deep, clone, copy );  //然后进行递归操作

		} else if ( copy !== undefined ) {    //浅拷贝
		    target[ name ] = copy;
		}
	}
    }
}
	return target;
};
注释写上去之后,一些都明了了,也并没有什么难点。如果有不明白的地方可以下方留言。


三、扩展方法

<body>
<script src="https://cdn.bootcss.com/jquery/2.0.3/jquery.js"></script>
<script>
$.extend({
	freddy: function(){
		console.log('扩展jQuery工具方法');	
	}	
});
$.fn.extend({
	freddy: function(){
		console.log('扩展jQuery实例对象方法');
	}	
});
$.freddy();
$(document).freddy();
</script>
</body>

运行结果

这样是不是很方面,就算不熟悉jquery源码,也能很快扩展出自己想要的方法。不过这里要注意的是,如果扩展的方法名如果跟jQuery原生的方法名重名(如css,attr),会发生我们扩展的方法覆盖了原生的jQuery方法。  


【jquery源码】目录表。

猜你喜欢

转载自blog.csdn.net/w390058785/article/details/80857794