为什么我写的JS运行起来很缓慢?

JavaScript013

为什么我写的JS运行起来很缓慢?,第1张

js代码执行速度 很大程度上依赖浏览器的引擎 不同浏览器跑 速度可能会差很多

然后就是算法的时间复杂度 和处理的数据量

还有就是多次操作dom也相当耗时

你要分析下你的代码慢的原因

是循环套循环了?

还是说逻辑太复杂了

如果多次操作dom 导致页面reflow次数过多

渲染次数过多 也可能给你感觉很慢

方案1:针对支持html5 webworker的现代浏览器方案:。

代码1.你的大量计算,放到一个js文件中。如下:

//job.js

onmessage =function (evt){

  //do massive job.在这里你进行大量耗时的计算过程。

  postMessage( data )//将计算结果的数据发送会主线程

}

你的页面代码:

<!DOCTYPE HTML>

<html>

<head>

 <meta http-equiv="Content-Type" content="text/html charset=utf-8"/>

 <script type="text/javascript">

//WEB页主线程

var worker =new Worker("job.js") //创建一个Worker对象并向它传递将在新线程中执行的脚本的URL

 worker.postMessage('开始计算')

 worker.onmessage =function(evt){//接收worker传过来的数据函数

   console.log(evt.data)//输出worker发送来的数据,这里就获取到了大量计算的结果。

 }

 </script>

 </head>

 <body></body>

</html>

方案2:对于不支持WebWorker线程的浏览器。

可以考虑分批处理。即是说创造一个间隔定时器setInterval。

每隔一小段时间,处理大量数据中的一部分。

这样就可以避免大量计算导致浏览器卡死。

大致代码如下(这里是简单的例子。具体情况具体分析。):

假设我们要计算1000万个数据的和。

var jobData =  []//假设是一个数组。里面有1000万个数据。

function sliceJob(){

    var num = (jobData.length / 100) + 1//把任务数据划分为100份。

    var portion = 100000//每份有10万个数字。

    var addition = 0//这里用来保存最后的结果。一开始是0;

    var intv = setInterval(function(){

        if(num--){

            //然后每一份结果。

            additoin += every

        } else {

            计算最后一份,然后输出结果。

            alert('最终结果是:', addition)

            window.clearInterval(intv)

        }

    }, 50)

}

此外。jQuery的deferred对象无法实现你的要求。

因为deferred对象的目的是为了串行处理异步过程。

但是异步过程在执行的过程中,如果耗时过长,仍然会阻塞浏览器线程,导致浏览器不可操作(卡死)。

唯一的一个例外是$.ajax。$.ajax方法也会返回一个Deferred对象。但是由于该异步过程是用的XMLHttpRequest。而xhr默认是异步执行的,相当于另起一个线程,因此不会阻塞浏览器县城。

<script type="text/javascript">

/*对比:

1、map速度比foreach快

2、map会返回一个新数组,不对原数组产生影响,foreach不会产生新数组,foreach返回undefined

3、map因为返回数组所以可以链式操作,foreach不能

4, map里可以用return ,而foreach里用return不起作用,foreach不能用break,会直接报错*/

/*方法一:*/

var arr1 = [1, 2, 3, 4, 5, 6]

for(var i = 0, len = arr1.lengthi <leni++) { //优化性能处理

console.log(arr1[i], 'for遍历出来的数据')//每个item 1,2,3,4,5,6

}

/*方法二:*/

/*forEach方法中的function回调支持3个参数,第1个是遍历的数组内容;第2个是对应的数组索引,第3个是数组本身*/

var arr2 = [{

name: 'bob',

age: 20

},

{

name: 'tom',

age: 18

},

{

name: 'sos',

age: 19

}

]

arr2.forEach((val, i) =>{ //没有返回值的,对原来数组也没有影响

console.log(val, '遍历出来的每个obj')

})

/*方法三:*/

var fruits = [1, 2, 3, 4, 5, 6, 7, 8]

let arr = fruits.map((item, index) =>{

console.log(item, 'top')

console.log(index, 'top')

return item * 8

})

console.log(arr, 'newarr') //[8, 16, 24, 32, 40, 48, 56, 64] "newarr"

var a = fruits.indexOf("Apple", 4)

console.log(a)

//for 和 forEach都是普通循环,map 带返回值并且返回一个新数组;

/*

*当前元素的值,当期元素的索引值,当期元素属于的数组对象

语法:array.map(function(currentValue,index,arr), thisValue)

map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。

map() 方法按照原始数组元素顺序依次处理元素。

注意: map() 不会对空数组进行检测。

注意: map() 不会改变原始数组。

* */

/*方法四:*/

/*兼容写法:

不管是forEach还是map在IE6 - 8 下都不兼容( 不兼容的情况下在Array.prototype上没有这两个方法), 那么需要我们自己封装一个都兼容的方法:*/

/**

* forEach遍历数组

* @param callback [function] 回调函数;

* @param context [object] 上下文;

*/

Array.prototype.myForEach = function myForEach(callback, context) {

context = context || window

if('forEach' in Array.prototye) {

this.forEach(callback, context)

return

}

//IE6-8下自己编写回调函数执行的逻辑

for(var i = 0, len = this.lengthi <leni++) {

callback &&callback.call(context, this[i], i, this)

}

}

/**

* map遍历数组

* @param callback [function] 回调函数;

* @param context [object] 上下文;

*/

Array.prototype.myMap = function myMap(callback, context) {

context = context || window

if('map' in Array.prototye) {

return this.map(callback, context)

}

//IE6-8下自己编写回调函数执行的逻辑var newAry = []

for(var i = 0, len = this.lengthi <leni++) {

if(typeof callback === 'function') {

var val = callback.call(context, this[i], i, this)

newAry[newAry.length] = val

}

}

return newAry

}

</script>