JS内部是如何实现Array的length属性的?

貌似判断数组可以用arr.length === + arr.length,所以想了解一下js内部length的实现

阅读 10.6k
6 个回答

arr.length === + arr.length的确是一种鸭式辨型的判断方法。
这句话包含两层意思:
1. arrlength这个属性
2. arr.length是一个Number(可以试一下x === +x)

鸭式辨型的经典假设:只要是会游泳的鸟类,不管它是什么,我都把它当成鸭子。
鸭式辨型在楼主例子中的假设:只要arrlength这个属性,且它是个Number,我都把arr当成是数组。

这种鸭式辨型的判定方法,要看你的具体需求!!比如你并不在乎其他事,只关心要使用的这个变量必须满足上面的两个条件,就可以这么判断。

var arr = "123";
var arr2 = [1,2,3];
arr.length === + arr.length; //true
arr2.length === + arr2.length; //true

因为字符串有length这个属性,且它的length是个Number。所以如果你用了arr.length === + arr.length;来判断数组,字符串也满足这样的条件。如果在你的开发场景中,只关心这两个条件,当然就没问题。如果你要求必须是个数组,就不能用这种鸭式辨型的方法来判断了。

据说jQuery中要判断一个变量是否是一个数组的确切方法是:

Object.prototype.toString.call(arr)==='[object Array]'

关于鸭式辨型更多的了解,可以参考《javascript权威指南》中的描述

关于js内部是如何实现Array的length的。我想楼主可以参考MDN的文档:《Array.length

为啥不用arr instanceof Array 来判断是否是数组呢

主流的库使用的判断方法是Object.prototype.toString.call(arr) === '[object Array]';
ES5以上环节可以用Array.isArray(arr)这样

至于LZ标题里所说的“怎么实现的”,我认为有两种办法
1. 引擎通过native实现
2. 通过Object.defineProperty定义它的getter/setter函数内维护这个属性

判断数组可以用 arr.length === + arr.length

不知道你從哪看(聽)來的,很遺憾,這是不對的, 比如:

(function(a,b,c){}).length === + '345'.lengthtrue

其實,該判斷還需要前提: typeof arr === typeof []. 另外還考慮到 arguments 這個奇葩的存在(感謝 @mcfog 提醒), 需要另外加上 !arr.callee 的判斷. 所以完整的是:

typeof arr === typeof [] && !arr.callee && arr.length === + arr.length


為什麼?因為對 Object 或者 Arraytypeof 運算得到的值都是 "object", 造成了混淆。

但是這兩者還是有區別的,體現在 Arraylength 屬性而 Object 沒有.

+ arr.length 等價于 0 + arr.length, 如果 arr 不是數組,那麼 arr.length 就是 undefined, 嘗試把 undefined 轉換為數字就會得到 NaN, 顯然 undefined !== NaN, 即可知 arrObject.


Ps. 這跟內部實現沒有關係。

想了解一下js内部length的实现

关于array的判断,angularJS是这样做的

Object.prototype.toString.call(arr) === '[object Array]'
推荐问题
宣传栏