zoukankan      html  css  js  c++  java
  • Java程序猿的JavaScript学习笔记(9—— jQuery工具方法)

    计划按例如以下顺序完毕这篇笔记:
     

    1. Java程序猿的JavaScript学习笔记(1——理念)
    2. Java程序猿的JavaScript学习笔记(2——属性复制和继承)
    3. Java程序猿的JavaScript学习笔记(3——this/call/apply)
    4. Java程序猿的JavaScript学习笔记(4——this/闭包/getter/setter)
    5. Java程序猿的JavaScript学习笔记(5——prototype)
    6. Java程序猿的JavaScript学习笔记(6——面向对象模拟)
    7. Java程序猿的JavaScript学习笔记(7——jQuery基本机制)
    8. Java程序猿的JavaScript学习笔记(8——jQuery选择器)
    9. Java程序猿的JavaScript学习笔记(9——jQuery工具方法)
    10. Java程序猿的JavaScript学习笔记(10——jQuery-在“类”层面扩展)
    11. Java程序猿的JavaScript学习笔记(11——jQuery-在“对象”层面扩展)
    12. Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)
    13. Java程序猿的JavaScript学习笔记(13——jQuery UI)
    14. Java程序猿的JavaScript学习笔记(14——扩展jQuery UI)

    这是笔记的第9篇,从jQuery源代码的角度,聊聊jQuery的工具方法。


    作者博客:http://blog.csdn.net/stationxp

    作者微博:http://weibo.com/liuhailong2008

    转载请取得作者允许


    1、先看几个工具方法怎样使用:

    var t = $.trim('   >>_<<   ');
    var ps = $.param({x:15,y:16});
    jQuery.type(function(){}) === "function"

    jQuery的工具方法,相对jQuery本身。是相对独立的。

    2、这些方法是怎样定义的呢?
    我们推測一下,试试看。


    我们知道jQuery(即$)是全局变量,这些方法应该是jQuery变量的属性。
    我们能够通过例如以下语法加入:

    jQuery.xx = function(a,b){
    	 return a + b;
    }
    // try
    var r1 = jQuery.xx(2,3);
    console.log(r1);// output : 5
    var r2 = $.xx(3,3);
    console.log(r2);// output : 6
    上面代码,说明$和jQuery引用了同样变量。他们是一样一样的。


    这些代码达到了定义工具方法的目的,但jQuery是这样做的吗?

    3、
    查看jQuery源码,jQuery通过例如以下语法定义工具方法:

    jQuery.extend({
    	 noConflict: function( deep ) {
    	  if ( window.$ === jQuery ) {
    			window.$ = _$;
    	  }
    	  if ( deep && window.jQuery === jQuery ) {
    			window.jQuery = _jQuery;
    	  }
    	  return jQuery;
    	 }
    	 //, ...
     });

    extend方法定义例如以下:

    //定义了一个方法,赋值给jQuery.fn.extend和jQuery.extend.
    //jQuery.fn.extend和jQuery.extend尽管定义同样,但调用者不同,从而方法中this指向不同,从而实现的功能不同。

    //没有显式声明參数。而是通过arguments动态获得,从而支持更丰富的功能。

    jQuery.extend = jQuery.fn.extend = function() { var src, copyIsArray, copy, name, options, clone, // 将第一个參数作为目标对象 target = arguments[0] || {}, // i初始化为1。临时还不知道做什么用 i = 1, // length表示參数的个数 length = arguments.length, // deep 应该表示是否深层拷贝,默觉得否。 deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { //假设第一个參数是布尔类型。则第二个參数为目标对象 //形如:jQuery.extend(false,UiObject,...); deep = target; target = arguments[1] || {}; // i 是当前參数的数组下标,从0開始 i = 2; } //目标对象是能是函数或者对象。传入其它參数,target默觉得空对象。 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // 眼下,假设第一个參数不是布尔,i值为1。length也为1,即extend(obj)的情况 // 假设是布尔。i值为2,length也为2,即extend(true,obj)的情况 // 总之。没有传入 src if ( length === i ) { // jQuery 把传入參数收了 // 參数下标又一次指向传入的这个參数,即此时指向了src target = this; --i; } // 如今i指向了target后面某个參数,应该是src // 把后面传入的每一个參数都当src for ( ;i < length; i++ ) { // Only deal with non-null/undefined values // 这样过滤非空啊,假设是undefined会被过滤掉吗? // 不做 typeof src 是否 "object"、"function"的推断吗? if ( (options = arguments[ i ]) != null ) { // 赋值给变量 options // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // 思虑万全:假设已经是自家人,就别嘚瑟了 // Prevent never-ending loop if ( target === copy ) { continue; } // 对普通对象和数组,考虑递归深层拷贝 // 问题来了,什么叫普通对象? function 算不算? 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 : {}; } //递归调 //假设写成 jQuery.extend( deep, clone, copy ) 是否一样 // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values // 对 undefined 和 != null 还要加深理解 } else if ( copy !== undefined ) { // 临门一脚。假设是 jQuery.extend({xx,xfasf});的情况,扩展的是this。即调用者。

    // 对target直接改动。也没创建clone啥的 target[ name ] = copy; } } } } // Return the modified object return target; };

    4、再看看jQuery.isPlainObject怎样定义的

     isPlainObject: function( obj ) {
      
    	  // Must be an Object.
    	  // Because of IE, we also have to check the presence of the constructor property.
    	  // Make sure that DOM nodes and window objects don't pass through, as well
    	  // 翻译:
    	  // 必须是一个对象。
    	  // 由于IE的缘故。我们还必须检查是否有constructor属性。

    // 确认别放过Dom节点和window对象。他们不是普通对象。 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { // 下面不通过空、undefined、0、jQuery.type返回不是object的、dom对象、window对象 // 所以 typeof 为string、number、function、正则、date的都不成 return false; } try { // Not own constructor property must be Object if ( obj.constructor && !core_hasOwn.call(obj, "constructor") && !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) { // IE8,9 Will throw exceptions on certain host objects #9897 return false; } // 枚举的时候,自有属性会先被枚举出来。假设最后一个属性是自有属性,那么全部属性都是自有属性。 // 简而言之。不能有继承来的,能够被枚举到的属性。你妹!

    为什么有这种要求? // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || core_hasOwn.call( obj, key ); }

    5、
    试试看

    jQuery.extend({
     <span style="white-space:pre">	</span>sayHi:function(you){
      <span style="white-space:pre">		</span>console.log('hi',you);
     <span style="white-space:pre">	</span>}
    });
    $.sayHi('Stanley'); // output : hi Stanley

    还不错!

    假设想覆盖jQuery已有的方法呢?

    jQuery.extend({
    	 isPlainObject:function(obj){
    			return 'baby, I am not sure.';
    	 }
    });
    var r = $.isPlainObject({});
    console.log(r); // output : baby, I am not sure.

    这...好吧,能够得逞。想想别的办法吧,不能这样。

    再玩儿:

    jQuery.extend({
    	 extend:function(obj){
    		  // do nothing
    		  return 'who am i?';
    	 }
    });
    var r = $.extend({x:function(){ alert();}});
    console.log(r); // output : who am i?
    jQuery.x();// error : function not be defined

    又得逞,这样。再没人能够通过extend扩展jQuery的方法了。
    但能够有更直接的方法。



  • 相关阅读:
    软阈值迭代算法(ISTA)和快速软阈值迭代算法(FISTA)
    伍德伯里矩阵恒等式(Woodbury matrix identity)
    压缩感知:一种新型亚采样技术
    运输层--------运输层与网络层的关系、UDP、TCP
    单链表的基本操作(二)
    单链表的基本操作(一)
    c++中的数据类型转换
    链表总的首元结点、头结点、头指针的区别
    封装设计基础知识点
    git的使用总结
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7052441.html
Copyright © 2011-2022 走看看