首页 web前端 js教程 JavaScript 提升运行速度之循环篇 译文_javascript技巧

JavaScript 提升运行速度之循环篇 译文_javascript技巧

May 16, 2016 pm 06:48 PM
循环 运行速度

这篇着重讲第一个原因。最后给出了一个开发模式,替换传统的循环结构,可以完全避免脚本失控的状况发生。

原文标题:Speed up your JavaScript, Part 1
原文作者:Nicholas C. Zakas
在我 上一篇帖子 (译文 ) 中,谈到了各个浏览器究竟会在什么情况下弹出脚本失控提示,对于Internet Explorer 来说,当浏览器执行了数量过多的语句时就会停止执行脚本,而其他的浏览器,则是持续执行脚本超过一定时间的时候就会给出提示。而我们要探讨的核心问题,不是这些浏览器如果探测失控的脚本,而是我们如何才可以让脚本运行的更快一些,从而避免这些警告 。
脚本失控基本上有以下四个方面的原因:
在循环中执行了太多的操作。
臃肿的函数体
过多的递归
过多的 DOM 调用
在这篇帖子中,我将会把重点放到第一条上:循环中的过多操作。循环的操作是同步进行的,所以执行一个循环所花费的时间完全取决于循环的次数。因此有 两种情况会导致循环执行的时间过长,并直接导致锁定浏览器。一是循环体中包含了太多的操作,二是循环的次数过多。这两种情况都能直接导致锁定浏览器,并显示脚本失控的提示。
解决这个问题的诀窍就是用下面这两个问题来评估每个循环:
这个循环必须要同步执行么?
循环里面的数据,必须要按顺序执行么?
如果两个问题的答案都是否定的话,你就可以选择将循环 里的操作进行分解。关键是要根据代码的具体环境确定上面两个问题的答案。一个典型的循环可能像下面这个样子:

复制代码 代码如下:

for(var i=0; i process(items[i]);
}

乍一看这个循环并没有太大的问题,是不是会运行很长时间完全取决于循环的次数。如果紧接循环后没有其他代码在执行的时候需要依赖于循环的结果,那么 对于第一个问题的答案就是“ 不” 。你还可以发现,循环每次只处理一个数值,而且不依赖于上一次循环的结果,所以对于第二个问题的答案同样也是否定的。这就意味着,循环可以通过某种方式进行拆解,不会导致锁定浏览器而显示脚本失控的提示。
在《Professional JavaScript, Second Edition 》这本书中,对于那些执行次数非常巨大的虚幻,我推荐使用下面的方式来处理:
复制代码 代码如下:

function chunk(array, process, context){
setTimeout(function(){
var item = array.shift();
process.call(context, item);
if (array.length > 0){
setTimeout(arguments.callee, 100);
}
}, 100);
}

chunk() 函数的用途就是将一个数组分成小块处理(这也是名字的由来),我们可以传递三个参数。要处理的数组对象、处理函数以及一个可选的上下文变量,用于设置process() 函数中对应的this 对象。第一个timer 用于处理操作之间的延时(这里设置为100 毫秒,大家可以根据实际需要自行修改)。每次执行这个函数,都会将数组中的第一个对象取出,并传给process() 函数进行操作,如果这时process() 中还有未处理完的对象, 另外一个timer 就会启动,用于重复等待。上面提到的循环,可以通过下面的方法使用这个函数:
chunk(items, process);
需要注意的是,在这里数组采用了队列(queue )的形式,而且在循环的过程中,每次都会发生修改。如果你要修改数组的原始状态,这里介绍两种途径:一种是通过concat() 函数,在传递之前,建立一个当前数组的副本:
chunk(items.concat(), process);
另外一种选择是直接修改chunk() 函数,直接在函数内部进行修改:
复制代码 代码如下:

function chunk(array, process, context){
var items = array.concat(); //clone the array
setTimeout(function(){
var item = items.shift();
process.call(context, item);
if (items.length > 0){
setTimeout(arguments.callee, 100);
}
}, 100);
}

注意这种方法要比只保存一个索引安全的多,因为数组的内容在下次计时器生效之前可能会发生变化。
这里提到的chunk() 函数,只是优化循环性能的一个起点。你可以根据需要不断改进它,让它拥有更多的功能。比如说,在数组中所有对象都处理完成以后,可以增加一个函数回调。无论你是否会按照这种方式对函数进行修改,这只是一种JavaScript 的代码开发模式,可以帮助优化数组的处理性能,还可以避免那个脚本失控的警告。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

lambda表达式跳出循环 lambda表达式跳出循环 Feb 20, 2024 am 08:47 AM

lambda表达式跳出循环,需要具体代码示例在编程中,循环结构是经常使用的一种重要语法。然而,在特定的情况下,我们可能希望在循环体内满足某个条件时,跳出整个循环,而不是仅仅终止当前的循环迭代。在这个时候,lambda表达式的特性可以帮助我们实现跳出循环的目标。lambda表达式是一种匿名函数的声明方式,它可以在内部定义简单的函数逻辑。它与普通的函数声明不同,

