jquery1.4
这里使用了 jQuery1.4,为什么使用 1.4 因为 1.4 很多特性没有添加分析起来相对容易。
extend 可以说是 jQuery 用的最多的函数之一了,除了核心的几个函数之外其他的几乎全部用 extend 进行原型或者静态函数的扩展。下面来看看 extend 如果完成这样的工作的吧
jQuery.extend = jQuery.fn.extend = function() { // copy reference to target object var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy; // Handle a deep copy situation // 深度拷贝 if ( typeof target === "boolean" ) { deep = target; // 修正深度拷贝 target = arguments[1] || {}; // 修正目标 // skip the boolean and the target // 如果是深度拷贝 修正循环(跳过第一个参数(0)和目标(1)) i = 2; } // Handle case when target is a string or something (possible in deep copy) // 确保目标元素是对象且不是函数,但可以是函数对象(new 函数) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed // 当扩展的对象只有一个的时候,就视为扩展 jQuery if ( length === i ) { target = this; // 修正 this 为jQuery --i; } // 遍历参数 for ( ; i < length; i++ ) { // Only deal with non-null/undefined values // 遍历不是 null 的值(对象) 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 object literal values or arrays // 深拷贝,且 copy 是对象或者数组 /** * deep => true * copy == true * copy => 必须是绝对对象 或 copy 是一个数组 * */ if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) { /** * 如果目标元素和要拷贝的元素有相同的 key 并且也是对象或者数组那么就返回目标对象的 key * 否则创建一个对应的类型用于保存数据 */ var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src : jQuery.isArray(copy) ? [] : {}; // 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; } } } } // Return the modified object return target;};
下面我列出一下 extend 的一些用法
1、这种是最基本的用法
var t = $.extend({a:"123"}, {b:'456'});console.log(t);//Object {a: "123", b: "456"}
2、深度拷贝
var o1 = { txt: "123", a: { 'a_text': 'a_text' }};var o2 = { txt1: '456', b: { 'b_text': '123' }};debugger;var t = $.extend(false,o1,o2);t['b']['b_text'] = '改变成文本';console.log(t);console.log(o1,o2);// -----------------------------深度克隆------------------------------------var o1 = { txt: "123", a: { 'a_text': 'a_text' }};var o2 = { txt1: '456', b: { 'b_text': '123' }};debugger;var t = $.extend(true,o1,o2);t['b']['b_text'] = '改变成文本';console.log(t);console.log(o1,o2);
我们看当深度克隆参数为 false 的时候,扩展出来的对象 key 为 b 的和元素对象 key 为 b 的是指向的同一个引用。所以当我改变了克隆回来的对象 t 值 'b_text' 的时候原始对象也跟着变了。
再来看看深度克隆的情况,当我改变了克隆回来的对象 t 值 'b_text' 的时候原始对象没有跟着变了。
3、接下来看看为 jQuery 扩展插件的情况
jQuery.extend = jQuery.fn.extend = function(){};
他这里为 jQuery 静态函数 和 原型都添加了 extend 函数, 所以我们要编写插件只需要给原型添加一个扩展函数就可以啦。
$.fn.extend({tudou:function(){alert('hello tudou')}});
看一下他这里怎么实现的,其实原理很简单。
// 当扩展的对象只有一个的时候,就视为扩展 jQueryif ( length === i ) { target = this; // 修正 this 为jQuery --i;}
当你只传递一个对象的时候他会把 扩展的目标指向当前 this,所以能很方便的进行插件编写。
好啦结束了。。。