成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深入理解JavaScript類數(shù)組

Towers / 1735人閱讀

摘要:但是,我們可以借用類數(shù)組方法不難看出,此時(shí)的在調(diào)用數(shù)組原型方法時(shí),返回值已經(jīng)轉(zhuǎn)化成數(shù)組了。很多時(shí)候,深入看看源代碼也會(huì)讓你對(duì)這個(gè)理解的更透徹。的前端樂(lè)園原文鏈接深入理解類數(shù)組

起因

寫這篇博客的起因,是我在知乎上回答一個(gè)問(wèn)題時(shí),說(shuō)自己在學(xué)前端時(shí)把《JavaScript高級(jí)程序設(shè)計(jì)》看了好幾遍。
于是在評(píng)論區(qū)中,出現(xiàn)了如下的對(duì)話:

天啦嚕,這話說(shuō)的,寶寶感覺(jué)到的,是滿滿的惡意啊。還好自己的JavaScript基礎(chǔ)還算不錯(cuò),沒(méi)被打臉。(吐槽一句:知乎少部分人真的是惡意度爆表,整天想著打別人的臉。都是搞技術(shù)的,和善一點(diǎn)不行嗎…………)

不過(guò)這個(gè)話題也引起了我的注意,問(wèn)了問(wèn)身邊很多前端同學(xué)關(guān)于數(shù)組與類數(shù)組的區(qū)別。他們都表示不太熟悉,所以決定寫一篇博客,來(lái)分享我對(duì)數(shù)組與類數(shù)組的理解。

什么是類數(shù)組

類數(shù)組的定義,有如下兩條:

具有:指向?qū)ο笤氐臄?shù)字索引下標(biāo)以及 length 屬性告訴我們對(duì)象的元素個(gè)數(shù)

不具有:諸如 push 、 forEach 以及 indexOf 等數(shù)組對(duì)象具有的方法Q

這兒有三個(gè)典型的JavaScript類數(shù)組例子。

1. DOM方法

// 獲取所有div
let arrayLike = document.querySelectorAll("div")

console.log(Object.prototype.toString.call(arrayLike))  // [object NodeList]

console.log(arrayLike.length) // 127

console.log(arrayLike[0]) 
// 
console.log(Array.isArray(arrayLike)) // false arrayLike.push("push") // Uncaught TypeError: arrayLike.push is not a function(…)

是的,這個(gè)arrayLike的 NodeList,有l(wèi)ength,也能用數(shù)組下標(biāo)訪問(wèn),但是使用Array.isArray測(cè)試時(shí),卻告訴我們它不是數(shù)組。直接使用push方法時(shí),當(dāng)然也會(huì)報(bào)錯(cuò)。
但是,我們可以借用類數(shù)組方法:

let arr = Array.prototype.slice.call(arrayLike, 0)

console.log(Array.isArray(arr)) // true

arr.push("push something to arr")
console.log(arr[arr.length - 1]) // push something to arr

不難看出,此時(shí)的arrayLike在調(diào)用數(shù)組原型方法時(shí),返回值已經(jīng)轉(zhuǎn)化成數(shù)組了。也能正常使用數(shù)組的方法。

2. 類數(shù)組對(duì)象

let arrayLikeObj = {
  length: 2,
  0: "This is Array Like Object",
  1: true
}

console.log(arrayLikeObj.length) // 2
console.log(arrayLikeObj[0]) // This is Array Like Object
console.log(Array.isArray(arrayLikeObj)) // false

let arrObj = Array.prototype.slice.call(arrayLikeObj, 0)
console.log(Array.isArray(arrObj)) // true

這個(gè)例子也很好理解。一個(gè)對(duì)象,加入了length屬性,再用Array的原型方法處理一下,搖身一變成為了真的數(shù)組。

3. 類數(shù)組函數(shù)

這個(gè)應(yīng)該算是最好玩,也是最迷惑人的類數(shù)組對(duì)象了。

let arrayLikeFunc1 = function () {}
console.log(arrayLikeFunc1.length) // 0
let arrFunc1 = Array.prototype.slice.call(arrayLikeFunc1, 0)
console.log(arrFunc1, arrFunc1.length) // ([], 0)

let arrayLikeFunc2 = function (a, b) {}
console.log(arrayLikeFunc2.length) // 2
let arrFunc2 = Array.prototype.slice.call(arrayLikeFunc2, 0)
console.log(arrFunc2, arrFunc2.length) // ([undefined × 2], 2)

可以看出,函數(shù)也有l(wèi)ength屬性,其值等于函數(shù)要接收的參數(shù)。

