【深入浅出jQuery】源码浅析2--奇技淫巧

最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美。

其结构明晰,高内聚、低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷、渐进增强)优雅的处理能力以及 Ajax 等方面周到而强大的定制功能无不令人惊叹。

另外,阅读源码让我接触到了大量底层的知识。对原生*S 、框架设计、代码优化有了全新的认识,接下来将会写一系列关于 jQuery 解析的文章。

我在 **thub 上关于 jQuery 源码的全文注解,感兴趣的可以围观一下。jQuery v1.10.2 源码注解&*bsp;

&*bsp;

系列第一篇:【深入浅出jQuery】源码浅析--整体架构

本篇是系列第二篇,标题起得有点大,希望内容对得起这个标题,这篇文章主要总结一下在 jQuery 中一些十分讨巧的 cod*** 方式,将会由浅及深,可能会有一些基础,但是我希望全面一点,对看文章的人都有所帮助,源码我还一直在阅读,也会不断的更新本文。

即便你不想去阅读源码,看看下面的总结,我想对提高编程能力,转换思维方式都大有裨益,废话少说,进入正题。

&*bsp;

&*bsp; &*bsp;短路表达式 与 多重短路表达式

短路表达式这个应该人所皆知了。在 jQuery 中,大量的使用了短路表达式与多重短路表达式。

短路表达式:作为"&&"和"||"操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值。这是这两个操作符的一个重要属性。

// ||短路表达式
var foo = a || b;
// 相当于
*f(a){
	foo = a;
}else{
	foo = b;
}

// &&短路表达式
var bar = a && b;
// 相当于
*f(a){
	bar = b;
}else{
	bar = a;
}

当然,上面两个例子是短路表达式最简单是情况,多数情况下,jQuery 是这样使用它们的:

// 选自 jQuery 源码中的 S*zzle 部分
fu*ct*o* s*bl***Check(a, b) {
	var cur = b && a,
		d*ff = cur && a.*odeType === 1 && b.*odeType === 1 &&
		(~b.sourceI*dex || MA*_NEGATIVE) -
		(~a.sourceI*dex || MA*_NEGATIVE);

	// other code ...	
}

嗯,可以看到,d*ff 的值经历了多重短路表达式配合一些全等判断才得出,这种代码很优雅,但是可读性下降了很多,使用的时候权衡一下,多重短路表达式和简单短路表达式其实一样,只需要先把后面的当成一个整体,依次推进,得出最终值。

var a = 1, b = 0, c = 3;

var foo = a && b && c, // 0 ,相当于 a && (b && c) 
  bar = a || b || c;  // 1

这里需要提出一些值得注意的点:

1、在 *avascr*pt 的逻辑运算中,0、""、*ull、false、u*def**ed、NaN 都会判定为 false ,而其他都为 true ;

2、因为 *avascr*pt 的内置弱类型域 (weak-typ*** doma**),所以对严格的输入验证这一点不太在意,即便使用 && 或者 ||&*bsp;运算符的运算数不是布尔值,仍然可以将它看作布尔运算。虽然如此,还是建议如下:

*f(foo){ ... }     //不够严谨
*f(!!foo){ ... }   //更为严谨,!!可将其他类型的值转换为boolea*类型

注重细节,*avaScr*pt 既不弱也不低等,我们只是需要更努力一点工作以使我们的代码变得真正健壮。

&*bsp;

&*bsp; &*bsp;预定义常用方法的入口

在 jQuery 的头几十行,有这么一段有趣的代码:

(fu*ct*o*(w**dow, u*def**ed) {
	var
		// 定义了一个对象变量,一个字符串变量,一个数组变量 
		class2type = {},
		core_vers*o* = "1.10.2",
		core_deletedIds = [],

		// 保存了对象、字符串、数组的一些常用方法 co*cat push 等等...
		core_co*cat = core_deletedIds.co*cat,
		core_push = core_deletedIds.push,
		core_sl*ce = core_deletedIds.sl*ce,
		core_**dexOf = core_deletedIds.**dexOf,
		core_toStr*** = class2type.toStr***,
		core_hasOw* = class2type.hasOw**roperty,
		c