類數組的定義是什麼?

by @zhangbao(zhangbao) #0105javascript

概覽

什麼是類數組呢?查看 Lodash _.isArrayLike(value) 函數的實現,得知參數 value 須符合下列條件:java

  1. 不是函數
  2. length 屬性
  3. length 屬性值是不大於 Number.MAX_SAFE_INTEGER 的天然數

字符串就符合這個條件,說明它就是類數組。git

carbon.png

Lodash 的實現

著名 JS 工具庫 Lodash 提供了一個工具函數:_.isArrayLike(value),檢查某個值是否爲類數組的。下面是官方給的用例:github

_.isArrayLike([1, 2, 3]);
// => true
 
_.isArrayLike(document.body.children);
// => true
 
_.isArrayLike('abc');
// => true
 
_.isArrayLike(_.noop);
// => false
複製代碼

我悄悄的看了看實現的源碼(這裏這裏)。算法

_.isArrayLike 的實現細節

isArrayLike

下面是定義函數 isArrayLike 的地方:數組

import isLength from './isLength.js'

function isArrayLike(value) {
  return value != null && typeof value !== 'function' && isLength(value.length)
}
複製代碼

首先檢查輸入的值:函數

  1. value != null:這個判斷使用的是 !=,而非 !==。令判斷結果爲 false 的值有兩個:nullundefined。就是說,若是向 isArrayLike 函數傳入的值是 nullundefined,那麼第一個判斷都未知足,直接返回 false

💡 提示: 這裏引入了 JS 一個小怪癖的地方,就是規範中定義對於抽象相等算法( == 內部執行的就是此算法):null == undefined 比較結果返回 true,天然 null != undefined 的返回結果爲 false工具

  1. typeof value !== 'function':傳入值不能是函數,若是函數的話,也不算是類數組。
  2. isLength(value.length):最後檢查傳入值的 length 屬性,isLength(value.length) 返回值即 isArrayLike 的返回值。

isLength

isLength 函數是用來幹什麼的?咱們來看下:oop

const MAX_SAFE_INTEGER = 9007199254740991

/** * Checks if `value` is a valid array-like length. * * **Note:** This method is loosely based on * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * ... * */
function isLength(value) {
  return typeof value === 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER
}
複製代碼

根據註釋,咱們知道 isLength 函數是用來檢查傳入值 value 是否爲有效長度。這裏的 MAX_SAFE_INTEGER 就等於 Number.MAX_SAFE_INTEGER 的值,這樣寫的目的估計是爲了效率,能少一步計算。ui

根據判斷邏輯,咱們知道所謂「有效的長度值」,是指值不大於 Number.MAX_SAFE_INTEGER 的天然數。

好比如下這些值,就不能算是有效的長度值:

isLength(Number.MIN_VALUE)
// => false。負數不是

isLength(Infinity)
// => false。無窮大不是

isLength('3')
// => false。字符串也不是
複製代碼

額外說明

根據 isLength 方法的註釋說明:此種驗證方式是對規範中定義的抽象算法 ToLength 的寬鬆實現。下面是規範中的定義:

image.png

相較於規範中的定義,後者是包含類型轉換和參數值糾正邏輯的:

  1. 類型轉換:首先將參數轉爲整數(ToInteger(argument)
    2. 參數糾正:負值轉爲 +0;無窮大轉爲 253 - 1 等。

而這在 Lodash 中的實現中是沒有的,這就是爲何稱之爲「寬鬆實現」的緣由。

參考連接

(完)

相關文章
相關標籤/搜索