• 关于

    JavaScript中的while循环

    的搜索结果

问题

【精品问答】前端实战100例之JavaScript篇

前端实战100例之JavaScript篇 前端JavaScript部分入门的例题为大家总结了100个,每个例题都附有代码解析,方便入门学习或做基础巩固。 1.用JavaScript输出文本 2.用JavaS...
珍宝珠 2020-02-14 15:10:56 1456 浏览量 回答数 1

回答

1.让JavaScript暂停下来,慢下来。 JavaScript排序是很快的,要我们肉眼能看到它的实现过程,我首先想到的是让排序慢下来。 排序的每一个循环都让它停300ms然后再继续进行。 怎么样才能停下来呢。查了一下JavaScript貌似没有sleep()这样的函数。暂停做不到,但是可以想办法让实现跟暂停差不多的效果。比如在循环里做一些无关的事情 。 首先尝试了让while(true)来一直执行一个空操作。执行一段时间再回到排序逻辑。代码大致是这样: for (var i = 0; i < 3; i++) { document.writeln(i); //DOM操作 var now = new Date().getTime(); while(new Date().getTime() - now < 3000){} } 慢是慢下来了。不过太耗资源,排序进行过程中dom并不会有任何改变,直到排序结束, DOM会变成排序好之后的样子。 但是如果设置断点一步步执行的时候 又可以看到一步步的排序变化。估计是因为这个操作太耗资源导致浏览器下达了一个DOM操作的命令但是一直腾不出资源来进行DOM操作。所以真正DOM操作的时候在js代码执行结束之后。 所以让JavaScript排序慢来来还是没有实现。 另一种让JavaScript暂停下来的思路: 写这个文章的时候又想到一种方法来让JavaScript停下来。 那就是AJAX的同步请求,以及超时操作。 也就是在要停下来的地方放一个AJAX请求,同步请求, 然后设置超时。超时的时间就是我们要暂停的时间。为了避免在到达超时请求之前服务 器就返回了我们的AJAX请求。可以在服务端运行类似 sleep()的程序 。从而保证AJAX不会返回。直接超时然后返回到我们的循环。不过这只是个设想。有兴趣的可以去尝试一下。 2.闭包和定时器。 这种思路不需要让排序过程慢下来。而是使用闭包缓存排序过程中数组的变化。然后使用setTimeout来确定展示每一个数组状态的顺序。在排序循环中放入类似下面的代码。 (function(){ var theArr = arr.slice();//当前数组状态的备份 setTimeout(function(){ bubbleSortDom(theArr);//排序的DOM操作。 },500*timeCount); timeCount++;//定时器的顺序。 })(); 不过后来发现这样子写的话代码量会比较大,逻辑有修改的话要修改的地方会有点多。局限性很多,比如要实现排序动画加快或减慢操作几乎是很困难的。所以还要另想办法。 3.缓存排序中的数组状态。 也就是在排序过程中。将数组的每一轮循环的状态保存到一个数组。然后再用这个数组依次将排序状态保存下来。 只需要在排序中加入一句就行。 this.pushHis(arr.slice(),i-1,j,k,temp); 这样就只需要一个setInterval()就可以了。并且可以很方便的实现动画的加快与减慢。逻辑也比较好理解 。 问题二:如何实现JavaScript排序动画的加快与减慢。 我们问题一使用的第三种方法。 得到一个保存了每一步排序状态的数组arr。 然后我们可以使用一个setInterval()定时器一步步展现排序状态。 如果要加快速度或减慢速度。就clearInterval(),修改定时器的执行间隔,重新setInterval(),从前一个定时器执行到数组中的位置开始执行。 问题三:对于使用递归实现的数组怎么办。 不是在原数组上进行操作的怎么办。 使用递归实现的排序。 可能并没有在一个数组上进行操作,只是最后返回一个排序好的数组出来。那么我们要如何获得排序中的数组的完整状态呢。 比如快速排序。 最开始不考虑动画,我的实现是这样的: function quickSort(arr){ var len = arr.length,leftArr=[],rightArr=[],tag; if(len<2){ return arr; } tag = arr[0]; for(i=1;i<len;i++){ if(arr[i]<=tag){ leftArr.push(arr[i]) }else{ rightArr.push(arr[i]); } } return quickSort(leftArr).concat(tag,quickSort(rightArr)); } 然后为了考虑动画,我改写了它的逻辑,让它在同一个数组上进行了实现。 其实是在递归的时候传入了当前的的子数组在原数组中的起始位置。从而在原数组上进行了操作。 用了两种方法来实现方式。在排序逻辑上略有不同。 第一种是先跟远处的对比。遇到比自己小的放到自己前面去。循环序号+1。比自己大的放到当前排序子数组的最后面去,循环序号不变。直到排列完成。 这种方法的缺点是即使是一个有序数组。它也会重新排。 第二种方法是 除了标记位,再设置一个对比位。 遇到比自己小的,放到前面去,标记位的位置+1,标记位与对比位之间所有的往后面移动一个位置。 遇到比自己大的。标记位不变,对比位+1。 这种方法的缺点是对数组进行的操作太多。优点是对有序数组不会再排。 方式一: function quickSort(arr,a,b,qArr){ var len = arr.length,leftArr=[],rightArr=[],tag,i,k,len_l,len_r,lb,ra,temp; if(a == undefined && b == undefined){ a = 0; b= arr.length-1;//初始化起始位置。 } if(qArr == undefined){ qArr = arr.slice(); } if((len == 2 && arr[0] == arr[1])||len<2){ return arr; } tag = qArr[a]; for (i = 1; i < len;) { if(qArr[a+i]<=tag){ leftArr.push(qArr[a+i]); qArr[a+i-1] = qArr[a+i]; qArr[a+i] = tag; k = a+i; i++; }else{ if(leftArr.length+rightArr.length == len-1){ break; } temp = qArr[a+i]; qArr[a+i] = qArr[b-rightArr.length]; qArr[b-rightArr.length] = temp; rightArr.push(temp); k = a+i-1; } this.pushHis(qArr.slice(),a,b,k); } len_l = leftArr.length; len_r = rightArr.length; if(len_l== 0){ lb = a; }else{ lb = a+len_l -1; this.sort(leftArr,a,lb,qArr); } if(len_r == 0){ ra = b; }else{ ra = b + 1 - len_r; this.sort(rightArr,ra,b,qArr) } return qArr } 方式二: function quickSort2(arr,a,b,qArr){ var len = arr.length,leftArr=[],rightArr=[],tag,i,j,k,temp,len_l,len_r,lb,ra; if(a == undefined && b == undefined){ a = 0; b= arr.length-1;//初始化起始位置。 } if(qArr == undefined){ qArr = arr.slice(); } if(len<2){ return arr; } if(len == 2 && arr[0] == arr[1]){ return arr; } tag = qArr[a]; for (i = 1,k = 0; i < len;) { if(qArr[a+i]>=tag){ rightArr.push(qArr[a+i]); i++; }else{ temp = qArr[a+i]; for(j = a+i;j>a+k;j--){ qArr[j] = qArr[j-1]; // this.pushHis(qArr.slice(),a,b,a+k); } qArr[a+k] = temp; leftArr.push(temp); k++; i++; } this.pushHis(qArr.slice(),a,b,a+k,i-1); } len_l = leftArr.length; len_r = rightArr.length; if(len_l== 0){ lb = a; }else{ lb = a+len_l -1; this.sort(leftArr,a,lb,qArr); } if(len_r == 0){ ra = b; }else{ ra = b + 1 - len_r; this.sort(rightArr,ra,b,qArr) } return qArr; } 具体的不同下面会有动画演示。 问题四:动画的流畅。 排序动画的DOM操作是很多的很快的。这里我做的优化只是让每一个排序步骤只涉及一个DOM操作。 全部由JavaScript拼接好,一次替换。类似下面的代码。 效果图: 主要实现了: 冒泡排序JavaScript动画演示 插入排序JavaScript动画演示 选择排序JavaScript动画演示 快速排序JavaScript动画演示 归并排序JavaScript动画演示 希尔排序JavaScript动画演示
liujae 2019-12-02 01:19:06 0 浏览量 回答数 0

回答

jquery的$.delay()方法设置一个延时来推迟执行队列中之后的项目。这个方法不能取代JS原生的setTimeout。 The .delay() method is best for delaying between queued jQuery effects. Because it is limited—it doesn't, for example, offer a way to cancel the delay—.delay() is not a replacement for JavaScript's native setTimeout function, which may be more appropriate for certain use cases.例子:在.slideUp() 和 .fadeIn()之间延时800毫秒。HTML 代码: jQuery 代码:$('#foo').slideUp(300).delay(800).fadeIn(400); 通过循环消耗cpufunction sleep(n) {var start = new Date().getTime();while(true) if(new Date().getTime()-start > n) break;} 用setTimeout。假设有三个步骤,步骤之间需要暂停一段时间;可以采用如下的方法: function firstStep() {//do somethingsetTimeout("secondStep()", 1000);}function secondStep() {//do somethingsetTimeout("thirdStep()", 1000);}function thirdStep() {//do something} ps:来源网络
元芳啊 2019-12-02 00:54:52 0 浏览量 回答数 0

回答

以下实例演示了如何遍历从Collection接口延伸出的List、Set和以键值对形式作存储的Map类型的集合,以下我们分别使用了普通for,增强型的 for ,iterator 等方式来遍历集合: List与Set类型集合的遍历 Main.java 文件 import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; public class Main { public static void main(String[] args) { // List集合的遍历 listTest(); // Set集合的遍历 setTest(); } private static void setTest() { Set set = new HashSet (); set.add("JAVA"); set.add("C"); set.add("C++"); // 重复数据添加失败 set.add("JAVA"); set.add("JAVASCRIPT"); // 使用iterator遍历set集合 Iterator<String> it = set.iterator(); while (it.hasNext()) { String value = it.next(); System.out.println(value); } // 使用增强for循环遍历set集合 for(String s: set){ System.out.println(s); } } // 遍历list集合 private static void listTest() { List list = new ArrayList (); list.add("菜"); list.add("鸟"); list.add("教"); list.add("程"); list.add("www.runoob.com"); // 使用iterator遍历 Iterator<String> it = list.iterator(); while (it.hasNext()) { String value = it.next(); System.out.println(value); } // 使用传统for循环进行遍历 for (int i = 0, size = list.size(); i < size; i++) { String value = list.get(i); System.out.println(value); } // 使用增强for循环进行遍历 for (String value : list) { System.out.println(value); } } } 以上代码运行输出结果为: 菜 鸟 教 程 www.runoob.com 菜 鸟 教 程 www.runoob.com 菜 鸟 教 程 www.runoob.com JAVA JAVASCRIPT C++ C JAVA JAVASCRIPT C++ C 关于Map类型集合的遍历 以下实例我们使用了 HashMap 的 keySet()与entrySet()方法来遍历集合: /* author by runoob.com Main.java */ import java.util.Map; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Map.Entry; //增强For循环 public class Main { public static void main(String[] args) { // 创建一个HashMap对象,并加入了一些键值对。 Map<String, String> maps = new HashMap<String, String>(); maps.put("1", "PHP"); maps.put("2", "Java"); maps.put("3", "C"); maps.put("4", "C++"); maps.put("5", "HTML"); // 传统的遍历map集合的方法1; keySet() //traditionalMethod1(maps); // 传统的遍历map集合的方法2; entrySet() //traditionalMethod2(maps); // 使用增强For循环来遍历map集合方法1; keySet() //strongForMethod1(maps); // 使用增强For循环来遍历map集合方法2; entrySet() strongForMethod2(maps); } private static void strongForMethod2(Map<String, String> maps) { Set<Entry<String, String>> set = maps.entrySet(); for (Entry<String, String> entry : set) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + " : " + value); } } private static void strongForMethod1(Map<String, String> maps) { Set set = maps.keySet(); for (String s : set) { String key = s; String value = maps.get(s); System.out.println(key + " : " + value); } } // 使用entrySet()方法,获取maps集合中的每一个键值对, private static void traditionalMethod2(Map<String, String> maps) { Set<Map.Entry<String, String>> sets = maps.entrySet(); // 取得迭代器遍历出对应的值。 Iterator<Entry<String, String>> it = sets.iterator(); while (it.hasNext()) { Map.Entry<String, String> entry = (Entry<String, String>) it.next(); String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + " : " + value); } } // 使用keySet()方法,获取maps集合中的所有键,遍历键取得所对应的值。 private static void traditionalMethod1(Map<String, String> maps) { Set sets = maps.keySet(); // 取得迭代器遍历出对应的值 Iterator it = sets.iterator(); while (it.hasNext()) { String key = it.next(); String value = maps.get(key); System.out.println(key + " : " + value); } } } 以上代码运行输出结果为: 1 : PHP 2 : Java 3 : C 4 : C++ 5 : HTML
问问小秘 2020-02-13 17:21:28 0 浏览量 回答数 0

回答

您可以选择是否使用webWorkers: 没有WebWorkers 对于需要与DOM或应用程序中的许多其他状态进行交互的代码,您不能使用webWorker,因此通常的解决方案是将工作分解为多个块,并在计时器上完成每个块的工作。计时器之间的块之间的中断使浏览器引擎可以处理其他正在进行的事件,不仅可以处理用户输入,还可以绘制屏幕。 通常,您可以负担每个计时器处理多个计时器的效率,这比每个计时器仅处理一个计时器效率更高,速度更快。此代码使UI线程有机会处理每个块之间的任何未决UI事件,这将使UI保持活动状态。 function processLargeArray(array) { // set this to whatever number of items you can process at once var chunk = 100; var index = 0; function doChunk() { var cnt = chunk; while (cnt-- && index < array.length) { // process array[index] here ++index; } if (index < array.length) { // set Timeout for async iteration setTimeout(doChunk, 1); } } doChunk(); } processLargeArray(veryLargeArray); 这是该概念的一个可行示例-不是相同的功能,而是一个使用相同setTimeout()思想通过多次迭代测试概率场景的长期运行过程:http : //jsfiddle.net/jfriend00/9hCVq/ 您可以将上述内容制作成更通用的版本,.forEach()像这样的调用回调函数: // last two args are optional function processLargeArrayAsync(array, fn, chunk, context) { context = context || window; chunk = chunk || 100; var index = 0; function doChunk() { var cnt = chunk; while (cnt-- && index < array.length) { // callback called with args (value, index, array) fn.call(context, array[index], index, array); ++index; } if (index < array.length) { // set Timeout for async iteration setTimeout(doChunk, 1); } } doChunk(); } processLargeArrayAsync(veryLargeArray, myCallback, 100); 除了可以一次猜测要分割多少块,还可以让经过的时间作为每个分割块的指导,并使其在给定的时间间隔内尽可能多地进行处理。不管迭代有多密集,CPU都会自动保证浏览器的响应能力。因此,您可以传递毫秒值(或仅使用智能默认值),而不用传递块大小: // last two args are optional function processLargeArrayAsync(array, fn, maxTimePerChunk, context) { context = context || window; maxTimePerChunk = maxTimePerChunk || 200; var index = 0; function now() { return new Date().getTime(); } function doChunk() { var startTime = now(); while (index < array.length && (now() - startTime) <= maxTimePerChunk) { // callback called with args (value, index, array) fn.call(context, array[index], index, array); ++index; } if (index < array.length) { // set Timeout for async iteration setTimeout(doChunk, 1); } } doChunk(); } processLargeArrayAsync(veryLargeArray, myCallback); 使用WebWorkers 如果循环中的代码不需要访问DOM,则可以将所有耗时的代码放入webWorker中。webWorker将独立于主浏览器Javascript运行,然后完成后,它可以通过postMessage返回任何结果。 webWorker需要将将在webWorker中运行的所有代码分离到一个单独的脚本文件中,但是它可以完全运行,而不必担心阻塞浏览器中其他事件的处理,也不必担心“无响应脚本”提示当在主线程上执行长时间运行的过程且不阻止UI中的事件处理时,可能会出现这种情况。
保持可爱mmm 2020-02-09 13:44:39 0 浏览量 回答数 0

回答

JavaScript具有强大的语义,可以遍历数组和类似数组的对象。我将答案分为两部分:真正数组的选项,以及仅是数组之类的东西的选项,例如arguments对象,其他可迭代对象(ES2015 +),DOM集合,等等。 我会很快注意到,您现在可以通过将ES2015转换为ES5 ,甚至在ES5引擎上使用ES2015选项。搜索“ ES2015 transpiling” /“ ES6 transpiling”以了解更多... 好吧,让我们看看我们的选择: 对于实际数组 您目前在ECMAScript 5(“ ES5”)中拥有三个选项,这是目前最广泛支持的版本,在ECMAScript 2015中又添加了两个选项(“ ES2015”,“ ES6”): 使用forEach及相关(ES5 +) 使用一个简单的for循环 正确使用for-in 使用for-of(隐式使用迭代器)(ES2015 +) 明确使用迭代器(ES2015 +) 细节: 1.使用forEach及相关 在任何可以访问ArrayES5(直接或使用polyfills)添加的功能的模糊现代环境(因此,不是IE8)中,都可以使用forEach(spec| MDN): var a = ["a", "b", "c"]; a.forEach(function(entry) { console.log(entry); }); forEach接受回调函数,以及(可选)this调用该回调时要使用的值(上面未使用)。依次为数组中的每个条目调用回调,从而跳过稀疏数组中不存在的条目。尽管上面只使用了一个参数,但回调函数使用以下三个参数调用:每个条目的值,该条目的索引以及对要迭代的数组的引用(以防您的函数尚未使用它) )。 除非您支持IE8之类的过时浏览器(截至2016年9月,NetApps在该市场上所占份额刚刚超过4%),forEach否则您可以在没有垫片的情况下在通用网页中愉快地使用。如果您确实需要支持过时的浏览器,forEach则可以轻松进行填充/填充(搜索“ es5 shim”以获得多个选项)。 forEach 这样做的好处是您不必在包含范围中声明索引和值变量,因为它们是作为迭代函数的参数提供的,因此可以很好地将作用域限定为该迭代。 如果您担心为每个数组条目进行函数调用的运行时成本,请不必担心;细节。 此外,forEach它是“遍历所有对象”功能,但是ES5定义了其他几个有用的“遍历数组并做事”功能,包括: every(在第一次返回回调false或出现错误时停止循环) some(在第一次返回回调true或发生错误时停止循环) filter(创建一个新数组,其中包含过滤器函数返回的元素,true并省略其返回的元素false) map (根据回调返回的值创建一个新数组) reduce (通过重复调用回调并传入先前的值来建立值;有关详细信息,请参见规范;对汇总数组内容和许多其他内容很有用) reduceRight(如reduce,但按降序而不是升序工作) 2.使用一个简单的for循环 有时,旧方法是最好的: var index; var a = ["a", "b", "c"]; for (index = 0; index < a.length; ++index) { console.log(a[index]); } 如果数组的长度将不会在循环过程中改变,它在性能敏感的代码(不可能),一个稍微复杂一点的版本抓住了长度达阵可能是一个很小的有点快: var index, len; var a = ["a", "b", "c"]; for (index = 0, len = a.length; index < len; ++index) { console.log(a[index]); } 和/或倒数: var index; var a = ["a", "b", "c"]; for (index = a.length - 1; index >= 0; --index) { console.log(a[index]); } 但是,使用现代JavaScript引擎,很少需要消耗掉最后的能量。 在ES2015及更高版本中,可以使索引和值变量在for循环本地: let a = ["a", "b", "c"]; for (let index = 0; index < a.length; ++index) { let value = a[index]; console.log(index, value); } //console.log(index); // would cause "ReferenceError: index is not defined" //console.log(value); // would cause "ReferenceError: value is not defined" 而且,当您执行此操作时,不仅会为每个循环迭代创建一个新的闭包,value而且还会index为每个循环迭代重新创建一个闭包,这意味着在循环主体中创建的闭包保留对为该特定迭代创建的index(和value)的引用: let divs = document.querySelectorAll("div"); for (let index = 0; index < divs.length; ++index) { divs[index].addEventListener('click', e => { console.log("Index is: " + index); }); } 如果您有五个div,则单击第一个将获得“索引为:0”,如果单击最后一个则将为“索引为:4”。如果您使用而不是则无法使用。varlet 3. 正确使用for-in 你会得到别人告诉你使用for-in,但是这不是for-in对。for-in遍历对象的可枚举属性,而不是数组的索引。甚至在ES2015(ES6)中也不保证顺序。ES2015 +不定义为对象属性(通过[[OwnPropertyKeys]],[[Enumerate]]以及使用他们喜欢的东西Object.getOwnPropertyKeys),但它并没有定义for-in将遵循这个顺序。(其他答案的详细信息。) for-in数组上唯一真正的用例是: 这是一个稀疏的数组,里面有巨大的空隙,或者 您正在使用非元素属性,并且希望将它们包括在循环中 仅查看第一个示例:for-in如果使用适当的保护措施,则可以用来访问那些备用阵列元素: // a is a sparse array var key; var a = []; a[0] = "a"; a[10] = "b"; a[10000] = "c"; for (key in a) { if (a.hasOwnProperty(key) && // These checks are /^0$|^[1-9]\d*$/.test(key) && // explained key <= 4294967294 // below ) { console.log(a[key]); } } 请注意以下三个检查: 该对象具有该名称的自身属性(不是从其原型继承的属性),并且 该键是所有十进制数字(例如,正常的字符串形式,而不是科学计数法),并且 该键的值在被强制为数字时为<= 2 ^ 32-2(即4,294,967,294)。这个数字从哪里来?它是规范中数组索引定义的一部分。其他数字(非整数,负数,大于2 ^ 32-2的数字)不是数组索引。它的2 ^ 32的理由- 2是使得大于2 ^ 32下一个最大的索引值- 1,这是一个数组的最大值length可以有。(例如,数组的长度适合于32位无符号整数。)(向RobG表示支持,在我的博客文章的评论中指出我先前的测试不太正确。) 当然,您不会在内联代码中执行此操作。您将编写一个实用程序函数。也许: 4.使用for-of(隐式使用迭代器)(ES2015 +) ES2015将迭代器添加到JavaScript。使用迭代器最简单的方法是new for-of语句。看起来像这样: const a = ["a", "b", "c"]; for (const val of a) { console.log(val); } 在幕后,它从数组中获取一个迭代器并循环遍历,从而从中获取值。这没有使用for-inhas 的问题,因为它使用了由对象(数组)定义的迭代器,并且数组定义了其迭代器遍历其条目(而不是其属性)。与for-inES5 不同,访问条目的顺序是其索引的数字顺序。 5.明确使用迭代器(ES2015 +) 有时,您可能想显式使用迭代器。您也可以这样做,尽管它比笨拙得多for-of。看起来像这样: const a = ["a", "b", "c"]; const it = a.values(); let entry; while (!(entry = it.next()).done) { console.log(entry.value); } 迭代器是与规范中的迭代器定义匹配的对象。每次调用时,其next方法都会返回一个新的结果对象。结果对象具有属性,done告诉我们是否完成操作,以及一个value具有该迭代值的属性。(done如果是false,value则为可选,如果是,则为可选undefined。) 的含义value取决于迭代器;数组至少支持三个返回迭代器的函数: values():这是我上面使用的那个。它返回迭代,其中每个value是用于该迭代阵列条目("a","b",和"c"在实施例更早)。 keys():返回一个迭代器,每个迭代器value都是该迭代的关键(因此,对于我们a上面的代码,将是"0",然后是"1",然后是"2")。 entries():返回一个迭代器,其中每个迭代器value都是[key, value]该迭代形式的数组。 对于类似数组的对象 除了真正的数组之外,还有一些类数组对象,它们具有一个length或多个具有数字名称的属性:NodeList实例,arguments对象等。我们如何遍历它们的内容? 对数组使用上面的任何选项 上面的至少一些(可能是大多数甚至全部)数组方法经常同样适用于类似数组的对象: 使用forEach及相关(ES5 +) 上的各种功能Array.prototype是“有意通用的”,通常可以通过Function#call或在类似数组的对象上使用Function#apply。(在此答案的末尾,请参阅警告,以了解主机提供的对象,但这是一个罕见的问题。) 假设您要forEach在Node的childNodes属性上使用。您可以这样做: Array.prototype.forEach.call(node.childNodes, function(child) { // Do something with `child` }); 如果要执行很多操作,则可能需要将函数引用的副本复制到变量中以供重用,例如: // (This is all presumably in some scoping function) var forEach = Array.prototype.forEach; // Then later... forEach.call(node.childNodes, function(child) { // Do something with `child` }); 使用一个简单的for循环 显然,一个简单的for循环适用于类似数组的对象。 正确使用for-in for-in具有与数组相同的保护措施,也应与类似数组的对象一起使用;上面#1中由主机提供的对象的警告可能适用。 使用for-of(隐式使用迭代器)(ES2015 +) for-of将使用对象提供的迭代器(如果有);我们将不得不看一下它如何与各种类似数组的对象一起运行,尤其是主机提供的对象。例如,NodeListfrom 的规范querySelectorAll已更新以支持迭代。HTMLCollectionfrom 的规格getElementsByTagName不是。 明确使用迭代器(ES2015 +) 参见#4,我们必须看看迭代器如何发挥作用。 创建一个真实的数组 其他时候,您可能希望将类似数组的对象转换为真正的数组。做到这一点非常容易: 使用slice数组的方法 我们可以使用slice数组的方法,就像上面提到的其他方法一样,它是“故意通用的”,因此可以与类似数组的对象一起使用,如下所示: var trueArray = Array.prototype.slice.call(arrayLikeObject); 因此,例如,如果我们要将a NodeList转换为真实数组,则可以执行以下操作: var divs = Array.prototype.slice.call(document.querySelectorAll("div")); 请参阅下面的警告,了解主机提供的对象。特别要注意的是,这将在IE8及更早版本中失败,这不允许您this像这样使用主机提供的对象。 使用传播语法(...) 还可以将ES2015的扩展语法与支持此功能的JavaScript引擎一起使用: var trueArray = [...iterableObject]; 因此,例如,如果我们想将a NodeList转换为真正的数组,使用扩展语法,这将变得非常简洁: var divs = [...document.querySelectorAll("div")]; 使用Array.from (规格) | (MDN) Array.from(ES2015 +,但很容易填充),从类似数组的对象创建数组,可以选择先将条目通过映射函数传递。所以: var divs = Array.from(document.querySelectorAll("div")); 或者,如果您想获取具有给定类的元素的标记名称的数组,则可以使用映射函数: // Arrow function (ES2015): var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName); // Standard function (since `Array.from` can be shimmed): var divs = Array.from(document.querySelectorAll(".some-class"), function(element) { return element.tagName; }); 警告主机提供的对象 如果您将Array.prototype函数与主机提供的类似数组的对象一起使用(DOM列表和浏览器而非JavaScript引擎提供的其他内容),则需要确保在目标环境中进行测试,以确保主机提供的对象行为正常。大多数(现在)确实表现正常,但是测试很重要。原因是Array.prototype您可能要使用的大多数方法都依赖于主机提供的对象,该对象为抽象[[HasProperty]]操作提供了诚实的答案。在撰写本文时,浏览器在这方面做得很好,但是5.1规范确实允许由主机提供的对象可能不诚实。在§8.6.2中,该部分开头附近的大表下方的几段中),其中表示: 除非另有说明,否则宿主对象可以以任何方式实现这些内部方法。例如,一种可能性是,[[Get]]和[[Put]]对特定宿主对象确实读取与存储的属性值但[[HasProperty]]总是产生假。 (我在ES2015规范中找不到等效的用法,但情况肯定仍然如此。)同样,在撰写本文时,现代浏览器中的主机提供的类似数组的对象(NodeList例如,实例)确实可以处理[[HasProperty]]正确,但是测试很重要。) 问题来源于stack overflow
保持可爱mmm 2020-01-08 11:20:24 0 浏览量 回答数 0

问题

十大经典排序算法最强总结(内含代码实现)

1、算法分类 十种常见排序算法可以分为两大类: 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。 非比较类排...
游客pklijor6gytpx 2020-01-09 14:44:55 1240 浏览量 回答数 2

问题

【javascript学习全家桶】934道javascript热门问题,阿里百位技术专家答疑解惑

阿里极客公益活动:或许你挑灯夜战只为一道难题或许你百思不解只求一个答案或许你绞尽脑汁只因一种未知那么他们来了,阿里系技术专家来云栖问答为你解答技术难题了他们用户自己手中的技术来帮助用户成长本次活动特邀百位阿里技术专家对javascript常...
管理贝贝 2019-12-01 20:07:22 6202 浏览量 回答数 1

问题

java上传下载报错

项目发布运行在Tomcat服务器上,文件上传没有问题,路径中的目录也都对,但是在浏览器端下载的时候就出现问题了, 访问到的下载路径中有两个文件夹合并了,代码如下ÿ...
DM。 2020-05-27 10:54:16 7 浏览量 回答数 2

云产品推荐

上海奇点人才服务相关的云产品 小程序定制 上海微企信息技术相关的云产品 国内短信套餐包 ECS云服务器安全配置相关的云产品 开发者问答 阿里云建站 自然场景识别相关的云产品 万网 小程序开发制作 视频内容分析 视频集锦 代理记账服务 阿里云AIoT