一篇文章搞定数组迭代方法(含ES3实现原理)!

221 阅读2分钟

[TOC]

数组迭代方法

一.介绍

1.forEach(让数组中的每一项做一件事)

不改变原数组
没有返回值
let arr = [1, 2, 3, 4, 5];
arr.forEach((item, index) => {
	console.log(item);
})

image-20210903110730908

2.map(让数组通过某种计算产生一个新数组)

不改变原数组
返回每一项处理后所组成的新数组
let newArr = arr.map(item => {
	return item * 2;
})
console.log(newArr); // [2, 4, 6, 8, 10]

image-20210903110534489

3.filter(筛选出数组中符合条件的项,组成新数组)

不改变原数组
返回符合条件的新数组
var newArray = [1, 2, 3].filter((item, index, arr) => {
  console.log(item, index, arr) 
  return item > 2
})
console.log(newArray); // [3]


var newArray = [1, 2, 3].filter((item, index, arr) => {
  console.log(item, index, arr) 
  return item > 2
})
console.log(newArray); // [3]

image-20210903101739030

4.every(检测数组是否每一项都符合条件)

不改变原数组
返回布尔值
let result = arr.every((item, index) => {
	return item > 3;
})
console.log(result); // false

image-20210903111343192

5.some(检测数组是否有任一项符合条件)

不改变原数组
返回布尔值
let result = arr.some((item, index) => {
	return item > 3;
})
console.log(result); // true

image-20210903111444969

二.ES3实现

1.forEach

Array.prototype.forEach = function(callback, thisArg) {
  if (this == null) {
    throw new TypeError('this is null or not defined');
  }
  if (typeof callback !== "function") {
    throw new TypeError(callback + ' is not a function');
  }
  var O = Object(this);
  var len = O.length >>> 0;  // 无符号右移 向右移0位,
  // 移0位的意义:移位操作符在移位前做了两种转换,第一将不是number类型的数据转换为number,
  // 第二将number转换为无符号的32bit数据,也就是Uint32类型。
  // Uint32类型是如何转换的
  // 1 . 如果不能转换为Number,那就为0
  // 2 . 如果为非整数,先转换为整数,参考公式sign(n) ⋅ floor(abs(n))
  // 3 . 如果是正数,返回正数,如果是负数,返回负数 + 2的32次方
  var k = 0;
  while (k < len) {
    if (k in O) {
      callback.call(thisArg, O[k], k, O);
    }
    k++;
  }
}

2.map

Array.prototype.map = function(callback, thisArg) {
  if (this == undefined) {
    throw new TypeError('this is null or not defined');
  }
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }
  var res = [];
  var O = Object(this);
  var len = O.length >>> 0;
  for (var i = 0; i < len; i++) {
    if (i in O) {
      // 调用回调函数并传入新数组
      res[i] = callback.call(thisArg, O[i], i, this);
    }
  }
  return res;
}

3.filter

Array.prototype.filter = function(callback, thisArg) {
  if (this == undefined) {
    throw new TypeError('this is null or not undefined');
  }
  if (typeof callback !== 'function') {
    throw new TypeError(callback + 'is not a function');
  }
  var res = [];
  // 让O成为回调函数的对象传递(强制转换对象)
  var O = Object(this);
  // >>> 0 保证len为number,且为正整数
  var len = O.length >>> 0;
  for (var i = 0; i < len; i++) {
    // 检查i是否在O的属性(会检查原型链)
    if (i in O) {
      // 回调函数调用传参
      if (callback.call(thisArg, O[i], i, O)) {
        res.push(O[i]);
      }
    }
  }
  return res;
}

4.every

Array.prototype.every = function (callback) {  //如果没有传入回调函数,则报错  if (!callback) throw new TypeError("undefined is not a function");  if (typeof callback !== "function") {    //传入的不是函数也报错    throw new TypeError(callback + " is not a function");  }  for (var i = 0, len = this.length; i < len; i++) {    if (!callback(this[i], i, this)) {      //如果回调函数的返回值为false ,则终止循环,返回false      return false;    }  }  return true; //最终没有匹配到就返回true};

5.some

Array.prototype.some = function (callback) {  if (this == undefined) {    throw new TypeError("this is null or not defined");  }  if (typeof callback !== "function") {    throw new TypeError(callback + " is not a function");  }       var O = Object(this);  var len = O.length >>> 0;  for (var i = 0; i < len; i++) {    if (callback(O[i])) {     // 一旦有一个callback返回的是true,将返回true  	  return true;    }  }  return false;};

数组归并方法

一.介绍

1.reduce(让数组前项和后项做某种计算--从前往后)

不改变原数组
返回计算完成的结果
let arr = [6, 0, 2, 9, 3];let result = arr.reduce((current, next) => {	return current + next * 2;})console.log(result); // 29// current + next * 2   => result//	  1    +   2 * 2    => 5//	  5    +   3 * 2    => 11//	 11    +   4 * 2    => 19//	 19    +   5 * 2    => 29

image-20210903111922213

2.reduceRight (从后往前)

let arr = [6, 0, 2, 9, 3];let result = arr.reduceRight((current, next) => {  console.log('当前数为'+current+'下一个数为'+next)  return current + next * 2;});console.log(result); // 37// current + next * 2   => result//	  3    +   9 * 2    => 21//	  21    +   2 * 2    => 25//	  25    +   0 * 2    => 25//	  25    +   6 * 2    => 37

image-20210903112004950

二.ES3实现

1.reduce

Array.prototype.myReduce = function (callback) {  if (this == undefined) {    throw new TypeError("this is null or not defined");  }  if (typeof callback !== "function") {    throw new TypeError(callback + " is not a function");  }  var O = Object(this);  var len = O.length >>> 0;  var result = O[0];   // 初始化时result(当前项)为数组第一项  for (var i = 0; i + 1 < len; i++) {    result = callback(result, O[i + 1]);  }  return result;};

2.reduceRight

Array.prototype.myReduceRight = function (callback) {  if (this == undefined) {    throw new TypeError("this is null or not defined");  }  if (typeof callback !== "function") {    throw new TypeError(callback + " is not a function");  }  var O = Object(this);  var len = O.length >>> 0;  var result = O[len - 1];  for (var i = len - 1; i - 1 >= 0; i--) {    result = callback(result, O[i - 1]);  }  return result;};

参考链接:juejin.im/post/687515…