前段我们写了个油猴脚本:[例] 简单脚本提取页面中所有图片地址 (实现, 改进, 实战), 里面需要将 DOM 节点列表转化成数组, 今天我们来讨论一下将 DOM 节点列表转化为数组的几种方式.
for 循环
循环是最直观, 也是最可靠的, 因为所有浏览器都支持 for 循环. 但它有许多的变种:
- // nl 变量为 DOM NodeList 的简写
- // arr 变量为 nl 将要转化成的数组
- // 方式 1
- var arr = [];
- for(var i = 0, n; n = nl[i]; ++i) arr.push(n);
- // 方式 2
- var arr = []; // Will hold the array of Node's
- for(var i = 0, ll = nl.length; i != ll; arr.push(nl[i++]));
- // 方式 3
- var arr = [];
- for(var i = nl.length; i--; arr.unshift(nl[i]));
- // 方式 4
- var arr = [];
- for(var i=-1,l=nl.length;++i!==l;arr[i]=nl[i]);
Array.prototype.slice.call 方式
在 javascrtipt 中, call() 和 apply() 可以用来重新定义函数的执行环境. 它们的第一个参数是要调用函数的母对象, 它是调用上下文, 在函数体内通过 this 来获得对它的引用. 如要想以对象 o 的来调用函数 f(), 可以这样:
- f.call(o);
- f.apply(o);
达到以下的效果:
- o.m=f;
- o.m();
- delete o.m;
所以 Array.prototype.slice.call(NodeList), 相当于 NodeList.slice(); 而得到一个于 NodeList 等长同项的数组对象.
原型增加 forEach 函数方式
在大多数场景下, 将 DOM 节点列表转换成数组, 无非是想用数组的隐式迭代的方法. 可以经 NodeList 原型上直接实现 forEach 方法.
NodeList.prototype.forEach = Array.prototype.forEach;
Array.from() 方式
回看 Array.prototype.slice.call 这种方式, 因为不需要显示的写循环, 一直被当成一种高级用法广泛使用. 但是我们在调用它时不能直观的感受到是在 "将 arrayLike 转换成一个数组".
ES 6 为了增加语义的清晰, 语法的简洁性. 添加了一个新方法 Array.from(), 用于将 arrayLike 的对象转换成数组. 所以:
var arr = Array.from(nl)
数组 / 对象扩展运算符 ...
扩展运算符用三个点号表示, 功能是把数组或类数组对象展开成一系列用逗号隔开的值. 详细请参考:(...) 这三个点在 JavaScript 中是个啥意思?
let arr = [...nl];
思考
这些方法中, 有些是各浏览器通用的, 有些高级浏览器适用的, 那么哪种方式哪个浏览器性能高些, 我们将做一个性能对比测试, 请持续关注!
来源: http://www.mzh.ren/ways-to-convert-javascript-nodelist-to-array.html