billfeller.github.io
billfeller.github.io copied to clipboard
JS遍历数组的3种不同实现与比较
实现说明
JS遍历数据有3中不同实现:
- Loop: for
- Map: array.prototype.map
- forEach: array.prototype.forEach
示例:
source: https://jsperf.com/loop-vs-map-vs-foreach
可以看到,for 实现最快,map,forEach有一定的性能损耗;但是,map,forEach 代码较 for 简洁;
map与forEach区别
首先看下MDN对于二者的定义:
The map() method creates a new array with the results of calling a provided function on every element in the calling array. var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg])
The forEach() method executes a provided function once for each array element. arr.forEach(function callback(currentValue[, index[, array]]) { //your iterator }[, thisArg]);
可以看到,二者的区别在于map()返回新数组,而forEach()返回undefined。
比较二者的 Array.prototype.forEach 与 Array.prototype.map polyfill源码实现:
// 实现 ECMA-262, Edition 5, 15.4.4.18
// 参考: http://es5.github.io/#x15.4.4.18
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback, thisArg) {
var T, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
// 1. 将O赋值为调用map方法的数组.
var O = Object(this);
// 2.将len赋值为数组O的长度.
var len = O.length >>> 0;
// 3.如果callback不是函数,则抛出TypeError异常.
// See: http://es5.github.com/#x9.11
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
// 4. 如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 5. 将k赋值为0
k = 0;
// 6. 当 k < len 时,执行循环.
while (k < len) {
var kValue;
//遍历O,k为原数组索引
if (k in O) {
//kValue为索引k对应的值.
kValue = O[k];
// 执行callback,this指向T,参数有三个.分别是kValue:值,k:索引,O:原数组.
callback.call(T, kValue, k, O);
}
// k自增1
k++;
}
// 7. 返回undefined
};
}
// 实现 ECMA-262, Edition 5, 15.4.4.19
// 参考: http://es5.github.com/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. 将O赋值为调用map方法的数组.
var O = Object(this);
// 2.将len赋值为数组O的长度.
var len = O.length >>> 0;
// 3.如果callback不是函数,则抛出TypeError异常.
if (Object.prototype.toString.call(callback) != "[object Function]") {
throw new TypeError(callback + " is not a function");
}
// 4. 如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined.
if (thisArg) {
T = thisArg;
}
// 5. 创建新数组A,长度为原数组O长度len
A = new Array(len);
// 6. 将k赋值为0
k = 0;
// 7. 当 k < len 时,执行循环.
while(k < len) {
var kValue, mappedValue;
//遍历O,k为原数组索引
if (k in O) {
//kValue为索引k对应的值.
kValue = O[ k ];
// 执行callback,this指向T,参数有三个.分别是kValue:值,k:索引,O:原数组.
mappedValue = callback.call(T, kValue, k, O);
// 返回值添加到新数组A中.
A[ k ] = mappedValue;
}
// k自增1
k++;
}
// 8. 返回新数组A
return A;
};
}