貌似判断数组可以用arr.length === + arr.length,所以想了解一下js内部length的实现
认证高级PHP讲师
arr.length === + arr.length的确是一种鸭式辨型的判断方法。 这句话包含两层意思: 1. arr有length这个属性 2. arr.length是一个Number(可以试一下x === +x)
arr.length === + arr.length
arr
length
arr.length
Number
x === +x
鸭式辨型的经典假设:只要是会游泳的鸟类,不管它是什么,我都把它当成鸭子。 鸭式辨型在楼主例子中的假设:只要arr有length这个属性,且它是个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;来判断数组,字符串也满足这样的条件。如果在你的开发场景中,只关心这两个条件,当然就没问题。如果你要求必须是个数组,就不能用这种鸭式辨型的方法来判断了。
arr.length === + arr.length;
据说jQuery中要判断一个变量是否是一个数组的确切方法是:
Object.prototype.toString.call(arr)==='[object Array]'
关于鸭式辨型更多的了解,可以参考《javascript权威指南》中的描述
关于js内部是如何实现Array的length的。我想楼主可以参考MDN的文档:《Array.length》
为啥不用arr instanceof Array 来判断是否是数组呢
arr instanceof Array
判断数组可以用 arr.length === + arr.length
不知道你從哪看(聽)來的,很遺憾,這是不對的, 比如:
(function(a,b,c){}).length === + '345'.length 為 true
(function(a,b,c){}).length === + '345'.length
其實,該判斷還需要前提: typeof arr === typeof []. 另外還考慮到 arguments 這個奇葩的存在(感謝 @mcfog 提醒), 需要另外加上 !arr.callee 的判斷. 所以完整的是:
typeof arr === typeof []
arguments
!arr.callee
typeof arr === typeof [] && !arr.callee && arr.length === + arr.length
為什麼?因為對 Object 或者 Array 作 typeof 運算得到的值都是 "object", 造成了混淆。
typeof
"object"
但是這兩者還是有區別的,體現在 Array 有 length 屬性而 Object 沒有.
+ arr.length 等價于 0 + arr.length, 如果 arr 不是數組,那麼 arr.length 就是 undefined, 嘗試把 undefined 轉換為數字就會得到 NaN, 顯然 undefined !== NaN, 即可知 arr 為 Object.
+ arr.length
0 + arr.length
undefined
NaN
undefined !== NaN
Ps. 這跟內部實現沒有關係。
想了解一下js内部length的实现
关于array的判断,angularJS是这样做的
Object.prototype.toString.call(arr) === '[object Array]'
主流的库使用的判断方法是Object.prototype.toString.call(arr) === '[object Array]'; ES5以上环节可以用Array.isArray(arr)这样
Object.prototype.toString.call(arr) === '[object Array]';
Array.isArray(arr)
至于LZ标题里所说的“怎么实现的”,我认为有两种办法 1. 引擎通过native实现 2. 通过Object.defineProperty定义它的getter/setter函数内维护这个属性
Object.defineProperty
占楼。我不说话。
arr.length === + arr.length
的确是一种鸭式辨型的判断方法。这句话包含两层意思:
1.
arr
有length
这个属性2.
arr.length
是一个Number
(可以试一下x === +x
)鸭式辨型的经典假设:只要是会游泳的鸟类,不管它是什么,我都把它当成鸭子。
鸭式辨型在楼主例子中的假设:只要
arr
有length
这个属性,且它是个Number
,我都把arr
当成是数组。这种鸭式辨型的判定方法,要看你的具体需求!!比如你并不在乎其他事,只关心要使用的这个变量必须满足上面的两个条件,就可以这么判断。
因为字符串有
length
这个属性,且它的length
是个Number
。所以如果你用了arr.length === + arr.length;
来判断数组,字符串也满足这样的条件。如果在你的开发场景中,只关心这两个条件,当然就没问题。如果你要求必须是个数组,就不能用这种鸭式辨型的方法来判断了。据说jQuery中要判断一个变量是否是一个数组的确切方法是:
关于鸭式辨型更多的了解,可以参考《javascript权威指南》中的描述
关于js内部是如何实现Array的length的。我想楼主可以参考MDN的文档:《Array.length》
为啥不用
arr instanceof Array
来判断是否是数组呢不知道你從哪看(聽)來的,很遺憾,這是不對的, 比如:
(function(a,b,c){}).length === + '345'.length
為 true其實,該判斷還需要前提:
typeof arr === typeof []
. 另外還考慮到arguments
這個奇葩的存在(感謝 @mcfog 提醒), 需要另外加上!arr.callee
的判斷. 所以完整的是:typeof arr === typeof [] && !arr.callee && arr.length === + arr.length
為什麼?因為對 Object 或者 Array 作
typeof
運算得到的值都是"object"
, 造成了混淆。但是這兩者還是有區別的,體現在 Array 有
length
屬性而 Object 沒有.+ arr.length
等價于0 + arr.length
, 如果arr
不是數組,那麼arr.length
就是undefined
, 嘗試把undefined
轉換為數字就會得到NaN
, 顯然undefined !== NaN
, 即可知arr
為 Object.Ps. 這跟內部實現沒有關係。
关于array的判断,angularJS是这样做的
主流的库使用的判断方法是
Object.prototype.toString.call(arr) === '[object Array]';
ES5以上环节可以用
Array.isArray(arr)
这样至于LZ标题里所说的“怎么实现的”,我认为有两种办法
1. 引擎通过native实现
2. 通过
Object.defineProperty
定义它的getter/setter函数内维护这个属性占楼。我不说话。