JavaScript的迭代函数与迭代函数的实现

Image result for JavaScript 迭代

前言

若是对技比较自信,请直接看实现的源码javascript

若是想回顾一下基础,请按文章顺序阅读前端


说到迭代方法,最早想到的是什么?forEach仍是map,迭代的方法ES5提供了5种方法java

如下定义来自 JavaScript高级程序设计windows

每一个方法都接收两个参数数组

  1. 在每一项上运行的函数
  2. 运行该函数的做用域对象(影响this的值)

传入这些方法中的函数会接收3个参数框架

  1. 数组项的值
  2. 该项在数组的位置
  3. 数组对象自己

迭代函数执行后可能会可能不会影响返回结果 (雾..)函数

ES5提供的迭代函数工具

  • forEach(): 对数组中的每一项运行给定函数,无返回值
  • every(): 对数组中的每一项运行给定函数,若是该函数每一项都返回true,则返回true
  • some(): 对数组中的每一项运行给定函数,若是该函数任意一项返回true,则返回true
  • map(): 对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
  • filter(): 对数组中的每一项运行给定函数,该函数会返回true的项组成的数组

参数说明

let array = [1,2,3,4,5,6,7,8,9]
array.forEach((element,index,array) => {
  console.log(`当前遍历元素${element}`);
  console.log(`当前元素位置${index}`);
  console.log(`数组自己${array}`);
})
> 当前遍历元素1
> 当前元素位置0
> 数组自己1,2,3,4,5,6,7,8,9
> 当前遍历元素2
> 当前元素位置1
> 数组自己1,2,3,4,5,6,7,8,9
> 当前遍历元素3
> 当前元素位置2
> 数组自己1,2,3,4,5,6,7,8,9
复制代码

forEach能够说是最经常使用的一个迭代方法了,该方法没有返回值,与for循环的效果同样学习

forEach的第二个参数,js高程上说明 是运行该函数的做用域对象,能够看一下经典的例子ui

let obj2 = {
  name: '张三',
  times:[1,2,3],
  print:function () {
    this.times.forEach(function(res) {
      console.log(this.name);
    },this)
  }
}
// 迭代函数内部的function默认指向windows 第二个参数调整了this指向
obj2.print()
// 张三
// 张三
// 张三
复制代码

若是这么写看不太懂的话,看箭头函数的写法一会儿就能明白

let obj2 = {
  name: '张三',
  times:[1,2,3],
  print:function () {
    this.times.forEach(res => {
      console.log(name);
    })
  }
}
// 箭头函数this指向父级,因此他不须要调整this
obj2.print()
// 张三
// 张三
// 张三
复制代码

every(判断函数)

对数组中的每一项运行给定函数,若是该函数每一项都返回true,则返回true

默认返回false

var array = [1,2,3,4,5,6,7,8,9]
var result = array.every(e => {})
console.log(result); // 
> false 
复制代码

所有ture才会返回true

var array = [1,2,3,4,5,6,7,8,9]
var result = array.every(e => {
  return e > 0
})
console.log(result);
> true

var array = [1,2,3,4,5,6,7,8,9]
var result = array.every(e => {
  return e > 1
})
console.log(result);
> false
复制代码

some(判断函数)

对数组中的每一项运行给定函数,若是该函数任意一项返回true,则返回true

默认返回false

var array = [1,2,3,4,5,6,7,8,9]
var result = array.some(e => {})
console.log(result); // 
> false 
复制代码

所有false才会返回false

var array = [1,2,3,4,5,6,7,8,9]
var result = array.some(e => {
  return e > 8
})
console.log(result);

var array = [1,2,3,4,5,6,7,8,9]
var result = array.some(e => {
  return e > 9
})
console.log(result);
> false
复制代码

以上两个都不是很经常使用,可是毫无疑问在特定的需求下,这个要比用forEach代码要简洁不少

filter(过滤函数)

对数组中的每一项运行给定函数,该函数会返回true的项组成的数组

var array = [1,2,3,4,5,6,7,8,9]
var result = array.filter(e => {
  return e>5
})
console.log(result);
> [6, 7, 8, 9]
复制代码

上面的例子,array数组里面大于5的数会被过滤出来,filter函数在平常当中比较经常使用

map(处理函数)

对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组

var array = [1,2,3,4,5,6,7,8,9]
var result = array.map(e => {
  return e>5
})
console.log(result);
> [false, false, false, false, false, true, true, true, true]

var array = [1,2,3,4,5,6,7,8,9]
var result = array.map(e => {
  return e*2
})
console.log(result);
> [2, 4, 6, 8, 10, 12, 14, 16, 18]
复制代码

forEach(迭代函数)

对数组中的每一项运行给定函数,无返回值

