JavaScript中的伪数组理解

看过jQuery源码的人都知道类数组对象,与我们熟知的arguments对象很像

构造一个类数组必须有两个条件

第一个条件:你必须给对象定义个splice方法,只要他是一个function就可以

第二个条件:就是赋值一个length属性,或者增加push,unshift,shift,pop其中任何一个方法,并且调用了一次。

当这两个条件同时满足那么当前的对象在控制台输出后跟数组的格式一模一样。

一般而言大部分都是这样构造一个类数组对象(jQuery就是这么干的)。因为相比而言,这样更简洁,并且更有意义。

1 var obj = {
2     length: 0,
3     splice: [].splice
4 };

同样可以实现类数组的代码,除了splice,其他四个方法只要定义了其中的任何一个并且调用了。

 1 var blankArray = [];
 2 var obj = {
 3     splice: blankArray.splice,
 4     push: blankArray.push,
 5     unshift: blankArray.unshift,
 6     pop: blankArray.pop,
 7     shift: blankArray.shift
 8 };
 9 obj.push();
10 obj.unshift();
11 obj.pop();
12 obj.shift();

那为什么浏览器会这么做?其实我也不明白,因为我没看过浏览器的内部实现,这个谁要知道的话,烦请告诉我一下。

----------------------------------------分割线------------------------------------

可能有些人不太明白直接把push指向数组的push方法就能直接调用,并且行为还和数组一样?

是的,push本身就是给数组追加值的,在对象中这里也是一样的,他会先检测length属性的值,然后从length的位置添加push传的参数。key从length之后开始累加,同时更改length值。来段代码说明下

1 var obj = {
2     length: 1, 
3     splice: blankArray.splice,
4     push: blankArray.push
5 }
6 obj[0] = 10;  //如果length是0的话,push后的结果就是1,2,3。如果length是1的话,那么结果就成了10,1,2,3。
7 
8 obj.push(1,2,3);
9 obj.length // 4

由此看出,对象这里的obj[0] = 10并不会影响length的值,而数组却不同,他会影响length的值。

你可以把数组的下标想象成对象的key

不理解?看下面的代码

1 var testArr = ['one', 'two', 'three'];
2 
3 //可以把以上数组理解成下面这种对象
4 
5 var testObj = {
6     0: 'one',
7     1: 'two',
8     2: 'three'
9 }

 接下来就简单了,obj的push引用了array实例对象的push方法

1 var obj = {
2     // ...
3     //事实上[].push这里引用的是function push() { [native code] },push方法的内部实现
4     push: [].push
5 }

而引用的这个push function,它的context就是obj,与下面的代码意义相同

1 var obj = {
2     push: function(){
3         return [].push.apply(this, arguments);
4     }
5 }

在用下标值访问类数组对象的时候,实际上访问的是它的key。

个人理解,不对请指出。

 

转载请注明出处。

 

posted @ 2014-05-29 19:53  Evan2z  阅读(7657)  评论(1编辑  收藏  举报