要说end(),我们就不得不说prevObject。
在jQuery中,每个jQuery对象都有一个prevObject属性
var $p = $('p');
这个属性是做什么的呢?
jQuery内部维护着一个jQuery对象栈。每个遍历方法都会找到一组新元素(一个jQuery对象),然后jQuery会把这组元素推入到栈中。
可能上面这句话让人读起来有些茫然,不要紧,我们来一个例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> div{ 100px; height:100px; background-color: antiquewhite; margin-bottom: 10px; } </style> </head> <body> <div></div> <div></div> <script src="jquery-3.1.1.js"></script> <script> console.log($('div').eq(0)); // 第二个div元素 console.log($('div').eq(0).end()); // $('div) </script> </body> </html>
看完上面这个例子,我们就大概就能明白end()的作用了。$('div').eq(0)的pervObject为$('div')。而end()的作用就是返回当前jQuery对象(在本例中就是$('div').eq(0))的prevObject对象。
来张图:
来看一看end()的源码:
jQuery.fn.end = function() { return this.prevObject || this.constructor(null); // 返回当前jQuery对象的prevObject对象,简单直接 };
为了更深入了了解prevObject的实现原理,我们先来看一看eq()的源码:
jQuery.eq = function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); // 负索引对应的正索引 = 负索引 + 长度 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); // 讲对应的DOM元素入栈操作 }
eq()用了一个pushStack()方法,那么pushStack()是什么鬼? pushStack会将传入的DOM元素创建为一个新的jQuery对象,并将这个新的jQuery对象的prevObject属性进行修改。
jQuery.fn.pushStack = function( elems ) { // Build a new jQuery matched element set var ret = jQuery.merge( this.constructor(), elems ); // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; // Return the newly-formed element set return ret; };
// 将DOM元素融入到jQuery对象中,并返回融合后的jQuery对象 jQuery.merge = function( first, second ) { // first:jQuery对象 second:DOM元素组成的数组 var len = +second.length, j = 0, i = first.length; for ( ; j < len; j++ ) { first[ i++ ] = second[ j ]; } first.length = i; return first; };