来自 澳门金莎娱乐手机版 2019-11-28 05:45 的文章
当前位置: 金沙澳门官网网址 > 澳门金莎娱乐手机版 > 正文

2源码学习6,伪数组实现方法_javascript技巧_脚本之

96 // Start with an empty selector
97 selector: "",
98
99 // The current version of jQuery being used
100 jquery: "1.3.2",
101
102 // The number of elements contained in the matched element set
103 size: function() {
104 return this.length;
105 },
106
107 // Get the Nth element in the matched element set OR
108 // Get the whole matched element set as a clean array
109 get: function( num ) {
110 return num === undefined ?
111
112 // Return a 'clean' array
113 Array.prototype.slice.call( this ) :
114
115 // Return just the object
116 this[ num ];
117 },

这篇文章来回答javascript通用循环遍历方法forEach中最后提到的关于伪数组的问题。 什么是伪数组 能通过Array.prototype.slice转换为真正的数组的带有length属性的对象。 这种对象有很多,比较特别的是arguments对象,还有像调用getElementsByTagName,document.childNodes之类的,它们都返回NodeList对象都属于伪数组。 我们可以通过Array.prototype.slice.call将伪数组转变为真正的Array对象。 来看个示例: 复制代码 代码如下: var fakeArray01 = {0:'a',1:'b',length:2};//这是一个标准的有伪数组对象 var arr01 = Array.prototype.slice.call; alert;//a var arr02 = [].slice.call; alert;//a slice 可以用来获取数组片段,它返回新数组,不会修改原数组。 示例中可以看到fakeArray被成功的转换成了Array对象。也许大家对Array.prototype.slice.call这种写法比较陌生,其实我们也可以通过[].slice.call这种形式实现同样的效果,那为什么我们要通过prototype的形式实现呢,答案是以prototype的形式执行程序效率更高,同样代码也更加优美。 伪数组的实现 让我们再深入的看一下伪数组的实现。 我们来看一些特殊的用例: 复制代码 代码如下: var fakeArray01 = {a:'a',b:'b',length:2};//没有length下标对应的值 var arr01 = Array.prototype.slice.call; alert;//undefined var fakeArray02 = {0:'a',1:'b',length:'num'};//length不是数值 var arr02 = Array.prototype.slice.call; alert;//undefined 同样fakeArray01和fakeArray02被转换成了真正的数组,但是数组中的值都为undefined 查看 V8 引擎 array.js 的源码,可以将 slice 的内部实现简化为: 复制代码 代码如下: function slice { var len = ToUint32, result = []; for(var i = start; i < end; i++) { result.push; } return result; } 可以看出,slice 并不需要 this 为 array 类型,只需要有 length 属性即可。并且 length 属性可以不为 number 类型,当不能转换为数值时,ToUnit32 返回 0. 根据以上结论可以得出:fakeArray01被转换成了lenth为2的数组,其值都被初始化为undefined,fakeArray02被转换成了length为0的数组,自然访问下标为1的元素返回undefined IE的问题 针对于标准浏览器slice实现已经可以解释所有的问题,但是IE在处理NodeList时出现了问题。IE中无法将NodeList转换为真正的数组,会出错。这又是为什么呢?严格说,在IE内部定义了一个抽象类Arraioid,Array和Arguments都继承与此,所以可以用slice。但DOM对象是通过COM接入到JScript的,slice检测的时候失效。 Jquery与伪数组 Jquery内部大量运用了伪数组。可以说整个Jquery对象,都是构建在伪数组的基础之上的,好让我们来看一些Jquery的实际运用: 复制代码 代码如下:

从 97 行开始,一直到 538 行,定义了 jQuery 对象所共享的方法和属性。

fakeArray

97 行在对象上定义了一个属性 selector,用来表示当前使用的选择器
110 行在对象上定义了一个属性 jquery,表示当前的 jQuery 版本
澳门金莎娱乐手机版 ,103 行定义了 jQuery 对象的 size 方法,由于 jQuery 对象就是一个仿数组的对象,所以直接返回对象的 length 属性,就是查询结果中的对象数量。

再简单不过的程序了,好,让我们来看一下其内部的实现原理: 复制代码 代码如下: jQuery.fn = jQuery.prototype = { init: function { var match, elem, ret, doc; // Handle $, or $ if { return this; } // Handle $ if { this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context ) { this.context = document; this[0] = document.body; this.selector = "body"; this.length = 1; return this; } //... ... }, get: function { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object ( num < 0 ? this.slice[ 0 ] : this[ num ] ); } } 最后,我们来解释一下,程序的执行细节.但是在这之前,还得说一下关于Jquery的内部的一些东西。 用过Jquery的用户应该都知道$()函数,它是Jquery的选择器代表。我们可能通过$()函数去选取页面中的元素。实际上当我们执行$()函数时,程序去执行上面列出的init方法,我们来看一下在调用$时所发生的事件: 复制代码 代码如下: //$ init: function { var match, elem, ret, doc; // Handle $ : 处理DOM元素, if { this.context = this[0] = selector; //给属性0赋予selector值,此时就是document对象 this.length = 1; //创建伪数组,更新下标 return this; //返回Jquery对象 } //... ... } $是同样的道理,不再多说了。 我们知道Jquery里所有的操作返回的都是Jquery对象,那我们如何得到其所对应的dom对象呢,Jquery为我们提供了一个get方法,这是专门用来从jquery对象中取得DOM对象用的,由此,便有了body.get而不是get()呢,因为Jquery的所有操作都是针对于数组进行的。所以,在get方法里,我们要传一个下标值,来得到具体的元素。现在该看get方法的具体实现了: 复制代码 代码如下: get: function { return num == null ? //如果没有num,则直接返回DOM数组 this.toArray() : //如果指定的num,则返回指定下标的元素 //this.slice是jquery的另一个方法,它内部其实还是调用Array.prototype.slice来实现将伪数组转换为真实的数组 ( num < 0 ? this.slice[ 0 ] : this[ num ] ); } 关于伪数组就到这吧,我想应该已经差不多了。 注:有机会的话,将来可能会出一个"超越Jquery"系列,专门分析Jquery内部执行细节。但是由于Jquery内部的有各种歪门邪道的手法还不是很理解,所以这是将来的问题了。 参考:

本文由金沙澳门官网网址发布于澳门金莎娱乐手机版,转载请注明出处:2源码学习6,伪数组实现方法_javascript技巧_脚本之

关键词: