zoukankan      html  css  js  c++  java
  • jQuery中,$.extend,$obj.extend和$.fn.extend三者的区别

    现在做的一个项目,所使用的框架是基于jQuery扩展的,于是平时学了一下jQuery,了解到了它的扩展函数:extend

    关于这个函数,这篇文章已经做了很好的介绍,这里只是补充一下我的疑问和见解。

    当我读了上面链接的这篇文章后,产生了个疑问:$.extend和$.fn.extend到底区别在哪呢?API说前者是将扩展成员合并到全局对象中去,后者是将扩展成员合并到实例对象中去。我看不明白这两句话,于是亲自试了一下,结果发现,两个函数的作用貌似是一样的,都是将后面几个参数所指定的扩展成员合并到第一个参数对象中。

    接着我又看了下这个函数的源码,代码并不多。首先第一句声明就让我觉得这两个函数其实是一样的了:

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

    没错。这两个函数确实是同一个。如果在里面打上断点,那么无论通过哪种方式调用都会在断点处中断。

    不过上面的引文还提到了一点:如果只传了一个参数,也就是target参数(如果第一个参数是boolean类型那么target参数是第二个),那么“target参数”就会成为“扩展成员”(option),被扩展的对象则是调用extend函数的对象。因此,通过这两种方式调用,函数体里面的this所指向的对象不同,因此实现的功能就不一样了。

    接着看一下调用extend函数的三种方式(这里都特指只传一个参数,或者第一个参数是boolean的前提下只传两个参数的情形,因为传更多的参数的话,这些调用方式的作用貌似是一样的):

    $.extend

    $("#id").extend

    $.fn.extend

    下面针对以上三个调用者,对jQuery的代码结构简化一下。

     1 (function( window, undefined ) {
     2     var jQuery = function( selector, context ) {
     3         // The jQuery object is actually just the init constructor 'enhanced'
     4         return new jQuery.fn.init( selector, context, rootjQuery );
     5     },
     6     jQuery.fn = jQuery.prototype = {
     7         // ...
     8         init: function(...) {},
     9         // ...
    10     };
    11     jQuery.fn.init.prototype = jQuery.fn;
    12     jQuery.extend = jQuery.fn.extend = function() {};
    13     window.jQuery = window.$ = jQuery;
    14 }(window);

    可以按照这个思路理解上面贴出的代码。当jQuery文件被加载完成后,闭包立刻执行,并且传入了window全局变量。然后在13行定义了window.jQuery和window.$,因此你可以在你代码的任何地方使用jQuery函数或者$函数,它俩是一样的东西。接着看它们共同指向的对象,是一个函数,调用这个函数会返回一个jQuery.fn.init类型的对象,换句话说。你调用$(...)或者jQuery(...)所得到的任何东西,都是jQuery.fn.init这个函数new出来的对象。然而,若用instanceOf来测试这些对象的类型,发现他们是jQuery类的对象。这是因为在11行,init的原型指向了jQuery.fn,而且在第6行,fn指向了jQuery.prototype。对于表达式a instanceOf b,只要在a的原型链中能够找到b,就会返回true。当然,通过a也可以调用b的所有成员和方法。

    到此,应该很容易理解下面贴出的测试代码和测试结果:

     1 $(function(){
     2                 var $p = $("#panel");
     3                 var $p2 = $("#panel2");
     4                 $p.extend({key1: "value1"});
     5                 $p2.extend({key2: "value2"});
     6                 $.extend({key3: "value3"});
     7                 $.fn.extend({key4: "value4"});
     8                 // 通过$px.extend只影响$px自身
     9                 console.log($p.key1); // value1
    10                 console.log($p2.key1); // undefined
    11                 console.log($p.key2); // undefined
    12                 console.log($p2.key2); // value2
    13                 console.log($.key1); // undefined
    14                 console.log($.key2); // undefined
    15                 // 通过$.extend只影响$自身
    16                 console.log($.key3); // value3
    17                 console.log($p.key3); // undefined
    18                 console.log($p2.key3); // undefined
    19                 // 通过$.fn.extend影响所有$px和$.prototype
    20                 console.log($p.key4); // value4
    21                 console.log($p2.key4); // value4
    22                 console.log($.prototype.key4); // value4
    23                 console.log($.key4); // undefined
    24             });

    最后总结一下结论:

    1。如果传入了两个以上,或者第一个参数是boolean类型,传入了三个以上参数时,三种调用方式的效果是一样的。

    2。否则,$.extend只是扩展了$这个函数自身;

    $("#id").extend只扩展了$("#id")这个jQuery对象自身;

    $.fn.extend扩展了jQuery对象的原型,可以通过所有的jQuery对象调用扩展成员,但不能通过$调用。

  • 相关阅读:
    LeetCode "Palindrome Partition II"
    LeetCode "Longest Substring Without Repeating Characters"
    LeetCode "Wildcard Matching"
    LeetCode "Best Time to Buy and Sell Stock II"
    LeetCodeEPI "Best Time to Buy and Sell Stock"
    LeetCode "Substring with Concatenation of All Words"
    LeetCode "Word Break II"
    LeetCode "Word Break"
    Some thoughts..
    LeetCode "Longest Valid Parentheses"
  • 原文地址:https://www.cnblogs.com/var-iable/p/3308437.html
Copyright © 2011-2022 走看看