zoukankan      html  css  js  c++  java
  • 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 );

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

  • 相关阅读:
    Dr.Watson
    得到当前操作系统的版本的
    屏蔽回车关闭对话框事件
    一个发邮件的类(用CDO实现)
    怎样配置SQL Server发送电子邮件
    无进程DLL木马的又一开发思路与实现
    Write AutoUpdating Apps with .NET and the Background Intelligent Transfer Service API
    WINDOWS编程入门一个初级问题的分析
    智能客户端技术总结(一)
    【.NET】C#.NET ADO.NET数据访问模型概述
  • 原文地址:https://www.cnblogs.com/xxiaomai/p/3881314.html
Copyright © 2011-2022 走看看