第 120 题:为什么 for 循环嵌套顺序会影响性能?

发布于 2022-07-30 23:12:30 字数 440 浏览 183 评论 32

var t1 = new Date().getTime()
for (let i = 0; i < 100; i++) {
  for (let j = 0; j < 1000; j++) {
    for (let k = 0; k < 10000; k++) {
    }
  }
}
var t2 = new Date().getTime()
console.log('first time', t2 - t1)

for (let i = 0; i < 10000; i++) {
  for (let j = 0; j < 1000; j++) {
    for (let k = 0; k < 100; k++) {

    }
  }
}
var t3 = new Date().getTime()
console.log('two time', t3 - t2)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(32

空心空情空意 2022-05-04 13:55:02

两个循环的次数的是一样的,但是 j 与 k 的初始化次数是不一样的

  • 第一个循环的 j 的初始化次数是 100 次,k 的初始化次数是 10w 次
  • 第二个循环的 j 的初始化次数是 1w 次, k 的初始化次数是 1000w 次

所以相同循环次数,外层越大,越影响性能

应该不是吧, let是每次循环都会声明一个新的 i 、j 、 K ,所以

1.   i : 100       j:  100*1000       k : 100 * 1000 * 10000
2.   i: 10000    j:10000 * 1000   k: 10000 * 1000 *100

每一次for循环只会初始化一次而已。后面的循环是不会初始化。

我在网上看到的文章都是这样说的,let 每一轮都是一个新声明的变量的,你看看这里
还有这里

梦明 2022-05-04 13:55:02


可以参考这本书



按照你的示例,结果却是相反的。

预测,不能保证百分之百,就像天气预报似的,刷新一次,会有不同的结果。

萌酱 2022-05-04 13:55:02

两个循环的次数的是一样的,但是 j 与 k 的初始化次数是不一样的

  • 第一个循环的 j 的初始化次数是 100 次,k 的初始化次数是 10w 次
  • 第二个循环的 j 的初始化次数是 1w 次, k 的初始化次数是 1000w 次

所以相同循环次数,外层越大,越影响性能

应该不是吧, let是每次循环都会声明一个新的 i 、j 、 K ,所以

1.   i : 100       j:  100*1000       k : 100 * 1000 * 10000
2.   i: 10000    j:10000 * 1000   k: 10000 * 1000 *100

每一次for循环只会初始化一次而已。后面的循环是不会初始化。

我在网上看到的文章都是这样说的,let 每一轮都是一个新声明的变量的,你看看这里
还有这里

噢噢,let 每次循环都会初始化,var 是每个for循环只初始化一次

笑梦风尘 2022-05-04 13:55:02

我测试了一下 使用var和let的区别,为什么var比let性能差那么多呀?有大佬知道吗?

七度光 2022-05-04 13:55:02

内循环多的话,在跳出内部循环的之前,会动态记录和调整转移指,这部分工作需要消耗一定的时间,第二个 内循环跳出的次数多,导致耗时较多。

送君千里 2022-05-04 13:55:02


初始化值是正解啊

黄昏下泛黄的笔记 2022-05-04 13:55:02


这... 难道是我的chrome比较新?为什么得到的答案完全不一样

小瓶盖 2022-05-04 13:55:02

for循环中使用let,js引擎会为每一次循环初始化一个独立作用域和变量。
所以,第一种情况:
i 初始化次数:100,j 初始化次数:100 * 1000,k 初始化次数:100 * 1000 * 10000
第二种情况:
i 初始化次数:10000,j 初始化次数:10000 * 1000,k 初始化次数:10000 * 1000 * 100
通过比较可得
第二种情况,需要初始化的次数较多,所以耗时较长。

开始看清了 2022-05-04 13:55:02

我测试了很多次,发现每次的结果都不尽相同。但是当循环次数到达亿级的时候试了很多次输出的结果没有嵌套的比嵌套的使用时间更长。有大佬知道为什么吗?

何以畏孤独 2022-05-04 13:55:02

学习了,for的嵌套顺序不同,原来是因为每个值初始化的次数不一样,学习了

爱人如己 2022-05-04 13:55:02

同问为什么 var 和 let 时间差这么多,一直以为 var 用在循环里面会比较好,哪位大佬来解惑

2022-05-04 13:55:01

两个循环的次数的是一样的,但是 j 与 k 的初始化次数是不一样的

  • 第一个循环的 j 的初始化次数是 100 次,k 的初始化次数是 10w 次
  • 第二个循环的 j 的初始化次数是 1w 次, k 的初始化次数是 1000w 次

所以相同循环次数,外层越大,越影响性能

var a = 0;
var b = 0;
var t1 = new Date().getTime()
for (let i = 0; i < 10; i++) {
a++
  for (let j = 0; j < 20; j++) {
a++
    for (let k = 0; k < 30; k++) {
a++
    }
  }
}
var t2 = new Date().getTime()
console.log('first time', t2 - t1)

for (let i = 0; i < 30; i++) {
b++
  for (let j = 0; j < 20; j++) {
b++
    for (let k = 0; k < 10; k++) {
b++
    }
  }
}
var t3 = new Date().getTime()
console.log('two time', t3 - t2)  

console.log(a) //6210
console.log(b) //6630

你说的两个循环的次数的是一样的,可是我打印出来的a,b的数值是不一样的,这是为什么呢?

年少掌心 2022-05-04 13:55:01

两个循环的次数的是一样的,但是 j 与 k 的初始化次数是不一样的

  • 第一个循环的 j 的初始化次数是 100 次,k 的初始化次数是 10w 次
  • 第二个循环的 j 的初始化次数是 1w 次, k 的初始化次数是 1000w 次

所以相同循环次数,外层越大,越影响性能

var a = 0;
var b = 0;
var t1 = new Date().getTime()
for (let i = 0; i < 10; i++) {
a++
  for (let j = 0; j < 20; j++) {
a++
    for (let k = 0; k < 30; k++) {
a++
    }
  }
}
var t2 = new Date().getTime()
console.log('first time', t2 - t1)

for (let i = 0; i < 30; i++) {
b++
  for (let j = 0; j < 20; j++) {
b++
    for (let k = 0; k < 10; k++) {
b++
    }
  }
}
var t3 = new Date().getTime()
console.log('two time', t3 - t2)  

console.log(a) //6210
console.log(b) //6630

你说的两个循环的次数的是一样的,可是我打印出来的a,b的数值是不一样的,这是为什么呢?

因为你这累加不对:

  • 第一个循环 10 + 200 + 6000
  • 第二个循环 30 + 600 + 6000

前两个累加去掉才一样,是 6000

还不是爱你 2022-05-04 13:55:01

(一)var a = 1000100100 = 100 + 1001000 + 100100010000;
(二)var b = 1010010000 = 10000+10000
1000+100001000100;
a<b
但大头100001000100不变

浅笑依然 2022-05-04 13:55:01

两个循环的次数的是一样的,但是 j 与 k 的初始化次数是不一样的

  • 第一个循环的 j 的初始化次数是 100 次,k 的初始化次数是 10w 次
  • 第二个循环的 j 的初始化次数是 1w 次, k 的初始化次数是 1000w 次

所以相同循环次数,外层越大,越影响性能

应该不是吧, let是每次循环都会声明一个新的 i 、j 、 K ,所以

1.   i : 100       j:  100*1000       k : 100 * 1000 * 10000
2.   i: 10000    j:10000 * 1000   k: 10000 * 1000 *100
小耗子 2022-05-04 13:55:01

有趣的是在火狐下两次时间差不太多

有趣的还有 , 为什么你的5000+ms 我这只有 几百呀 , 哈哈

放低过去 2022-05-04 13:55:01

两个循环的次数的是一样的,但是 j 与 k 的初始化次数是不一样的

  • 第一个循环的 j 的初始化次数是 100 次,k 的初始化次数是 10w 次
  • 第二个循环的 j 的初始化次数是 1w 次, k 的初始化次数是 1000w 次

所以相同循环次数,外层越大,越影响性能

应该不是吧, let是每次循环都会声明一个新的 i 、j 、 K ,所以

1.   i : 100       j:  100*1000       k : 100 * 1000 * 10000
2.   i: 10000    j:10000 * 1000   k: 10000 * 1000 *100

每一次for循环只会初始化一次而已。后面的循环是不会初始化。

陌若浮生 2022-05-04 13:55:01


可以参考这本书

尘世孤行。 2022-05-04 13:55:01


可以参考这本书



按照你的示例,结果却是相反的。

海未深 2022-05-04 13:54:59

这里说说我个人的理解:对于这个例子,接下来我们利用三个例子来推算

注意:以下输出结果在不同机型和配置下可能存在差异,但是大小关系是不会变的

首先我们单独来比较最内层的循环,也就是循环 10000 次和 100 次的时长

  var t1 = new Date().getTime()
  for (let k = 0; k < 10000; k++) {
  }

  var t2 = new Date().getTime()
  console.log('first time', t2 - t1)

  for (let k = 0; k < 100; k++) {
  }
  var t3 = new Date().getTime()
  console.log('two time', t3 - t2)

输出: first time 0 two time 0

单独循环 10000 和 100 的时间是相差无几的,基本可以看成一个等量关系。那么差异肯定是在外层嵌套的两个循环了。

我们再来看看另外一个例子:两层嵌套遍历,外层循环次数是 1000,里层循环次数一个是 10000,另一个是 100

  var t1 = new Date().getTime()

  for (let j = 0; j < 1000; j++) {
    for (let k = 0; k < 10000; k++) {
    }
  }

  var t2 = new Date().getTime()
  console.log('first time', t2 - t1)

  for (let j = 0; j < 1000; j++) {
    for (let k = 0; k < 100; k++) {
    }
  }

  var t3 = new Date().getTime()
  console.log('two time', t3 - t2)

输出: first time 5 two time 1

差异就出来了,明显看到循环差异在 2-4 ms,可以看到当外层循环的次数一样是,循环的时长取决于里层循环,里层循环次数越多,执行时间越长。

我们再来看看这样一个例子:两层嵌套循环,里层的循环次数都是 1000,外层循环次数一个是 10000,一个是 1000

  var t1 = new Date().getTime()

  for (let j = 0; j < 10000; j++) {
    for (let k = 0; k < 1000; k++) {
    }
  }

  var t2 = new Date().getTime()
  console.log('first time', t2 - t1)

  for (let j = 0; j < 100; j++) {
    for (let k = 0; k < 1000; k++) {
    }
  }

  var t3 = new Date().getTime()
  console.log('two time', t3 - t2)

输出: first time 5 two time 1

差异就出来了,明显看到循环差异在 2-4 ms,可以看到当内层循环的次数一样是,循环的时长取决于外层循环,外层循环次数越多,执行时间越长。

====== 以上结论都可以根据算法的时间复杂度计算规则得到 =====================================

但是我觉得按照这个说法好像不能很好地解释题目三层嵌套的情况

蓝咒 2022-05-04 13:54:59

从数学的角度分析,已知for循环执行顺序,1:执行变量(仅执行一次)2:执行条件 3:执行代码块区域 4:最后执行++,当执行到第三步时,发现有一个for循环,程序会先执行完内部所有循环 ,之后返回到外部循环。设单次循环执行步骤2和步骤4的时间为T0,内层循环执行代码块区域的时间为T1,内层循环执行的次数为M ,中间层循环执行的次数为N,外层循环执行的次数为X,那么内层循环执行的总次数为MNX,中间层为MX,外层为X,所以循环的总次数为MNX+NX+X,总时间T是执行循环步骤的总时间加上执行代码区域的总时间,即T=(MNX+NX+X)T0+MNXT1,这里代码不变时,T0和T1不变, 总次数MNX不变,(NX+X)越小,所耗费的时间也会越少。

星光不落少年眉 2022-05-04 13:54:58

有趣的是在火狐下两次时间差不太多

皓月长歌 2022-05-04 13:50:40

我尝试了一下只有一层不嵌套的情况,得到的结果似乎不似预期,我认为性能应该是跟执行的次数有关,但是执行相同的次数,没有嵌套的反而是相对时间比较多的

你可以减少次数测试一下,当单循环次数过大,在相同循环次数的情况下,单循环性能比多循环次数差。可能是一个内存空间存放不了过大的数值,再调用一个内存空间。

灯角i 2022-05-04 13:50:04

第二循环
变量 实例化(次数) 初始化(次数)  比较(次数)   自增(次数)
i  1        1     1000     1000
j 1000     1000    1000 * 100   1000 * 100
k 1000 * 100  1000 * 100 1000 * 100 * 10 1000 * 100 * 10
第一循环

变量 | 实例化(次数) | 初始化(次数) | 比较(次数) | 自增(次数)
 i  |    1   |    1   |   10  |  10
 j  |    10   |   10   | 10 * 100  | 10 * 100
 k  | 10 * 100   | 10 * 100   | 10 * 100 * 1000 | 10 * 100 * 1000

主要差别是外层两个变量初始化,比较,自增次数全部减少

贪恋。 2022-05-04 13:34:57

坐等大佬

逆光飞翔i 2022-05-04 13:24:43

有没有大佬讲讲for循环嵌套循环相同循环次数,外层越大,越影响性能的原理是什么,比如V8引擎编译机智?或者什么因素的影响,挺好奇的

旧时光的。容颜 2022-05-04 12:48:15

这里说说我个人的理解:对于这个例子,接下来我们利用三个例子来推算

注意:以下输出结果在不同机型和配置下可能存在差异,但是大小关系是不会变的

首先我们单独来比较最内层的循环,也就是循环 10000 次和 100 次的时长

  var t1 = new Date().getTime()
  for (let k = 0; k < 10000; k++) {
  }

  var t2 = new Date().getTime()
  console.log('first time', t2 - t1)

  for (let k = 0; k < 100; k++) {
  }
  var t3 = new Date().getTime()
  console.log('two time', t3 - t2)

输出: first time 0 two time 0

单独循环 10000 和 100 的时间是相差无几的,基本可以看成一个等量关系。那么差异肯定是在外层嵌套的两个循环了。

我们再来看看另外一个例子:两层嵌套遍历,外层循环次数是 1000,里层循环次数一个是 10000,另一个是 100

  var t1 = new Date().getTime()

  for (let j = 0; j < 1000; j++) {
    for (let k = 0; k < 10000; k++) {
    }
  }

  var t2 = new Date().getTime()
  console.log('first time', t2 - t1)

  for (let j = 0; j < 1000; j++) {
    for (let k = 0; k < 100; k++) {
    }
  }

  var t3 = new Date().getTime()
  console.log('two time', t3 - t2)

输出: first time 5 two time 1

差异就出来了,明显看到循环差异在 2-4 ms,可以看到当外层循环的次数一样是,循环的时长取决于里层循环,里层循环次数越多,执行时间越长。

我们再来看看这样一个例子:两层嵌套循环,里层的循环次数都是 1000,外层循环次数一个是 10000,一个是 1000

  var t1 = new Date().getTime()

  for (let j = 0; j < 10000; j++) {
    for (let k = 0; k < 1000; k++) {
    }
  }

  var t2 = new Date().getTime()
  console.log('first time', t2 - t1)

  for (let j = 0; j < 100; j++) {
    for (let k = 0; k < 1000; k++) {
    }
  }

  var t3 = new Date().getTime()
  console.log('two time', t3 - t2)

输出: first time 5 two time 1

差异就出来了,明显看到循环差异在 2-4 ms,可以看到当内层循环的次数一样是,循环的时长取决于外层循环,外层循环次数越多,执行时间越长。

====== 以上结论都可以根据算法的时间复杂度计算规则得到 =====================================

浮华 2022-05-04 08:52:39

我尝试了一下只有一层不嵌套的情况,得到的结果似乎不似预期,我认为性能应该是跟执行的次数有关,但是执行相同的次数,没有嵌套的反而是相对时间比较多的

倦话 2022-05-04 06:47:55

两个循环的次数的是一样的,但是 j 与 k 的初始化次数是不一样的

  • 第一个循环的 j 的初始化次数是 100 次,k 的初始化次数是 10w 次
  • 第二个循环的 j 的初始化次数是 1w 次, k 的初始化次数是 1000w 次

所以相同循环次数,外层越大,越影响性能

青萝楚歌 2022-05-04 03:23:01

应该是第一个时间少一点,比如,按照每次循环判断来说 (初始化 自增次数类似)

1、i会循环100次,判断i<100 100
j会循环100 * 1000次,判断j<100 100 * 1000
k会循环100 * 1000 * 10000次,判断k<100 100 * 1000 * 10000次

2、i会循环10000次,判断i<100 10000
j会循环10000 * 1000次,判断j<100 10000 * 1000
k会循环100 * 1000 * 10000次, 判断k<100 100 * 1000 * 10000次

虽然判断k<100的次数都是一样的 但是前面两种判断就不一样了,由此可以看见时间长短。

画尸师 2022-05-03 22:50:56

循环次数少的放在外层,减少内层变量的操作(初始化,比较,自增等)次数吧。

歌枕肩 2022-05-03 16:58:33

为什么

~没有更多了~

关于作者

夜巴黎

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

missyouangeled

文章 0 评论 0

三生一梦

文章 0 评论 0

压抑⊿情绪

文章 0 评论 0

☆獨立☆

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文