注:不適用于ES6的rest參數(shù)。具體原因和表現(xiàn)這兒就不再闡述了,不屬于本文討論范圍??蓞⒁?jiàn) 《rest參數(shù) - ECMAScript 6 入門》。另外arguments在ES6中,被rest參數(shù)代替了,所以這兒不作為例子。

而length屬性大于0時(shí),如果轉(zhuǎn)為數(shù)組,則數(shù)組里的值會(huì)是undefined。個(gè)數(shù)等于函數(shù)length的長(zhǎng)度。

類數(shù)組的實(shí)現(xiàn)原理

類數(shù)組的實(shí)現(xiàn)原理,主要有以下兩點(diǎn):
第一點(diǎn)是JavaScript的“萬(wàn)物皆對(duì)象”概念。
第二點(diǎn)則是JavaScript支持的“鴨子類型”。

首先,從第一點(diǎn)開始解釋。

萬(wàn)物皆對(duì)象

萬(wàn)物皆對(duì)象具體解釋如下:

在JavaScript中,“一切皆對(duì)象”,數(shù)組和函數(shù)本質(zhì)上都是對(duì)象,就連三種原始類型的值——數(shù)值、字符串、布爾值——在一定條件下,也會(huì)自動(dòng)轉(zhuǎn)為對(duì)象,也就是原始類型的“包裝對(duì)象”。

而另外一個(gè)要點(diǎn)則是,所有對(duì)象都繼承于Object。所以都能調(diào)用對(duì)象的方法,比如使用點(diǎn)和方括號(hào)訪問(wèn)屬性。
比如說(shuō),這樣的:

let func = function() {}
console.log(func instanceof Object) // true
func[0] = "I"m a func"
console.log(func[0]) // "I"m a func"
鴨子類型

萬(wàn)物皆對(duì)象具體解釋如下:

如果它走起來(lái)像鴨子,而且叫起來(lái)像鴨子,那么它就是鴨子。

比如說(shuō)上面舉的類數(shù)組例子,雖然他們是對(duì)象/函數(shù),但是只要有l(wèi)ength屬性和對(duì)應(yīng)的數(shù)字下標(biāo),那么他們就是數(shù)組。

但是,在這兒,還是有些迷糊的。為什么使用call/apply借用數(shù)組方法就能處理這些類數(shù)組呢?

探秘V8

一開始,我也對(duì)這個(gè)犯迷糊啊。直到我去Github上,看到了谷歌V8引擎處理數(shù)組的源代碼。
地址在這兒:v8/array.js
作為講述,我們?cè)谶@里引用push的源代碼(方便講述,刪除部分。slice的比較長(zhǎng),但是原理一致):

// Appends the arguments to the end of the array and returns the new
// length of the array. See ECMA-262, section 15.4.4.7.
function ArrayPush() {
  // 獲取要處理的數(shù)組
  var array = TO_OBJECT(this);
  // 獲取數(shù)組長(zhǎng)度
  var n = TO_LENGTH(array.length);
  // 獲取函數(shù)參數(shù)長(zhǎng)度
  var m = arguments.length;

  for (var i = 0; i < m; i++) {
    // 將函數(shù)參數(shù)push進(jìn)數(shù)組
    array[i+n] = arguments[i];
  }

  // 修正數(shù)組長(zhǎng)度
  var new_length = n + m;
  array.length = new_length;
  // 返回值是數(shù)組的長(zhǎng)度
  return new_length;
}

是的,整個(gè)push函數(shù),并沒(méi)有涉及是否是數(shù)組的問(wèn)題。只關(guān)心了length。而因?yàn)槠鋵?duì)象的特性,所以可以使用方括號(hào)來(lái)設(shè)置屬性。

這也是萬(wàn)物皆類型和鴨子類型最生動(dòng)的體現(xiàn)。

總結(jié)

JavaScript中的類數(shù)組的特殊性,是由其“萬(wàn)物皆類型”和“鴨子類型”決定的,而瀏覽器引擎底層的實(shí)現(xiàn),更是佐證了這一點(diǎn)。
而先前說(shuō)我的那位同學(xué),因?yàn)橹皇侵李悢?shù)組的幾種表現(xiàn)和用法,并且想通過(guò)apply來(lái)打我臉,證明我根本沒(méi)有仔細(xì)看書。這種行為不僅不友善,而且學(xué)習(xí)效率也不高。
因?yàn)椋?strong>知其然而不知其所以然是不可取的。特別是發(fā)現(xiàn)很多這種例子,就得學(xué)會(huì)歸納總結(jié)。(感謝winter老師的演講:一個(gè)前端的自我修養(yǎng),教會(huì)我很多東西。)。
很多時(shí)候,深入看看源代碼也會(huì)讓你對(duì)這個(gè)理解的更透徹。將來(lái)就算是蹦出一百種類數(shù)組,也能知道是怎么回事兒。

