当前位置: 首页 > Web前端 > HTML

深入理解JavaScript——循环来这里

时间:2023-03-28 13:53:44 HTML

写这篇文章真的很痛苦,因为我的心已经不在了。前后花了一周的时间撬动了键盘循环集合,以至于JavaScript中出现了各种循环,比如for,for(reverse),for...in,for...of,forEach,map等,这些循环有自己的什么特点?for循环这是最常见的循环for(vari=0;i<10;i++){console.log(i)}它的特点是最常见的,缺点是可读性差for(reverse)loop顾名思义,就是for循环的翻转版本是for(vari=10;i>0;i--){console.log(i)}同样可读性差。for...infor循环可以以任何顺序迭代一个对象,除了Symbol可枚举属性,包括继承的可枚举属性,有两个特点。一是对象是迭代的,二是循环目标是可枚举的属性,包括继承的属性。//示例1:迭代对象varobj={a:1,b:2,c:3}for(varkeyinobj){console.log("obj."+key+"="+obj[key])}//obj.a=1//obj.b=2//obj.c=3//示例2:迭代可枚举属性Object.prototype.sayHello=function(){console.log('hello')}//数组也属于对象,数组也可以使用对象方法constiterable=[1,2,3]iterable.name='hello'for(letkeyiniterable){console.log("key&value:"+key+"="+iterable[key])}//key&value:0=1//key&value:1=2//key&value:2=3//key&value:name=hello//key&value:sayHello=function(){console.log('hello')}它使用例是检查其中的任何键是否为特定值。我们在复制秘密中手写了一个简单的深层复制:[]:{}for(letpropintarget){if(source.hasOwnProperty(prop)){target[prop]=typeofsource[prop]==='object'?deepClone(source[prop]):source[prop]}}returntarget}通过for...in遍历所有可枚举的属性,然后通过hasOwnProperty过滤掉不是自己属性的属性,从而得到所有可以枚举的属性自己枚举,深拷贝完成。它是ES6支持的特性,其用途是遍历可迭代对象(包括Array、Map、Set、String、arguments等),以for...in中的例子2为例:Object.prototype.sayHello=function(){console.log('hello')}constiterable=[1,2,3]iterable.name='hello'for(letiofiterable){console.log(i);//3,5,7}如果for...in是获取对象的key(因为可以在for循环中获取value),那么for...of获取对象的值就更方便了目的。对数组的每个元素执行一次给定的函数遍历时,不能通过break或return提前终止循环。先看它的参数,一共有三点:element:当前元素index:当前元素的索引array:原数组constarray1=['a','b','c'];array1.forEach((str,i,origin)=>{console.log(`${i}:${str}/${origin}`);});//0:a/a,b,c//1:b/a,b,c//2:c/a,b,c调用时不会改变原数组(重点)constarray1=['a','b','c'];array1.forEach((element)=>{element=element+1});console.log(array1)//[a,b,c]但是经常遇到这样的项目开发中的例子:constarr=[{name:'johan',age:29},{name:'elaine',age:29}]arr.forEach(ele=>{if(ele.name==='johan'){ele.age=22}})console.log(arr)//[{name:'johan',age:22},{name:'elaine',age:29}]原数组已经变了,为什么?因为虽然调用forEach不会改变原来的数组,但是callbackFn可能会改变元素(当前对象)。在第一个例子中,因为当前元素是基本类型,所以给它赋原始数组是无效的,而当当前元素是引用类型时,情况就不同了。引用类型存放在堆内存中,共享一个引用地址。当引用改变时,原始数组也会改变。您可以查看复制的秘密地图ES6新API。此方法创建一个新数组。这个新数组由调用提供的函数一次后原数组中每个元素的返回值组成constarray1=[1,4,9,16];constmap1=array1.map(x=>x*2);控制台日志(地图1);//[2,8,18,32]如果for...in经常和for...of比较,那么forEach的比较对象就是map。比如forEach没有返回值,map会返回一个新的数组;forEach偶尔会改变原数组(当callbackFn改变当前对象时),而map因为返回的是新数组,所以永远不会改变原数组(所以在函数式编程中经常用到map,是一个标准的纯函数)来派生一道面试题["1","2","3"].map(parseInt)为什么这道题的答案是[1,NaN,NaN]?parseInt的语法是parseInt(string,radix),意思是//parseInt(string,radix)=>map(parseInt(value,index))//也就是说它的迭代过程是://第一次迭代:indexis0:parseInt("1",0)//1//第二次迭代:index为1:parseInt("2",1)//NaN//第三次迭代:index为2:parseInt("3",2)//NaNradix表示基制的基数,取值范围2~36,常见的有二进制、八进制、十进制、十六进制。二进制的时候,除了“0、1”,其他数都是不是有效的二进制数速度比较一些屌丝面试题会问这些round-robin方法速度排序。太搞笑了,又不是造火箭。问这些的目的是什么?不过,我这里都写好了,我来测试一个例子:constmillion=10000000;constarr=数组(百万);console.time('timer')for(leti=0;i0;i--){}//for(reverse)for(constvinarr){}//for...infor(constvofarr){}//for...ofarr.forEach(v=>v)//forEacharr.map(v=>v)//derivedfrommapconsole.timeEnd('timer')有人在知乎上问:如何直观地解释JavaScript中map、foreach、reduce的区别,游雨溪打了个巧妙的比喻:forEach就是你让他们做的按顺序做;map就是你拿箱子,让他们把钱包扔进去,然后返回一个新的数组,里面有大家的钱包。Reduce是为了守住钱包。每张支票,加上你和之前的合成,就可以算出总额。大于100的钱的快速总结循环有3个tricks,一是比较for...in和for...of;另一种是比较forEach和map;三是用ES6编写其他常用的API。彻底区分JS数组的forEach()和map()MDN是如何形象地解释JavaScript中map、foreach、reduce的区别的?系列文章深入理解JavaScript-开篇深入理解JavaScript-什么是JavaScript深入理解JavaScript-JavaScript由什么组成深入理解JavaScript-一切皆对象深入理解JavaScriptJavaScript之——对象(object)深入理解JavaScript——newdone什么是深入理解JavaScript——Object.create深入理解JavaScript——复制的秘密深入理解JavaScript——原型深入理解JavaScript——继承深入理解JavaScript——JavaScript中的第一位皇帝深入理解JavaScript——instanceof——寻找祖先深入理解JavaScript——函数深入理解深入理解JavaScript——Scope深入理解JavaScript——this关键字深入理解JavaScript——调用、应用、绑定将深入理解JavaScript——立即执行函数(IIFE)深入理解JavaScript——词法环境深入理解JavaScript——执行上下文和调用栈深入理解JavaScript——作用域VS执行上下文深入理解JavaScript——闭包深入理解JavaScript——防抖与节流深入理解JavaScript-函数式编程深入理解JavaScript-垃圾收集机制深入理解JavaScript-Array深入理解JavaScript-循环来这里是为了深入理解JavaScript-字符串