jquery-extend源码分析

PS:这次分析基于2.0以上版本;

jquery的extend大家都不陌生,也是jquery的重要接口,写过jquery组件的人都用过extend吧!

先说两个$.extend()和$.fn.extend();

当只写一个对象自变量的时候,是Jquery中扩展插件的形式;$.extend() ->$.ajax;

而$.fn.extend是扩展Jquery实例方法; $.fn.extend ->$().方法;

接下来看下extend的源码,首先在jquery中定义了一些变量:

var src, copyIsArray, copy, name, options, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;   //是否是深拷贝

将目标定为第一个参数,正常情况下目标元素是个对象,当然后面jquery会做处理;

if ( typeof target === "boolean" ) { 
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}

在第一个判断中,会判断目标对象是否是布尔值,如果是,说明是深拷贝,将目标元素设为第二个参数;

if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}

这个时候已经确定目标对象是对象了,现在判断目标对象不是对象或者函数的时候,将目标对象转换为对象;

if ( length === i ) {
target = this;
--i;
}

接下来的这个判断是判断是不是插件形式,如果只写一个对象,把这个对象扩展到jquery源码上,只要判断length和i是否相等。如果相等的活,把target设为this,this可能为两种情况,$或者$.prototype.

for ( ; i < length; i++ ) { //多个对象的情况
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];

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

// Recurse if we‘re merging plain objects or arrays
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 : {};
}

// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );

// Don‘t bring in undefined values
} else if ( copy !== undefined ) { 
target[ name ] = copy;
}
}
}
}

这个for循环是处理对个对象的情况,如果有多个对象,多个对象都要扩展到第一个对象上面。for循环中的if如下

if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];

首先判断参数是否有值,然后把各种赋值。接下来如下:

if ( target === copy ) { 
continue;
}

这个if是判断是防止循环引用的,如:

$.extend(x,{name : x}),如果不做上面那个if判断,如果写成这样会造成循环引用。

接下来会开始判断深度拷贝还是浅拷贝

f ( 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 : {};
}

// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );

// Don‘t bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}

首先通过deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) )判断;deep -> 深浅拷贝  copy ->是否是对象或者数组

不满足以上条件就是浅拷贝。

if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];

} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}

这个判断是拷贝数组和json不同情况的不同处理。

如果src只写src={}/ src=[];不写src && jQuery.isPlainObject(src) ? src : {}/src : [];

这样写如果在多个对象继承的时候,如果对象a和对象b有相同名字的属性,就会把a原有的属性给覆盖,通过jquery的处理,就不会覆盖以前的属性。

target[ name ] = jQuery.extend( deep, clone, copy );

在深拷贝中其实就是利用递归,针对不同情况,分别处理。

jquery-extend源码分析

时间: 2024-11-05 18:29:22

jquery-extend源码分析的相关文章

jQuery.extend() 源码分析

jQuery.extend() 方法 可以合并对象 深拷贝与浅拷贝 源码分析: 概述:  1. 首先定义变量 options:保存每次循环遍历的arguments[i] , name: 保存循环遍历对象的key值 src:保存目标对象target的属性 copy: 保存合并对象的属性 copyIsArray: 如果copy是数组,用copyIsArray保存 clone:如果目标对象是数组,用clone保存. target:目标对象 deep: boolean值,判断是否是深拷贝 2. 然后判断

jQuery.attributes源码分析(attr/prop/val/class)

回顾 有了之前的几篇对于jQuery.attributes相关的研究,是时候分析jQuery.attr的源码了 Javascript中的attribute和property分析 attribute和property兼容性分析 jQuery.access源码分析 结构 jQuery.fn.extend({ attr: function (name, value) { }, removeAttr: function (name) { }, prop: function (name, value) {

jQuery.access源码分析

基本理解 jQuery.attr是jQuery.attr,jQuery.prop,jQuery.css提供底层支持,jQuery里一个比较有特色的地方就是函数的重载, 比如attr,有如下几种重载 $('#box').attr('title') $('#box').attr('title','标题') $('#box').attr({title:'标题',data-menu-toggle:'dropdown'}) $('#box').attr('title',function () {....}

jQuery选择器源码分析和easyui核心分析

写在选择器源码分析之前 这里指对1.7.2版本的源码分析,更高版本添加了更多代码. 整个jQuery的代码是写在一个(function(window, undefined){})(window);这样一个闭包里.请思考,为什么要这样做? 将其写在一个闭包函数里,并传入window直接运行的好处有三: 1,统一命名空间,防止变量的污染:  2,将window作为参数传入函数,在函数里调用window的时候,就不用再去找外层的对象,可以提高效率 : 3,undefined并不是javascript的

jQuery.buildFragment源码分析以及在构造jQuery对象的作用

这个方法在jQuery源码中比较靠后的位置出现,主要用于两处.1是构造jQuery对象的时候使用 2.是为DOM操作提供底层支持,这也就是为什么先学习它的原因.之前的随笔已经分析过jQuery的构造函数了,也提到了有12个分支,其中有一个分支就是通过jQuery.buildFragment方法来处理的,什么情况呢?就是在处理复杂html标签的时候,例如$('<div>123</div>')这样的形式,在构造函数内部通过ret变量判断是不是简单标签,如果是就调用js的createEl

jQuery.queue源码分析

作者:禅楼望月(http://www.cnblogs.com/yaoyinglong ) 队列是一种特殊的线性表,它的特殊之处在于他只允许在头部进行删除,在尾部进行插入.常用来表示先进先出的操作(FIFO)--先进队列的元素先出队.搜索整个jQuery库会发现,queue在jQuery内部仅供给animate动画来使用.它提供了对外的接口,因此程序员也可以使用队列来完成一些特殊需求. queue模块对外开放的API:工具方法:queue,dequeue,_queueHooks(仅内部使用)实例方

jQuery.extend源码深层分析

在网站的开发中,经常会自己写一些jQuery插件来方便使用,其中自然少不了一个关键的方法->jQuery.extend(),使用这个方法来扩展jQuery对象. 那么今天就来讲讲这个函数的实现原理. 这个方法不仅仅可以实现插件,当然也有它本来的功能,扩展对象.like this: var person = {name:'李四'}; var person2 = $.extend(person,{age:20},{sex:'male'}); //person.name='李四'; //person.

jQuery.Deferred 源码分析

作者:禅楼望月(http://www.cnblogs.com/yaoyinglong ) 1 引子 观察者模式是我们日常开发中经常用的模式.这个模式由两个主要部分组成:发布者和观察者.通过观察者模式,实现发布者和观察者的解耦. 发布者主要负责发布内容,观察者主要负责监听发布者发布的内容,并作出相应的动作.和我们平时订阅期刊一样,cnki会维护一个订阅者列表,有期刊被发布出来时,cnki会将这些期刊推送给订阅者.从程序角度来说,订阅者就是一堆的方法,发布者的推送内容的动作就是依次调用订阅者列表中的

jquery extend源码解析

$.extend(obj1,0bj2,{"name":"s","age":22}) //target 要拷贝到哪个对象上 // i 要执行拷贝的次数 // length 要拷贝的参数的长度 // name 对象参数中属性值 // options 对象参数 // clone 深度拷贝时重名对象属性的拷贝 // target 要拓展的对象 jQuery.extend = jQuery.fn.extend = function() { var src,

jQuery.extend()源码解读

// extend方法为jQuery对象和init对象的prototype扩展方法// 同时具有独立的扩展普通对象的功能jQuery.extend = jQuery.fn.extend = function() { /* *target被扩展的对象 *length参数的数量 *deep是否深度操作 */ var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = ar