javascript 类数组对象
参考自: https://github.com/justjavac/12-javascript-quirks/blob/master/cn/8-array-like-objects.md
简单来说: 具有length属性并且可以通过数字下标方式访问属性的对象就是类数组对象, 它不一定具有数组的方法( 你可以用 Object.getOwnPropertyNames(Array.prototype) 来看一个对象默认有哪些方法 ).
<<>javascript权威指南>> 中判断类数组对象的一个方法:
// Determine if o is an array-like object. // Strings and functions have numeric length properties, but are // excluded by the typeof test. In client-side JavaScript, DOM text // nodes have a numeric length property, and may need to be excluded // with an additional o.nodeType != 3 (text node type) test. function isArrayLike(o) { if (o && // o is not null, undefined, etc. typeof o === 'object' && // o is an object isFinite(o.length) && // o.length is a finite number o.length >= 0 && // o.length is non-negative o.length===Math.floor(o.length) && // o.length is an integer o.length < 4294967296) // o.length < 2^32 return true; // Then o is array-like else return false; // Otherwise it is not }
哪里会用常到类数组对象:
1. arguments 就是类数组对象
2. DOM( 用来操作XML,HTML的API ) 操作的返回值(i.e. document.getElementsByClassName() ) 通常就是类数组对象
怎么创建一个类数组对象? 在这个之前先要了解方法借用.
方法借用: 每个函数 myfunc 都有一个 call 的属性(也是一个函数), 可以从下面打印出 Function.prototype 的所有属性来看:
console.log(Object.getOwnPropertyNames(Function.prototype)); //["length", "name", "arguments", "caller", "constructor", "bind", "toString", "call", "apply"]
fun.call(thisArg[, arg1[, arg2[, ...]]]) 中有一个thisArg 让你自己选择调用这个myfunc 的对象(this), 这样就能把 myfunc "借" 出去. 那么其他对象如果能用这个方法, 就可以借来用. ----- 这样 myfyunc 就变成了一个通用方法.
所以你可以这样使用:
var o = { name : "roger", age : 21 } function f(){ for(var p in this){ console.log(o[p]); } } f.call(o);
f 是一个普通的方法, 但是可以把它当成对象 o 的方法来使用. 当然 如果 f 是其他某个对象的方法也没问题( 如: Array.prototype.slice() )
好了, 这样我们就可以从一个对象开始创建类数组对象 --- 只要让它变得有 length 属性 和 可以数字下标访问即可:
var obj = {}; // 首先创建一个对象 Array.prototype.push.call(obj,'a','b'); // 借用数组的方法往对象里面添加元素
这样我们就将 obj 变成了一个类数组对象, 输出 obj 可以看到: Object {0: "a", 1: "b", length: 2} , 添加元素时, 自动创建了数字下标 和 length属性(自动初始化为0 并自动管理).
但是记住这个obj 仍然是一个对象, 它没有实现数组的其他方法, 使用 Array,isArray(obj) 会得到 false , 很多情况下这样够我们用了!
不过, 如果你觉得数组的其他操作也是需要的, 那么, 你可以进一步将 obj 转化为数组: obj = Array.prototype.slice.call(obj); 这样, Array,isArray(obj) 就得到 true 了!