`
stationxp
  • 浏览: 17146 次
社区版块
存档分类
最新评论

Java程序员的JavaScript学习笔记(9—— jQuery工具方法)

 
阅读更多

计划按如下顺序完成这篇笔记:

1. 理念。
2. 属性复制和继承。
3. this/call/apply。
4. 闭包/getter/setter。
5. prototype。
6. 面向对象模拟。
7. jQuery基本机制。
8. jQuery选择器。
9. jQuery工具方法。
10. jQuery-在“类”层面扩展。
11. jQuery-在“对象”层面扩展。
12. jQuery-扩展选择器。
13. jQuery UI。
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的方法了。
但可以有更直接的方法。



分享到:
评论

相关推荐

    Java Web程序员开发手册(全)

    CSS完全参考手册3.0 ApacheMenu_zh_CN DIV+CSS(WEB标准) hibernate学习笔记 java web 标签大全 JavaScript 中文版 JDK_API_1_6_zh_CN jquery 1.7 中文 api 修正版 Jsp_sevlet中文API jsdom Oracle九阴真经 Servlet ...

    java版商城源码下载-Study-Notes:学习笔记

    2020年Java基础教程(全资料+笔记+源码): 2020年javaweb全套教程: Mysql: Oracle: JDBC: C3P0: 前端技术 HTML、CSS、Javascript: jQuery-: Ajax: Vue: 微信小程序: 动态网页: 编程强化 JVM优化: 数据...

    58同城源码java-javascript-understanding-the-weird-parts:TonyAlicea的JavaScri

    58同城源码java JavaScript:理解奇怪的部分 这些是我关于深入学习 JavaScript 的精彩课程的笔记。 如果您想了解 JavaScript 引擎是如何在幕后工作的,我强烈建议您查看本课程,您可以在 中找到该课程。 生成的目录 ...

    程序员专用刷题-syllabus:纽约大学高级JavaScript课程的教学大纲

    程序员专用刷题 布局 永久链接 默认 / 高级 JavaScript 教学大纲 如果您是教师或对课程设计感兴趣,请参阅文档。 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以即使周围没有...

    vue-notes:Vue学习笔记!

    Vue 系列 学习笔记阅读目录Vue 双向绑定原理,浅析 MVVMVue 源码概要VueX 状态管理常用地址链接Vue 是一个开源框架,最新版本已经更新到了 3.0,当前系列基于 2.X(单独发文 3.0),是一个独立的 Javascript 框架,...

    程序员专用刷题-syllabus:课程说明

    程序员专用刷题高级 JavaScript 教学大纲 如果您是教师或对课程设计感兴趣,请参阅文档。 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以即使周围没有人也可以随意提问。 浏览...

    程序员专用刷题-syllabus:教学大纲

    程序员专用刷题 布局 永久链接 默认 / 高级 JavaScript 教学大纲 如果您是教师或对课程设计感兴趣,请参阅文档。 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以即使周围没有...

    程序员专用刷题-2019.1:2019.1

    程序员专用刷题 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以即使周围没有人也可以随意提问。 浏览并创建 办公时间(见) 获得一对一帮助,或安排见面时间 课程说明 在这门...

    程序员专用刷题-silabus:计算机图形学大纲(IF184502)A级,ITS信息学,2018年

    程序员专用刷题 布局 永久链接 默认 / Silabus Grafika Komputer (kelas A) 如果您是教师或对课程设计感兴趣,请参阅文档。 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以...

Global site tag (gtag.js) - Google Analytics