仿栈与队列的操作


jQuery既然是模仿的数组结构,那么肯定会实现一套类数组的处理方法,比如常见的栈与队列操作push、pop、shift、unshift、求和、遍历循环each、排序及筛选等一系的扩展方法。

jQuery对象栈是一个便于Dom的查找,提供的一系列方法,jQuery可以是集合元素,那么我们怎么快速的找到集合中对应的目标元素呢?正序,逆序。

jQuery提供了.get()、:index()、 :lt()、:gt()、:even()及 :odd()这类索引值相关的选择器,他们的作用可以过滤他们前面的匹配表达式的集合元素,筛选的依据就是这个元素在原先匹配集合中的顺序。

我们来分别看一下这几个选择器的实现原理:

get方法--是通过检索匹配jQuery对象得到对应的DOM元素,如下代码实现:

get: function(num) {
    return num != null ?
    // Return just the one element from the set
    (num < 0 ? this[num + this.length] : this[num]) :
    // Return all the elements in a clean array
    slice.call(this);
}
 
  
 原理很简单,因为jQuery查询出来的是一个数组的DOM集合,所以就可以按照数组的方法通过下标的索引取值,当然如果num的值超出范围,比如小于元素数量的负数或等于或大于元素的数量的数,那么它将返回undefined。 假设我们页面上有一个简单的无序列表,如下代码:
 
  
<ul>
  <li id="foo">foo</li>
  <li id="bar">bar</li>
</ul>
 
  
 如果指定了index参数,.get()则会获取单个元素,如下代码:
 
  
console.log( $( "li" ).get( 0 ) );
 
  
 由于索引 index 是以 0 开始计数的,所以上面代码返回了第一个列表项<li id="foo">foo</li>。
 然而,这种语法缺少某些 .get() 所具有的附加功能,比如可以指定索引值为负值:
 
  
console.log( $( "li" ).get(-1) );
 
  
 负的索引值表示从匹配的集合中从末尾开始倒数,所以上面这个例子将会返回列表中最后一项:<li id="bar">bar</li>。
 
 由于是数组的关系,所以我们有几个快速方法,比如头跟尾的取值:
 
  
first: function() {
    return this.eq( 0 );
},

last: function() {
    return this.eq(-1);
},
 
   
有一条语句要重点解释:
 
  
有一条语句要重点解释:
 由于是数组的关系,所以我们有几个快速方法,比如头跟尾的取值: 
  
Array.prototype.slice.call(argments,0)

Array.prototype.slice.call(thisArg[, arg1[, arg2[, ...]]]) 

成员介绍: 
Array [object] 

Array对象(即数组对象) 
prototype [property] 
Javascript的原型,此prototype非Prototype.js,可以暂且理解为Java中的静态属性/方法。 
slice [Function] 
数组切分方法,很有用的一个方法,具体请看这里,或那里。  
call [Function] 
神奇的方法,该方法是所有Function对象里的方法,所以slice就有这样一个方法。用于把Function对象里的this替换为目标对象。

作用效果: 
Array.prototype.slice.call == [].slice 

虽然运行结果是一个样的,前者的运行效率比后者大大提高

机理: 
这里的slice方法就是一个Function对象。通常情况下,程序员通过如下方法调用Function,实质是普通的函数调用方法: 

Array.slice(begin,end) 

至于call()方法,METHOD: Function::call告诉我们,可以通过 

Function.call(thisArg[, arg1[, arg2[, ...]]]) 

的形式调用一个Function对象,把当中的this对象替换为thisArg,即可以得到下面的代码: 

Array.prototype.slice.call(obj,begin,end) 

用伪代码模拟过程: 

好,我们用伪代码的方法来模拟整个过程: 

1 var mySlice=Array.prototype.slice; 

2 alert(mySlice); //alert: function(begin[,end]){...},这是个“函数” 

3 var array_empty=mySlice(begin,end); //create a new,empty array 

4 set array_empty=obj; //此时,把obj赋给这个空的数组,使数组有了种子, 
                              //这就是call()所做的事,“人工受精” 

5 alert(array_empty); //这是个未定型的数组对象,由Javascript内部掌控着, 
                           //这样看可能没什么结果,但有结果的话,就一定与obj有关 

//下面是关键的一行: 
6 var array_last=array_empty.slice(begin,end); 
/** 
*虽然之前说未定型, 
*但返回的已经是一个数组了,我们对数组进行切割,但拿什么进行切? 
*没错,就拿用obj制造出来的数组进行切割, 
*一个新的数组对象产生了! 
*/