`
bencode
  • 浏览: 109625 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

jQuery源码解析1(Utilities)

    博客分类:
  • WEB
阅读更多

使用jquery两年多了,  我最早是使用的是prototype库,后来使用mootools, 直到后来弟弟推荐我使用jquery(他是个UI设计师),就一直用到现在。 我是被它的简洁和精炼所吸引的。

 

我喜欢看源代码,以前开发eclipse rcp时,就喜欢看eclipse的源码,因为有时候API文档并不那么明了,eclipse优秀的架构配合JDT强大的功能,让我们很容易地看懂。 一个设计优秀的产品,它的代码应该也是易于理解的。 现在我做web用的是php的ci,在开发过程中也是时常查看它的源代码。

 

为了更好地使用jquery, 所以我阅读了jquery的源代码。不敢独享,所以写出来,相互讨论,一起进步。

 

我使用的是 1.3.2

 

我们从开始的地方开始

 

(function() {
 ...	
})();

 

所有代码包含在以上的函数中,避免名字冲突。

 

1. 几个"全局变量"

 

var 
	window = this,
	undefined, 
	_jQuery = window.jQuery, 
	_$ = window.$,

	jQuery = window.jQuery = window.$ = function(selector, context) {
		return new jQuery.fn.init(selector, context);
	},

	// A simple way to check for HTML strings or ID strings
	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
	// Is it a simple selector
	isSimple = /^.[^:#\[\.,]*$/;

 

1.1

 

 window 还是那个window, undefined 还是那个undefined,只是这样让js 解释器更快地找到他们,提高速度。

 

 _jQuery = window.jQuery

_$ = window.$,

 

保存原来的 jQuery 和 $, 因为默认情况下jquery占用名字空间 jQuery 和$

 

搜索一下使用 _jQuery的地方吧:

 

 

jQuery.extend({
	noConflict: function( deep ) {
		window.$ = _$;

		if ( deep )
			window.jQuery = _jQuery;

		return jQuery;
	},

 

OK, 是为了 noConflict

 

比如我们要同时使用prototype和jquery, 可以先让html页面包含 prototype.js 再包含 jquery.js。

 

然后调用  jq = jQuery.noConflict();   接着就可以用jq来使用jQuery框架, $ 就变回 prototype.js 中的方法了。

 

还有一个deep参数, 可以让另一个jQuery(可能不怎么有名, 但对你的项目有用) 和 现在的jQuery 共存。

 

 

quickExpr是一个正则表达式, 用于快速匹配一个 html tag 或 id 字符串(如 '#id')

isSimple: 也是一个与此同时表达式, 用于匹配一个 selector (css 选择器)

 

1.2

 

 

	jQuery = window.jQuery = window.$ = function(selector, context) {
		return new jQuery.fn.init(selector, context);
	},

 

我们思考: jQuery.fn.init 是构造函数, 那它的实例方法应该由 : jQuery.fn.init.prototype 指定。

 

搜索它, 在541行得到以下代码:

 

 

jQuery.fn.init.prototype = jQuery.fn;

 

所以 我们平常使用 $('#abc') 或 jQuery('#abc') 

 

$ 就是 jQuery,它返回一个对象。 这个对象的构造函数是 jQuery.fn.init(...

 

这个对象的实例方法和字段就是 jQuery.fn 的成员。

 

 

jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) {
	...
	},
	size: function() {
		return this.length;
	},
        ...

 

从以上可以看出,下面的代码等效。

 

var a = $('#id'); // a = new jQuery('#id');

a.size();

 

 

上面我们隐约看到了jQuery的插件结构, 你可以添加方法到 jQuery.fn,就可以在jQuery对象中使用。

 

但首先,我们先看几个通用工具方法,因为其他很多部分使用它们。

 

2. 几个工具方法

 

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

 

我们分两部分看这个方法:首先是准备, 然后是拷贝。

 

准备:

 

jQuery.extend = jQuery.fn.extend = function() {
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};

		i = 2;
	}

	if ( typeof target !== "object" && !jQuery.isFunction(target) )
		target = {};

	if ( length == i ) {
		target = this;
		--i;
	}

 

可以看到,第一个参数可以指定为 boolean , 表示: 是否进行 深拷贝

 

如果是多于一个 object,那么第一个object 为 target,它将被其他的 object 的成员扩展

如果仅有一个object, 那么 this (jQuery 或 jQuery.fn) 为 target,  object 的成员将添加到 target中

 

 

我们常常这样使用:

 

var b = $.extend({}, a);  // 复制一份

options = $.extend({ 'name': 'editor', value: '100' }, options); // 默认参数


$.extend({

  myfunc: function() {...  // 为jquery添加 工具方法

});


$.fn.extend({

  myplugin: function() {...  // 为jquery添加插件

})

 

 

另一部分的拷贝代码也很容易:

 

	for ( ; i < length; i++ )
		if ( (options = arguments[ i ]) != null )
			for ( var name in options ) {
				var src = target[ name ], copy = options[ name ];

				if ( target === copy )
					continue;

				if ( deep && copy && typeof copy === "object" && !copy.nodeType )
					target[ name ] = jQuery.extend( deep, 
						src || ( copy.length != null ? [ ] : { } )
					, copy );

				else if ( copy !== undefined )
					target[ name ] = copy;

			}

	return target;

 

2.2  each(object, callback)

 

 

	// args is for internal usage only
	each: function( object, callback, args ) {
		var name, i = 0, length = object.length;

...

 

 

我们只使用到两个参数,args 内部使用。

 

		if ( args ) {
			if ( length === undefined ) {
				for ( name in object )
					if ( callback.apply( object[ name ], args ) === false )
						break;
			} else
				for ( ; i < length; )
					if ( callback.apply( object[ i++ ], args ) === false )
						break;

			// A special, fast, case for the most common use of each
		} else {

 

这一部分是是框架内部使用。我们else部分:

 

		} else {
			if ( length === undefined ) {
				for ( name in object )
					if ( callback.call( object[ name ], name, object[ name ] ) === false )
						break;
			} else
				for ( var value = object[0];
					i < length && callback.call( value, i, value ) !== false; 
					value = object[++i] ){}

 

 从代码中,我们知道,可以对“数组”或“对象”进行迭代。

 

var a = ['a', 'b', 'c', 'd', 'e'];

$.each(a, function() {
    alert(this);  // this即每次迭代的值
});

$.each(a, function(index, value) {
  // ...
});

$.each(a, function() {
   if (this == 'c') {
    return false;    // 'break'
  }
}

 

最后,each 返回 object 以支持链式调用

2.3  isFunction(obj),  isArray(obj), isXMLDoc(elem)

注: isXMLDoc 没有收录在API文档中, 所以不要使用。

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return toString.call(obj) === "[object Function]";
	},

	isArray: function( obj ) {
		return toString.call(obj) === "[object Array]";
	},

	// check if an element is in a (or is an) XML document
	isXMLDoc: function( elem ) {
		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
			!!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
	},

 

2.4  trim(text)

这个太熟悉不过了:

 

	trim: function( text ) {
		return (text || "").replace( /^\s+|\s+$/g, "" );
	},

 

没有什么特殊的技巧, 使用简单的正则替换。

 

prototype.js是这样的:

 

  strip: function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  },

 

2.5  grep(array, callback, insert),  map(array, callback)

 

	grep: function( elems, callback, inv ) {
		var ret = [];
		for ( var i = 0, length = elems.length; i < length; i++ )
			if ( !inv != !callback( elems[ i ], i ) )
				ret.push( elems[ i ] );

		return ret;
	},

 

所以我们这样使用:

 

var a = [2, 3, 6, 1, 8, 9];

$.grep(a, function(v) {  //   只要>= 3的数
    return v >= 3;
});

$.grep(a, function(v) {
    return v >= 3;
}, false); // 这样相当于 < 3

 

下面是map

 

	map: function( elems, callback ) {
		var ret = [];
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			var value = callback( elems[ i ], i );

			if ( value != null )
				ret[ ret.length ] = value;
		}

		return ret.concat.apply( [], ret );
	}

 

最后一句话是干嘛? return ret.concat.apply( [], ret );

上面的相当于:  return [].concat(ret[0], ret[1], ...);

 

var a = [].concat(1, 2, 3, [4, 5]) ; // a = [1, 2, 3, 4, 5];

 

原来这样是让函数更灵活, 让我们可以这样使用:

 

a = [1, 2, 3, 4];

b = $.map(a, function(v) {
	return [v, 2 * v];
});

// b = [1, 2, 2, 4, 3, 6, 4, 8];

 

返回值为null 会被过滤

 

---

 

2.6 makeArray(obj),  inArray(value, array)

 

	makeArray: function( array ) {
		var ret = [];

		if( array != null ){
			var i = array.length;
			// The window, strings (and functions) also have 'length'
			if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
				ret[0] = array;
			else
				while( i )
					ret[--i] = array[i];
		}

		return ret;
	},

 

 

如果没有length属性,或者是 string, function window 之一, 就返回一个元素的数组。

 

 

	inArray: function( elem, array ) {
		for ( var i = 0, length = array.length; i < length; i++ )
		// Use === because on IE, window == document
			if ( array[ i ] === elem )
				return i;

		return -1;
	},

 

如果元素elm在 array中,返回位置,否则返回-1

 

  2.7 merge(first, second)

 

 

 

	merge: function( first, second ) {
		// We have to loop this way because IE & Opera overwrite the length
		// expando of getElementsByTagName
		var i = 0, elem, pos = first.length;
		// Also, we need to make sure that the correct elements are being returned
		// (IE returns comment nodes in a '*' query)
		if ( !jQuery.support.getAll ) {
			while ( (elem = second[ i++ ]) != null )
				if ( elem.nodeType != 8 )
					first[ pos++ ] = elem;

		} else
			while ( (elem = second[ i++ ]) != null )
				first[ pos++ ] = elem;

		return first;
	},

 

但是我不知道 jQuery.support.getAll 是哪里来的?

只有 jQuery.support.objectAll, 这里会不会是笔误?

 

 整理一下先:

 


 

(PS: 本来想全部写好才发布的,但一开始保存在草稿箱中,后来修改的时候不小心按错了, 就将错就错,还是把它分成几部分,否则太长了)

  • 大小: 5.4 KB
分享到:
评论
8 楼 forgood 2010-10-25  
var a = [].concat(1, 2, 3, [4, 5]) ; // a = [1, 2, 3, 4, 5];

concat(value)是Array的一个方法,可以合并value的数据生成一个新的数组
7 楼 __游乐场 2010-10-19  
jquery对象的length属性被delete了的时候
6 楼 lipeng88213 2010-10-19  
引用
merge: function( first, second ) {
var i = first.length, j = 0;

if ( typeof second.length === "number" ) {
for ( var l = second.length; j < l; j++ ) {
first[ i++ ] = second[ j ];
}

} else {
while ( second[j] !== undefined ) {
first[ i++ ] = second[ j++ ];
}
}

first.length = i;

return first;
}


这是1.4.3版本的代码 请问楼主 
引用

} else {
while ( second[j] !== undefined ) {
first[ i++ ] = second[ j++ ];
}
}

这个是判断什么的 什么情况会用到?
5 楼 freshman008 2010-06-17  
推荐jquery学习网站
http://jquery-api-zh-cn.googlecode.com/svn/trunk/index.html
绝对很有收获
4 楼 oolala 2010-06-11  
持续观看,请发布其余高见
3 楼 lipeng88213 2010-06-10  
我认真读了一遍 写的真的不错  希望楼主继续努力
2 楼 bencode 2010-04-06  
skyblue1984 写道
引用

从以上可以看出,下面的代码等效。
var a = $('#id'); // a = new jQuery('#id');
a.size();

这个是错的
应该是
var a = $('#id'); // a = new jQuery.fn.init('#id');


a = new jQuery('#id'); // 可以的,只是没有人这么用:)
当然 a = new jQuery.fn.init('#id'); 肯定也可以。
1 楼 skyblue1984 2010-03-30  
引用

从以上可以看出,下面的代码等效。
var a = $('#id'); // a = new jQuery('#id');
a.size();

这个是错的
应该是
var a = $('#id'); // a = new jQuery.fn.init('#id');

相关推荐

    jQuery Utilities 分类下的函数(或属性)的实现方式分析

    本文将深入探讨jQuery Utilities分类下的函数(或属性)的实现方式,帮助你更好地理解和利用这些功能,提高你的前端开发效率。 首先,jQuery Utilities包含了各种实用的函数,它们是jQuery库中的基础组成部分,用于...

    jquery插件jquery-ui-1.8.2.custom.min.js

    《jQuery UI与jQuery插件深度解析——以jquery-ui-1.8.2.custom.min.js为例》 在Web开发领域,jQuery库以其简洁易用的API和强大的功能深受开发者喜爱。而jQuery UI作为jQuery的一个扩展,提供了丰富的用户界面组件...

    UtilitiES UtilitiES UtilitiES

    UtilitiES UtilitiES UtilitiES UtilitiES UtilitiES

    sirenix.utilities.dll

    sirenix.utilities.dll

    DameWare NT Utilities 8.0.1.151破解版

    DameWare NT Utilities 8.0.1.151破解版

    qemukvm详细教程[借鉴].pdf

    sudo apt-get install gcc libsdl1.2-dev zlib1g-dev libasound2-dev linux-kernel-headers pkg-config libgnutls-dev libpci1 pciutils-dev ``` 然后,下载最新的 qemu-kvm-0.12.4.tar.gz,解压缩: ```bash tar ...

    jQuery中文API

    9. **实用工具(Utilities)**:jQuery还包含了一些实用工具函数,如`.each()`用于循环迭代,`.data()`用于存储和检索元素关联的数据,`.is()`用于判断元素是否匹配某个选择器。 10. **版本更新与兼容性(Version ...

    CommonUtilities工具类源码2012429

    CommonUtilities工具类源码 程序介绍: 控件——对象——关系映射 常用公共操作类 增强的自定义控件 代码自动生成器 界面自动生成器 框架目前已经实现哪些功能 1.有一些公共操作类,是以前积累的。 2.写了三个...

    jQuery1.11.0_20140330_jquery_

    jQuery是一个JavaScript函数库。jQuery是一个轻量级的&quot;...jQuery库包含以下功能: HTML 元素选取 HTML 元素操作 CSS 操作 HTML 事件函数 JavaScript 特效和动画 HTML DOM 遍历和修改 AJAX Utilities

    jQuery的帮助文档

    jQuery中的Utilities包括了一组有用的函数和工具,用于简化常见任务,比如文档处理、数组操作、对象扩展等。这些工具方法为开发者提供了方便,可以减少编码工作量。 通过以上知识点的介绍,我们可以看到jQuery不仅...

    jquery-ui-1.10.2.custom

    1. **ThemeRoller**:这是一个在线工具,允许开发者自定义 jQuery UI 的外观,创建符合网站风格的主题。在 `jquery-ui-1.10.2.custom` 中,你可以找到预设的主题文件,用于快速调整界面样式。 2. **Widgets**:包括...

    Magic Utilities v6.11

    《Magic Utilities v6.11:打造高效便捷的系统管理体验》 Magic Utilities v6.11是一款专为用户设计的高效系统工具,其主要功能包括卸载管理、启动加载和进程管理,旨在提供一种简单易用且智能的电脑维护方案。这款...

    UTIlITIES...

    UTIlITIES UTIlITIES UTIlITIESOK

    MP3 Player Utilities v3.57

    1. **固件下载**:软件可能会提供最新的固件版本,允许用户下载并准备刷入到MP3播放器中。 2. **备份与恢复**:在进行固件更新前,软件可能允许用户备份当前的固件,以便在出现问题时恢复到原始状态。 3. **刷机...

    jQuery-1.8.1.js jQuery-1.8.0 API

    1. **核心(Core)**:介绍 jQuery 对象的基本概念,如 `$()` 函数的使用和如何创建 jQuery 对象。 2. **选择器(Selectors)**:详细列出所有可用的选择器,以及它们如何与 CSS 选择器对应。 3. **DOM 操作...

    jquery.validate Validation .js验证框架 帮助 手册 文档 chm

    (一)、可选项( options ) 1 (二)插件方法 (jQuery validation) 6 (三、四)选择器及实用工具 (jQuery validation) 7 四、实用工具(Utilities) 8 (五)验证器 (jQuery validation) 8 (六)内置验证方法 ...

    batch utilities.scp

    batch utilities.scpbatch utilities.scp

    Norton Utilities激活码

    《Norton Utilities激活码:深度解析与使用指南》 Norton Utilities是一款由Symantec公司推出的强大系统优化工具,被誉为“免费永久优化大师”。这款软件集合了多项实用功能,包括磁盘清理、性能提升、注册表修复、...

    mysql-utilities源代码

    1. **下载源代码**: 首先,你需要从MySQL官方网站或GitHub仓库下载`mysql-utilities-1.6.1.zip`文件。这是源代码的压缩包,解压后可以获取所有源代码文件。 2. **编译环境准备**: 确保你的系统已经安装了GCC编译器...

    TuneUp Utilities 2012注册码注册机

    史上最强大的TuneUp Utilities™ TuneUp Utilities™ 2012现在可供使用了,并且...有才: TuneUp Start Center可以让您立即访问TuneUp Utilities™ 2012的最佳功能,例如1键维护、Turbo模式、实时优化和TuneUp节能模式

Global site tag (gtag.js) - Google Analytics