lodash原始碼分析之自減的兩種形式

對角發表於2018-01-08

這個世界需要一個特定的惡人,可以供人們指名道姓,千夫所指:“全都怪你”。

——村上春樹《當我談跑步時我談些什麼》

本文為讀 lodash 原始碼的第六篇,後續文章會更新到這個倉庫中,歡迎 star:pocket-lodash

gitbook也會同步倉庫的更新,gitbook地址:pocket-lodash

本篇分析的是 assocIndexOf 函式。

作用與用法

assocIndexOf 是 lodash 的內部函式,之前在《lodash原始碼分析之Hash快取》介紹過一種這樣的資料結構:

var caches = [['test1', 1],['test2',2],['test3',3]]
複製程式碼

這是一個二維陣列,每項中的第一項作為快取物件的 key,第二項為快取的值。

assocIndexOf 的作用是找出指定的 key 在陣列中的索引值。

例如要找 keytes1 的索引 :

assocIndexOf(caches, 'test1') // 0
複製程式碼

依賴

import eq from '../eq.js'
複製程式碼

lodash原始碼分析之NaN不是NaN

原始碼分析

function assocIndexOf(array, key) {
  let { length } = array
  while (length--) {
    if (eq(array[length][0], key)) {
      return length
    }
  }
  return -1
}
複製程式碼

這段程式碼很精簡,讓 length 自減,呼叫 eq 函式,從二維陣列的最後一項開始,逐項獲取 key 值,與傳入的 key 比較,遇到匹配的,馬上將該項的索引返回。如果都沒找到,返回 -1 。返回結果的規則與 indexOf 一致。

length--和--length

我們都知道自減還有另外一種前置的形式,即 --length,那將上面的程式碼改成 while(--length) 可不可以呢?試一下就知道了。

改了之後,用 caches 來測試下:

assocIndexOf(caches, 'test3') // 2
assocIndexOf(caches, 'test2') // 1
assocIndexOf(caches, 'test1') // -1
複製程式碼

可以看到,改了之後,隻影響到了第一項的結果,也就是終止條件有問題,根本沒有遍歷到第一項,但是後面的結果是正確的,也就說迴圈體裡的 length 沒有受到影響。

你可能會有點疑惑,while 的終止條件比較的不是 length 嗎?為什麼 length-- 正確,而 --length 不正確呢?

其實 while 的終止條件並不是 length ,而是 length-- 表示式所返回的結果。現在來看一下 length----length 所返回的結果有什麼差別。

var length = 3
length-- // 3
length // 2
複製程式碼

可以看到, length-- 返回的結果和自減前的一致,但是 length 已經減少 1 了。因此使用 length-- ,最後一次進入迴圈體應該在 length 等於 1 的時候。

再來看 --length

var length = 3
--length // 2
length // 2
複製程式碼

--length 返回的結果跟自減後的結果一致,因此最後一次進入迴圈體應該是 length2 的時候,因此如果換成這種形式,會漏掉一次迴圈。

參考

  1. 程式碼之謎(二)- 語句與表示式

License

署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)

最後,所有文章都會同步傳送到微信公眾號上,歡迎關注,歡迎提意見:

lodash原始碼分析之自減的兩種形式

作者:對角另一面

相關文章