var array = [1,2,3,4,5,6,7,8,9]
var arraypush = []
var result = array.forEach(e => {
  if (e > 5) {
    arraypush.push(e)
  }
})
console.log(arraypush);
> [6, 7, 8, 9]
复制代码

最纯粹的迭代函数,彷佛forEach是处理外部数组最好的选择

到这里,我想起了我第一次使用filter函数的时候,我惊呆了,这函数太强大了!

如此好用的工具函数,不本身实现一遍怎么能作到彻底了解

如下函数为本身实现的,并非源码,如有错误请指点!

实现forEach

首先明显forEach是Array上的原型链上的函数因此第一件事就是建立一个原型方法

Array.prototype.MyforEach = function (){}
复制代码

forEact 第一个参数为一个匿名函数 第二个参数为this指向 因此

Array.prototype.MyforEach = function (fn,obj){}
复制代码

forEach会迭代调用它的数组因此内部确定是循环

Array.prototype.MyforEach = function (fn,obj){
  let len = this.length
  for (let index = 0; index < len; index++) {
    fn(this[index],index,this)
  }
}
复制代码

可是咱们尚未考虑this指向的事情,因此还须要添加一些调整this的代码

Array.prototype.MyforEach = function (fn,obj){
  let len = this.length
  if (obj != undefined) {
    fn = fn.bind(obj)
  }
  for (let index = 0; index < len; index++) {
    fn(this[index],index,this)
  }
}
复制代码

运行一下试试,就用以前的例子

var array = [1,2,3,4,5,6,7,8,9]
Array.prototype.MyforEach = function (fn,obj){
  let len = this.length
  if (obj != undefined) {
    fn = fn.bind(obj)
  }
  for (let index = 0; index < len; index++) {
    fn(this[index],index,this)
  }
}

var obj2 = {
  name: '张三',
  times:[1,2,3],
  print:function () {
    this.times.MyforEach(function(res) {
      console.log(this.name);
    },this)
  }
}
obj2.print()
> 张三
> 张三
> 张三
复制代码

实现map

map与forEach的区别是

  1. map中若是是运算,会返回每次函数调用的新的结果组成的数组
  2. map中若是是判断,会返回每次迭代结果组成的数组

因此只要在迭代函数内部建立一个数组,每次迭代都push进去,最后返回出去就好啦

Array.prototype.Mymap = function (fn,obj){
  var resultData = []
  var len = this.length
  if (obj != undefined) {
    fn = fn.bind(obj)
  }
  for (let index = 0; index < len; index++) {
    resultData.push(fn(this[index],index,this))
  }
  return resultData
}
复制代码

运行一下

var array = [1,2,3,4,5,6,7,8,9,]
var result = array.Mymap(e => {
    return e*2
})
console.log(result);
> [2, 4, 6, 8, 10, 12, 14, 16, 18]
复制代码

实现 some every

some与every都会有一个特色 默认返回false

不一样的地方在于

some要求 所有返回false返回false

every要求 所有返回true返回true

// -- every -- 
Array.prototype.Myevery = function (fn,obj) {
  var len = this.length
  if (obj != undefined) {
    fn = fn.bind(obj)
  }
  for (let index = 0; index < len; index++) {
    if (fn(this[index],index,this) == undefined) { // 无返回值 默认返回false
      return false
    }else if (fn(this[index],index,this) !== true) { // 出现一个不为 true 就中止迭代 返回结果
      return false
    }
  }
  return true
}

// -- some -- 
Array.prototype.Mysome = function (fn,obj) {
  var len = this.length
  if (obj != undefined) {
    fn = fn.bind(obj)
  }
  for (let index = 0; index < len; index++) {
    if (fn(this[index],index,this) == undefined) {
      return false
    } else if (fn(this[index],index,this) !== false) {
      return true
    }
  }
  return false
}
复制代码

实现fliter

相信到这里,你也能够直接实现一个fliter函数了,仅仅是多添加一个数组

Array.prototype.Myfilter = function (fn, obj) {
  let resultData = []
  var len = this.length
  if (obj != undefined) {
    fn = fn.bind(obj)
  }
  for (let index = 0; index < len; index++) {
    if (fn(this[index],index,this)) { // 返回true则进行处理
      resultData.push(this[index]) // 注意不是push函数结果
    }
  }
  return resultData
}

// -- 运行 -- 

var array = [1,2,3,4,5,6,7,8,9]
var result = array.Myfilter(e => {
  return e>5
})
console.log(result);
>  [6, 7, 8, 9]
复制代码

perfect! 😉

原来不少东西,并无想象的那么复杂

后记

想起了以前掘金上的 中止学习框架 一文,以及后面各位大佬的 驳 ....中止学习框架,说到底都是为了告诉咱们,无论学习什么,都要打好基础,做为前端开发者,最最基础的就是打好JavaScript的基础,基础扎实,学习框架都不是困难事情

相关文章
相关标签/搜索