最后,還是開頭那句話:“都是搞技術(shù)的,和善一點(diǎn)不行嗎?有問(wèn)題就好好交流,不要總想著打別人臉啊…………”

最后附上本人博客地址和原文鏈接,希望能與各位多多交流。

Lxxyx的前端樂(lè)園
原文鏈接:深入理解JavaScript類數(shù)組

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79397.html

相關(guān)文章

  • JS程序

    摘要:設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊蹋駝t只會(huì)讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識(shí)只有分享才有存在的意義。 是時(shí)候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評(píng)論0 收藏0
  • 深入理解JavaScript(三):獲取數(shù)組中的最大值方法(this,apply)

    摘要:三個(gè)方法的作用,都是改變的指向,只是用法稍微有些區(qū)別什么是既不指向函數(shù)自身,也不指函數(shù)的詞法作用域。它在函數(shù)定義的時(shí)候是確定不了的在函數(shù)被調(diào)用時(shí)才發(fā)生的綁定,也就是說(shuō)具體指向什么,取決于你是怎么調(diào)用的函數(shù)。 1.排序法 思路:給數(shù)組先排序(由大到小排序),第一項(xiàng)就是最大值 let arr = [1,5,6,7,9,20,40,2,3]; let max1 = arr.sort(func...

    canopus4u 評(píng)論0 收藏0
  • [ JS 基礎(chǔ) ] JS 中 instanceof 運(yùn)算符深入解析 (2)

    摘要:在高級(jí)的技巧中會(huì)用來(lái)創(chuàng)建作用域安全的構(gòu)造函數(shù)。運(yùn)算符希望左操作數(shù)是一個(gè)對(duì)象,右操作數(shù)表示對(duì)象的類。中對(duì)象的類似通過(guò)初始化它們的構(gòu)造函數(shù)來(lái)定義的。為了理解運(yùn)算符是如何工作的,必須首先理解原型鏈原型鏈可作為的繼承機(jī)制。 在js高級(jí)的技巧中會(huì)用instanceof來(lái)創(chuàng)建作用域安全的構(gòu)造函數(shù)。instanceof運(yùn)算符希望左操作數(shù)是一個(gè)對(duì)象,右操作數(shù)表示對(duì)象的類。如果左側(cè)的對(duì)象是右側(cè)類的...

    劉厚水 評(píng)論0 收藏0
  • MongoDB指南---3、MongoDB基礎(chǔ)知識(shí)-數(shù)據(jù)

    摘要:如將構(gòu)造函數(shù)作為函數(shù)進(jìn)行調(diào)用即不包括的方式,返回的是日期的字符串表示,而非日期對(duì)象。如果不注意這一點(diǎn),沒(méi)有始終使用日期構(gòu)造函數(shù),將得到一堆混亂的日期對(duì)象和日期的字符串。關(guān)于日期類的完整解釋,以及構(gòu)造函數(shù)的參數(shù)格式,參見(jiàn)規(guī)范節(jié)。 上一篇文章:MongoDB指南---2、MongoDB基礎(chǔ)知識(shí)-文檔、集合、數(shù)據(jù)庫(kù)、客戶端下一篇文章:MongoDB指南---4、MongoDB基礎(chǔ)知識(shí)-使用M...

    aervon 評(píng)論0 收藏0
  • MongoDB指南---3、MongoDB基礎(chǔ)知識(shí)-數(shù)據(jù)

    摘要:如將構(gòu)造函數(shù)作為函數(shù)進(jìn)行調(diào)用即不包括的方式,返回的是日期的字符串表示,而非日期對(duì)象。如果不注意這一點(diǎn),沒(méi)有始終使用日期構(gòu)造函數(shù),將得到一堆混亂的日期對(duì)象和日期的字符串。關(guān)于日期類的完整解釋,以及構(gòu)造函數(shù)的參數(shù)格式,參見(jiàn)規(guī)范節(jié)。 上一篇文章:MongoDB指南---2、MongoDB基礎(chǔ)知識(shí)-文檔、集合、數(shù)據(jù)庫(kù)、客戶端下一篇文章:MongoDB指南---4、MongoDB基礎(chǔ)知識(shí)-使用M...

    tunny 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<