前言

​ 如果对技术很自信,请直接看 实现的源码

​ 如果想回顾一下基础,请按文章顺序阅读

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

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

每个方法都接收两个参数

  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高程上说明 是运行该函数的作用域对象,可以看一下经典的例子

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的迭代函数与迭代函数的实现的更多相关文章

  1. Python 函数 切片 迭代 列表生成器

    函数 编写     定义一个函数要用def语句    def sum(i,n):   ⚠有冒号 返回多值     实际上是返回一个tuple 定义默认参数    默认参数的作用是简化调用   def ...

  2. python记录_day14 内置函数二 迭代 二分法

    一.匿名函数 形式: lambda 形参:返回值 lambda表示的是匿名函数. 不需要用def来声明, 一句话就可以声明出一个函数.匿名函数不是说一定没名字,而是他们的名字统一称为“lambda”, ...

  3. Python学习笔记014——迭代工具函数 内置函数enumerate()

    1 描述 enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中. 2 语法 enumerate(sequ ...

  4. Python学习笔记014——迭代工具函数 内置函数zip()

    1 描述 zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表. 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操 ...

  5. filter(函数,可以迭代的对象)

    #!/usr/bin/env python #filter(函数,可以迭代的对象) def f1(x): if x > 22: return True else: return False re ...

  6. Javascript数组系列三之迭代方法2

    今天我们来继续 Javascript 数组系列的文章,上文 <Javascript数组系列二之迭代方法1> 我们说到一些数组的迭代方法,我们在开发项目实战的过程中熟练的使用可以大大提高我们 ...

  7. JavaScript高级编程——Array数组迭代(every()、filter()、foreach()、map()、some(),归并(reduce() 和reduceRight() ))

    JavaScript高级编程——Array数组迭代(every().filter().foreach().map().some(),归并(reduce() 和reduceRight() )) < ...

  8. javascript递归、循环、迭代、遍历和枚举概念

    javascript递归.循环.迭代.遍历和枚举概念 〓递归(recursion)在数学与计算机科学中,是指在函数的定义中使用函数自身的方法.递归一词还较常用于描述以自相似方法重复事物的过程.例如,当 ...

  9. 深入理解javascript函数定义与函数作用域

    最近在学习javascript的函数,函数是javascript的一等对象,想要学好javascript,就必须深刻理解函数.本人把思路整理成文章,一是为了加深自己函数的理解,二是给读者提供学习的途径 ...

随机推荐

  1. post字符 特殊字符处理【转】

    今天和同事调试接口,由于产品设计的问题,传递的参数没有做任何的限制.同事就在传参数的时候加了些特殊字符到后台,但是后台打印的日志是 null... 然后上网搜了下解决办法:转 https://www. ...

  2. centos ntfs-3g 安装和使用

    安装fuse 下载fuse(ntfs-3g依赖fuse):http://vdisk.weibo.com/s/ajww5fZsUq50L?from=page_100505_profile&wvr ...

  3. visual box 安装 centos7后,无法上网

    ifconfig  命令后,只看到个回环网卡: 进入 /etc/sysconfig/network-scripts后,发现有设备 visual box 中设置为“桥接网卡”,也没问题,最后把控制芯片改 ...

  4. python基础——Linux系统下的文件目录结构

    单用户操作系统和多用户操作系统 单用户操作系统:指一台计算机在同一时间只能由一个用户使用,一个用户独自享用系统的全部硬件和软件资源. 多用户操作系统:指一台计算机在同一时间可以由多个用户使用,多个用户 ...

  5. Java学习---面向对象的远程方法调用[RMI]

    基础知识 分布式计算是一门计算机科学,它研究如何把一个需要非常巨大的计算能力才能解决的问题分成许多小的部分,然后把这些部分分配给许多计算机进行处理,最后把这些计算结果综合起来得到最终的结果. 常见的分 ...

  6. 企业级Apache详解2

    http_conf主配置说明 root@lamp01 apache]# grep -Ev "#|^$" conf/httpd.conf DocumentRoot "/us ...

  7. CSMA/CD 3

    一.二进制指数类型退避算法 (truncated binary exponential type) 发生碰撞的站在停止发送数据后,要推迟(退避)一个随机时间才能再发送数据. 目的:重传时再次发生碰撞的 ...

  8. December 14th 2016 Week 51st Wednesday

    Everything has its time and that time must be watched. 万物皆有时,时来不可失. Everything has its time, and I r ...

  9. ZT 王国维先生“人生三大境界”的具体含义是什么?

    昨夜西风凋碧树.独上高楼,望尽天涯路. 衣带渐宽终不悔,为伊消得人憔悴. 众里寻他千百度,蓦然回首,那人却在,灯火阑珊处. 这三句本来都是言情话相思的佳句,却被王国维用以表现“悬思——苦索——顿悟”的 ...

  10. [T-ARA][그녀를 보면][看着那个女人的话]

    歌词来源:http://music.163.com/#/song?id=29343995 作曲 : 코난 [作曲 : Ko-nan] 作词 : 코난/로코 [作词 : Ko-nan-/lo-Ko] b ...