亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

javascript 偽數(shù)組實現(xiàn)方法

 更新時間:2010年10月11日 22:30:46   作者:  
能通過Array.prototype.slice轉(zhuǎn)換為真正的數(shù)組的帶有l(wèi)ength屬性的對象。
這篇文章來回答javascript通用循環(huán)遍歷方法forEach中最后提到的關(guān)于偽數(shù)組的問題。
什么是偽數(shù)組
能通過Array.prototype.slice轉(zhuǎn)換為真正的數(shù)組的帶有l(wèi)ength屬性的對象。
這種對象有很多,比較特別的是arguments對象,還有像調(diào)用getElementsByTagName,document.childNodes之類的,它們都返回NodeList對象都屬于偽數(shù)組。
我們可以通過Array.prototype.slice.call(fakeArray)將偽數(shù)組轉(zhuǎn)變?yōu)檎嬲腁rray對象。
來看個示例:
復(fù)制代碼 代碼如下:

var fakeArray01 = {0:'a',1:'b',length:2};//這是一個標(biāo)準(zhǔn)的有偽數(shù)組對象
var arr01 = Array.prototype.slice.call(fakeArray01);
alert(arr01[0]);//a
var arr02 = [].slice.call(fakeArray01);
alert(arr02[0]);//a

slice 可以用來獲取數(shù)組片段,它返回新數(shù)組,不會修改原數(shù)組。
示例中可以看到fakeArray被成功的轉(zhuǎn)換成了Array對象。也許大家對Array.prototype.slice.call這種寫法比較陌生,其實我們也可以通過[].slice.call這種形式實現(xiàn)同樣的效果,那為什么我們要通過prototype的形式實現(xiàn)呢,答案是以prototype的形式執(zhí)行程序效率更高,同樣代碼也更加優(yōu)美。
偽數(shù)組的實現(xiàn)
讓我們再深入的看一下偽數(shù)組的實現(xiàn)。
我們來看一些特殊的用例:
復(fù)制代碼 代碼如下:

var fakeArray01 = {a:'a',b:'b',length:2};//沒有l(wèi)ength下標(biāo)對應(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)部實現(xiàn)簡化為:
復(fù)制代碼 代碼如下:

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 類型,只需要有 length 屬性即可。并且 length 屬性可以不為 number 類型,當(dāng)不能轉(zhuǎn)換為數(shù)值時,ToUnit32(this.length) 返回 0.
根據(jù)以上結(jié)論可以得出:fakeArray01被轉(zhuǎn)換成了lenth為2的數(shù)組,其值都被初始化為undefined,fakeArray02被轉(zhuǎn)換成了length為0的數(shù)組,自然訪問下標(biāo)為1的元素返回undefined
IE的問題
針對于標(biāo)準(zhǔn)瀏覽器slice實現(xiàn)已經(jīng)可以解釋所有的問題,但是IE在處理NodeList時出現(xiàn)了問題。IE中無法將NodeList轉(zhuǎn)換為真正的數(shù)組,會出錯。這又是為什么呢?嚴(yán)格說,在IE內(nèi)部定義了一個抽象類Arraioid,Array和Arguments都繼承與此,所以可以用slice。但DOM對象是通過COM接入到JScript的,slice檢測的時候失效。
Jquery與偽數(shù)組
Jquery內(nèi)部大量運用了偽數(shù)組。可以說整個Jquery對象,都是構(gòu)建在偽數(shù)組的基礎(chǔ)之上的,好讓我們來看一些Jquery的實際運用:
復(fù)制代碼 代碼如下:

<!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>

再簡單不過的程序了,好,讓我們來看一下其內(nèi)部的實現(xiàn)原理:
復(fù)制代碼 代碼如下:

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 ] );
}
}

最后,我們來解釋一下,程序的執(zhí)行細(xì)節(jié).但是在這之前,還得說一下關(guān)于Jquery的內(nèi)部的一些東西。
用過Jquery的用戶應(yīng)該都知道$()函數(shù),它是Jquery的選擇器代表。我們可能通過$()函數(shù)去選取頁面中的元素(具體語法可參數(shù)Jquery幫助文檔)。實際上當(dāng)我們執(zhí)行$()函數(shù)時,程序去執(zhí)行上面列出的init方法,我們來看一下在調(diào)用$(document)時所發(fā)生的事件:
復(fù)制代碼 代碼如下:

//$(document)
init: function( selector, context ) {
var match, elem, ret, doc;
// Handle $(DOMElement) : 處理DOM元素,
if ( selector.nodeType ) {
this.context = this[0] = selector; //給屬性0賦予selector值,此時就是document對象
this.length = 1; //創(chuàng)建偽數(shù)組,更新下標(biāo)
return this; //返回Jquery對象
}
//... ...
}

$("body")是同樣的道理,不再多說了。
我們知道Jquery里所有的操作返回的都是Jquery對象,那我們?nèi)绾蔚玫狡渌鶎?yīng)的dom對象呢,Jquery為我們提供了一個get方法,這是專門用來從jquery對象中取得DOM對象用的,由此,便有了body.get(0),那為什么又是get(0)而不是get()呢,因為Jquery的所有操作都是針對于數(shù)組進(jìn)行的。所以,在get方法里,我們要傳一個下標(biāo)值,來得到具體的元素?,F(xiàn)在該看get方法的具體實現(xiàn)了:
復(fù)制代碼 代碼如下:

get: function( num ) {
return num == null ?
//如果沒有num,則直接返回DOM數(shù)組
this.toArray() :
//如果指定的num,則返回指定下標(biāo)的元素
//this.slice是jquery的另一個方法,它內(nèi)部其實還是調(diào)用Array.prototype.slice來實現(xiàn)將偽數(shù)組轉(zhuǎn)換為真實的數(shù)組
( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
}

關(guān)于偽數(shù)組就到這吧,我想應(yīng)該已經(jīng)差不多了。
注:有機會的話,將來可能會出一個"超越Jquery"系列,專門分析Jquery內(nèi)部執(zhí)行細(xì)節(jié)。但是由于Jquery內(nèi)部的有各種歪門邪道的手法還不是很理解,所以這是將來的問題了。
參考:
http://lifesinger.org/blog/2010/05/array-prototype-slice/

相關(guān)文章

最新評論