Go语言中的循环和递归的比较研究 Go语言中的循环和递归的比较研究 Jun 01, 2023 am 09:23 AM

注:本文以Go语言的角度来比较研究循环和递归。在编写程序时,经常会遇到需要对一系列数据或操作进行重复处理的情况。为了实现这一点,我们需要使用循环或递归。循环和递归都是常用的处理方式,但在实际应用中,它们各有优缺点,因此在选择使用哪种方法时需要考虑实际情况。本文将对Go语言中的循环和递归进行比较研究。一、循环循环是一种重复执行某段代码的机制。Go语言中主要有三

PHP返回数组所有值,组成一个数组 PHP返回数组所有值,组成一个数组 Mar 21, 2024 am 09:06 AM

这篇文章将为大家详细讲解有关PHP返回数组所有值,组成一个数组,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。使用array_values()函数array_values()函数返回一个数组中所有值的数组。它不会保留原始数组的键。$array=["foo"=>"bar","baz"=>"qux"];$values=array_values($array);//$values将是["bar","qux"]使用循环可以使用循环手动获取数组的所有值并将其添加到一个新

为什么C代码比Python的运行速度更快? 为什么C代码比Python的运行速度更快? Sep 11, 2023 pm 12:45 PM

在本文中,我们将了解为什么C语言代码运行速度比Python更快。GuidoVanRossum开发了Python,这是最著名的编程语言之一。Python因其清晰的语法和简单的代码而受到开发人员的欢迎,即使对于新手来说也是如此。学习Python对于那些刚刚开始编程职业生涯的人来说是非常有利的。他们可以使用Python编程培训、博客、视频、模块和数千种其他资源来了解这种流行语言的各个方面。完成后,您将能够进行现代开发活动,例如GUI开发、网页设计、系统管理、复杂的金融交易或计算、数据科学、可视化等等。

Java Iterator 与 Iterable:迈入编写优雅代码的行列 Java Iterator 与 Iterable:迈入编写优雅代码的行列 Feb 19, 2024 pm 02:54 PM

Iterator接口Iterator接口是一个用于遍历集合的接口。它提供了几个方法,包括hasNext()、next()和remove()。hasNext()方法返回一个布尔值,指示集合中是否还有下一个元素。next()方法返回集合中的下一个元素,并将其从集合中删除。remove()方法从集合中删除当前元素。以下代码示例演示了如何使用Iterator接口来遍历集合:Listnames=Arrays.asList("John","Mary","Bob");Iterator

Java函数中递归调用有哪些替代方案? Java函数中递归调用有哪些替代方案? May 05, 2024 am 10:42 AM

用迭代替代Java函数中的递归调用在Java中,递归是一个强大的工具,用于解决各种问题。但是,在某些情况下,使用迭代可能是一个更好的选择,因为它更有效且不易出现堆栈溢出。以下是迭代的优点:效率更高,因为它不需要为每个递归调用创建新的栈帧。不容易发生堆栈溢出,因为堆栈空间使用受限制。替代递归调用的迭代方法:Java中有几种方法可以将递归函数转换为迭代函数。1.使用栈使用栈是将递归函数转换为迭代函数最简单的方法。栈是一种后入先出(LIFO)数据结构,类似于函数调用栈。publicintfa

win10系统如何调整虚拟内存提高运行速度 win10系统如何调整虚拟内存提高运行速度 Jul 01, 2023 pm 02:01 PM

  win10系统如何调整虚拟内存提高运行速度?随着电脑的使用率越来越高,我们有时候可能会遇到对win10系统调整虚拟内存提高运行速度进行设置,如果我们需要对win10系统调整虚拟内存提高运行速度进行设置时,要怎么处理win10系统调整虚拟内存提高运行速度呢?  win10系统调整虚拟内存提高运行速度的修复方案  1.点击开始菜单–所有应用–Windows系统–这台电脑,右键这台电脑,点击选择“属性”进入下一步操作。  2.在打开的系统窗口中,点击左侧的“高级系统设置”进入下一步操作。  3.在

python中使用矢量化替换循环 python中使用矢量化替换循环 Apr 14, 2023 pm 07:07 PM

所有编程语言都离不开循环。因此,默认情况下,只要有重复操作,我们就会开始执行循环。但是当我们处理大量迭代(数百万/十亿行)时,使用循环是一种犯罪。您可能会被困几个小时,后来才意识到它行不通。这就是在python中实现矢量化变得非常关键的地方。什么是矢量化?矢量化是在数据集上实现(NumPy)数组操作的技术。在后台,它将操作一次性应用于数组或系列的所有元素(不同于一次操作一行的“for”循环)。接下来我们使用一些用例来演示什么是矢量化。求数字之和##使用循环importtimestart

See all articles