zoukankan      html  css  js  c++  java
  • JQuery extend()与工具方法、实例方法

    使用jQuery的时候会发现,jQuery中有的函数是这样使用的:

    $.get();
    $.post();
    $.getJSON();

    有些函数是这样使用的:

    $('div').css();
    $('ul').find('li');

    有些函数是这样使用的:

    $('li').each(callback);
    $.each(lis,callback);

    这里涉及到两个概念:工具方法与实例方法。通常我们说的工具方法是指无需实例化就可以调用的函数,如第一段代码;实例方法是必须实例化对象以后才可以调用的函数,如第二段代码。jQuery中很多方法既是实例方法也是工具方法,只是调用方式略有不同,如第三段代码。为了更清晰解释JavaScript中的工具方法与实例方法,进行如下测试。

    functionA(){
            
        }
       A.prototype.fun_p=function(){console.log("prototpye");};
        A.fun_c=function(){console.log("constructor");};
        var a=new A();
        A.fun_p();//A.fun_p is not a function
        A.fun_c();//constructor
        a.fun_p();//prototpye
        a.fun_c();//a.fun_c is not a function

    通过以上测试可以得出结论,在原型中定义的是实例方法,在构造函数中直接添加的是工具方法;实例方法不能由构造函数调用,同理,工具方法也不能由实例调用。

    当然实例方法不仅可以在原型中定义,有以下三种定义方法:

            functionA(){
                   this.fun_f=function(){
                           console.log("Iam in the constructor");
                   };
            }
            A.prototype.fun_p=function(){
                   console.log("Iam in the prototype");
            };
            var a=newA();
            a.fun_f();//Iam in the constructor
            a.fun_i=function(){
                   console.log("Iam in the instance");
            };
            a.fun_i();//Iam in the instance
            a.fun_p();//Iam in the prototype

    这三种方式的优先级为:直接定义在实例上的变量的优先级要高于定义在“this”上的,而定义在“this”上的又高于 prototype定义的变量。即直接定义在实例上的变量会覆盖定义在“this”上和prototype定义的变量,定义在“this”上的会覆盖prototype定义的变量。

    下面看jQuery中extend()方法源码:

    jQuery.extend = jQuery.fn.extend = function() {
            var options,name, src, copy, copyIsArray, clone,
                   target= arguments[0] || {},
                   i =1,
                   length= arguments.length,
                   deep= false;
            // Handle adeep copy situation
            if ( typeoftarget === "boolean" ) {
                   deep= target;
                   //Skip the boolean and the target
                   target= arguments[ i ] || {};
                    i++;
            }
            // Handlecase when target is a string or something (possible in deep copy)
            if ( typeoftarget !== "object" && !jQuery.isFunction(target) ) {
                   target= {};
            }
            // ExtendjQuery itself if only one argument is passed
            if ( i ===length ) {
                   target= this;
                   i--;
            }
            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;
                                   }
                           }
                   }
            }
            // Returnthe modified object
            return target;
    };

    (1)首先,jQuery和其原型中extend()方法的实现使用的同一个函数。

    (2)当extend()中只有一个参数的时候,是为jQuery对象添加插件。在jQuery上扩展的叫做工具方法,在jQuery.fn(jQuery原型)中扩展的是实例方法,即使在jQuery和原型上扩展相同名字的函数也可以,使用jQuery对象会调用工具方法,使用jQuery()会调用实例方法。

    (3)当extend()中有多个参数时,后面的参数都扩展到第一个参数上。

            var a={};
            $.extend(a,{name:"hello"},{age:10});
            console.log(a);//Object{name: "hello", age: 10}

    (4)浅拷贝(默认):    

            var a={};
            varb={name:"hello"};
            $.extend(a,b);
            console.log(a);//Object{name: "hello"}
            a.name="hi";
            console.log(b);//Object{name: "hello"}

    b不受a影响,但是如果b中一个属性为对象:

            var a={};
            varb={name:{age:10}};
            $.extend(a,b);
            console.log(a.name);//Object{age: 10}
            a.name.age=20;
            console.log(b.name);//Object{age: 20}

    由于浅拷贝无法完成,则b.name会受到a的影响,这时我们往往希望深拷贝。
    深拷贝:    

            var a={};
            varb={name:{age:10}};
            $.extend(true,a,b);
            console.log(a.name);//Object{age: 10}
            a.name.age=20;
            console.log(b.name);//Object{age: 10}

    b.name不受a的影响。

            var a={name:{job:"Web Develop"}};
    	var b={name:{age:10}};
    	$.extend(true,a,b);
    	console.log(a.name);//age: 10  job: "Web Develop"
    
           //b.name没有覆盖a.name.job。
  • 相关阅读:
    [HNOI2002]营业额统计
    HDU 1374
    HDU 3345
    HDU 2089
    Graham扫描法
    Codeforces 1144D Deduction Queries 并查集
    Codeforces 916E Jamie and Tree 线段树
    Codeforces 1167F Scalar Queries 树状数组
    Codeforces 1167E Range Deleting
    Codeforces 749E Inversions After Shuffle 树状数组 + 数学期望
  • 原文地址:https://www.cnblogs.com/sxhlf/p/7645193.html
Copyright © 2011-2022 走看看