javascript 偽數(shù)組實(shí)現(xiàn)方法
什么是偽數(shù)組
能通過(guò)Array.prototype.slice轉(zhuǎn)換為真正的數(shù)組的帶有l(wèi)ength屬性的對(duì)象。
這種對(duì)象有很多,比較特別的是arguments對(duì)象,還有像調(diào)用getElementsByTagName,document.childNodes之類(lèi)的,它們都返回NodeList對(duì)象都屬于偽數(shù)組。
我們可以通過(guò)Array.prototype.slice.call(fakeArray)將偽數(shù)組轉(zhuǎn)變?yōu)檎嬲腁rray對(duì)象。
來(lái)看個(gè)示例:
var fakeArray01 = {0:'a',1:'b',length:2};//這是一個(gè)標(biāo)準(zhǔn)的有偽數(shù)組對(duì)象
var arr01 = Array.prototype.slice.call(fakeArray01);
alert(arr01[0]);//a
var arr02 = [].slice.call(fakeArray01);
alert(arr02[0]);//a
slice 可以用來(lái)獲取數(shù)組片段,它返回新數(shù)組,不會(huì)修改原數(shù)組。
示例中可以看到fakeArray被成功的轉(zhuǎn)換成了Array對(duì)象。也許大家對(duì)Array.prototype.slice.call這種寫(xiě)法比較陌生,其實(shí)我們也可以通過(guò)[].slice.call這種形式實(shí)現(xiàn)同樣的效果,那為什么我們要通過(guò)prototype的形式實(shí)現(xiàn)呢,答案是以prototype的形式執(zhí)行程序效率更高,同樣代碼也更加優(yōu)美。
偽數(shù)組的實(shí)現(xiàn)
讓我們?cè)偕钊氲目匆幌聜螖?shù)組的實(shí)現(xiàn)。
我們來(lái)看一些特殊的用例:
var fakeArray01 = {a:'a',b:'b',length:2};//沒(méi)有l(wèi)ength下標(biāo)對(duì)應(yīng)的值
var arr01 = Array.prototype.slice.call(fakeArray01);
alert(arr01[0]);//undefined
var fakeArray02 = {0:'a',1:'b',length:'num'};//length不是數(shù)值
var arr02 = Array.prototype.slice.call(fakeArray02);
alert(arr02[1]);//undefined
同樣fakeArray01和fakeArray02被轉(zhuǎn)換成了真正的數(shù)組,但是數(shù)組中的值都為undefined
查看 V8 引擎 array.js 的源碼,可以將 slice 的內(nèi)部實(shí)現(xiàn)簡(jiǎn)化為:
function slice(start, end) {
var len = ToUint32(this.length), result = [];
for(var i = start; i < end; i++) {
result.push(this[i]);
}
return result;
}
可以看出,slice 并不需要 this 為 array 類(lèi)型,只需要有 length 屬性即可。并且 length 屬性可以不為 number 類(lèi)型,當(dāng)不能轉(zhuǎn)換為數(shù)值時(shí),ToUnit32(this.length) 返回 0.
根據(jù)以上結(jié)論可以得出:fakeArray01被轉(zhuǎn)換成了lenth為2的數(shù)組,其值都被初始化為undefined,fakeArray02被轉(zhuǎn)換成了length為0的數(shù)組,自然訪問(wèn)下標(biāo)為1的元素返回undefined
IE的問(wèn)題
針對(duì)于標(biāo)準(zhǔn)瀏覽器slice實(shí)現(xiàn)已經(jīng)可以解釋所有的問(wèn)題,但是IE在處理NodeList時(shí)出現(xiàn)了問(wèn)題。IE中無(wú)法將NodeList轉(zhuǎn)換為真正的數(shù)組,會(huì)出錯(cuò)。這又是為什么呢?嚴(yán)格說(shuō),在IE內(nèi)部定義了一個(gè)抽象類(lèi)Arraioid,Array和Arguments都繼承與此,所以可以用slice。但DOM對(duì)象是通過(guò)COM接入到JScript的,slice檢測(cè)的時(shí)候失效。
Jquery與偽數(shù)組
Jquery內(nèi)部大量運(yùn)用了偽數(shù)組??梢哉f(shuō)整個(gè)Jquery對(duì)象,都是構(gòu)建在偽數(shù)組的基礎(chǔ)之上的,好讓我們來(lái)看一些Jquery的實(shí)際運(yùn)用:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>fakeArray</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script src="jquery-1.4.2.js" type="text/javascript"></script>
<script>
$(document).ready(function(){
var body = $("body");
alert(body.get(0).tagName);
});
</script>
</head>
<body>
<div id="test"></div>
</body>
</html>
再簡(jiǎn)單不過(guò)的程序了,好,讓我們來(lái)看一下其內(nèi)部的實(shí)現(xiàn)原理:
jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {
var match, elem, ret, doc;
// Handle $(""), $(null), or $(undefined)
if ( !selector ) {
return this;
}
// Handle $(DOMElement)
if ( selector.nodeType ) {
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( num ) {
return num == null ?
// Return a 'clean' array
this.toArray() :
// Return just the object
( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
}
}
最后,我們來(lái)解釋一下,程序的執(zhí)行細(xì)節(jié).但是在這之前,還得說(shuō)一下關(guān)于Jquery的內(nèi)部的一些東西。
用過(guò)Jquery的用戶(hù)應(yīng)該都知道$()函數(shù),它是Jquery的選擇器代表。我們可能通過(guò)$()函數(shù)去選取頁(yè)面中的元素(具體語(yǔ)法可參數(shù)Jquery幫助文檔)。實(shí)際上當(dāng)我們執(zhí)行$()函數(shù)時(shí),程序去執(zhí)行上面列出的init方法,我們來(lái)看一下在調(diào)用$(document)時(shí)所發(fā)生的事件:
//$(document)
init: function( selector, context ) {
var match, elem, ret, doc;
// Handle $(DOMElement) : 處理DOM元素,
if ( selector.nodeType ) {
this.context = this[0] = selector; //給屬性0賦予selector值,此時(shí)就是document對(duì)象
this.length = 1; //創(chuàng)建偽數(shù)組,更新下標(biāo)
return this; //返回Jquery對(duì)象
}
//... ...
}
$("body")是同樣的道理,不再多說(shuō)了。
我們知道Jquery里所有的操作返回的都是Jquery對(duì)象,那我們?nèi)绾蔚玫狡渌鶎?duì)應(yīng)的dom對(duì)象呢,Jquery為我們提供了一個(gè)get方法,這是專(zhuān)門(mén)用來(lái)從jquery對(duì)象中取得DOM對(duì)象用的,由此,便有了body.get(0),那為什么又是get(0)而不是get()呢,因?yàn)镴query的所有操作都是針對(duì)于數(shù)組進(jìn)行的。所以,在get方法里,我們要傳一個(gè)下標(biāo)值,來(lái)得到具體的元素?,F(xiàn)在該看get方法的具體實(shí)現(xiàn)了:
get: function( num ) {
return num == null ?
//如果沒(méi)有num,則直接返回DOM數(shù)組
this.toArray() :
//如果指定的num,則返回指定下標(biāo)的元素
//this.slice是jquery的另一個(gè)方法,它內(nèi)部其實(shí)還是調(diào)用Array.prototype.slice來(lái)實(shí)現(xiàn)將偽數(shù)組轉(zhuǎn)換為真實(shí)的數(shù)組
( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
}
關(guān)于偽數(shù)組就到這吧,我想應(yīng)該已經(jīng)差不多了。
注:有機(jī)會(huì)的話(huà),將來(lái)可能會(huì)出一個(gè)"超越Jquery"系列,專(zhuān)門(mén)分析Jquery內(nèi)部執(zhí)行細(xì)節(jié)。但是由于Jquery內(nèi)部的有各種歪門(mén)邪道的手法還不是很理解,所以這是將來(lái)的問(wèn)題了。
參考:
http://lifesinger.org/blog/2010/05/array-prototype-slice/
- 關(guān)于javascript中偽數(shù)組和真數(shù)組的一些小秘密
- JS 將偽數(shù)組轉(zhuǎn)換成數(shù)組的實(shí)現(xiàn)示例
- JavaScript如何將偽數(shù)組轉(zhuǎn)換成數(shù)組?
- JavaScript偽數(shù)組和數(shù)組的使用與區(qū)別
- JS Array.from()將偽數(shù)組轉(zhuǎn)換成數(shù)組的方法示例
- JavaScript偽數(shù)組用法實(shí)例分析
- js中將HTMLCollection/NodeList/偽數(shù)組轉(zhuǎn)換成數(shù)組的代碼
- JavaScript中的偽數(shù)組用法及說(shuō)明
相關(guān)文章
基于JavaScript 性能優(yōu)化技巧心得(分享)
下面小編就為大家分享一篇基于JavaScript 性能優(yōu)化技巧心得,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12自動(dòng)刷新網(wǎng)頁(yè),自動(dòng)刷新當(dāng)前頁(yè)面,JS調(diào)用
自動(dòng)刷新網(wǎng)頁(yè),自動(dòng)刷新當(dāng)前頁(yè)面,JS調(diào)用,需要的朋友可以參考一下2013-06-06JS運(yùn)動(dòng)特效之任意值添加運(yùn)動(dòng)的方法分析
這篇文章主要介紹了JS運(yùn)動(dòng)特效之任意值添加運(yùn)動(dòng)的方法,結(jié)合實(shí)例形式分析了javascript針對(duì)多物體運(yùn)動(dòng)通過(guò)參數(shù)控制不同運(yùn)動(dòng)效果的實(shí)現(xiàn)方法,需要的朋友可以參考下2018-01-01JavaScript中顏色模型的基礎(chǔ)知識(shí)與應(yīng)用詳解
顏色模型,是用來(lái)表示顏色的數(shù)學(xué)模型。比如最常見(jiàn)的?RGB模型,使用?紅綠藍(lán)?三色來(lái)表示顏色。本文就來(lái)和大家講講JavaScript中顏色模型的基礎(chǔ)知識(shí)與應(yīng)用吧2023-02-02利用函數(shù)的惰性載入提高javascript代碼執(zhí)行效率
在 addEvent 函數(shù)每次調(diào)用的時(shí)候都要走一遍,如果瀏覽器支持其中的一種方法,那么他就會(huì)一直支持了,就沒(méi)有必要再進(jìn)行其他分支的檢測(cè)了2014-05-05純js實(shí)現(xiàn)的論壇常用的運(yùn)行代碼的效果
bluidea論壇的腳本板塊的版主寫(xiě)的,不錯(cuò),轉(zhuǎn)到這!2008-07-07一個(gè)js實(shí)現(xiàn)的所謂的滑動(dòng)門(mén)
一個(gè)js實(shí)現(xiàn)的所謂的滑動(dòng)門(mén)...2007-05-05一個(gè)JavaScript繼承的實(shí)現(xiàn)
一個(gè)JavaScript繼承的實(shí)現(xiàn)...2006-10-10