JavaSscript 函数的执行时机

函数的执行时机与执行环境有着必然的联系

单线程

Javascript语言的执行环境是”单线程”(single thread)。

什么是单线程?

就是一次只能完成一件任务。如果存在多个任务,那就得取号排队,n号任务完成,再执行n+1号任务。

优点

  • 实现较简单,就面对代码就是从上到下执行。
  • 执行环境相对单纯。

缺点

  • 只要一个任务执行耗时很长,后面未执行的任务就需要一直等待。
  • 拖延整个程序的执行。

解决办法

Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。

同步

“同步模式”就是上一段的模式,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;

异步

“异步模式”则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。

注:被作为实参传入另一函数,并在该外部函数内被调用,用以来完成某些任务的函数,称为回调函数。

执行时机

函数的执行时机不一样,就产生不一样的效果。

同步执行时机

直接看例子?

let  a = 1
function fn(){
    console.log(a)
}
fn()   //1
复制代码

明显的从上到下执行代码,一切都平淡无奇。

  1. 声明变量 a 并赋值为 1
  2. 声明函数 fn,该函数可以在控制台输出 a的值
  3. 调用函数 fn()
  4. 输出 1
let  a 
function fn(){
    console.log(a)
}
fn()   //undefined
a=2
复制代码

一切都在掌控中,因为a的赋值在函数调用前。

  1. 声明变量 a
  2. 声明函数 fn,该函数可以在控制台输出 a 的值
  3. 调用函数 fn()
  4. 输出 a //undefined
  5. a 赋值为 2

上面的两个例子可以明显的看出同步执行时机特点,顺序执行

异步执行时机

这一定是你见过无数遍的异步例子?,因为太经典了,经典到新人一看就错。

let i 
for( i = 0; i<6; i++){
    setTimeout(()=>{
        console.log(i)
    },0)
}
复制代码

输出结果: 6 6 6 6 6 6

为什么不是0 1 2 3 4 5

很明显,是0 1 2 3 4 5为什么不放同步的例子呢??

来看一看代码是怎么走的。

  1. 声明变量 i
  2. i 赋值为 0
  3. 判断依据i<6 为true
  4. 进入循环,遇到 setTimeout(定时器)、
  5. setTimeout 表示等会 需要在控制台输出 i
  6. i++
  7. … 反复步骤3、4、5、6
  8. 当i=6 时,循环结束
  9. setTimeout 开始输出 i 的值6,并重复6次

所以 setTiemout 只输出最后 i的值

那 setTimeout 中的 0 怎么解释呢?
setTimeout(fn,0)的含义是当同步任务的函数和语句执行完后,0秒立刻执行fn(实际最小延时 >=4ms),所有这个延时只控制 fn 执行需要等到多少时间。

就想要0 1 2 3 4 5

使用let的块级作用域

for(let i = 0; i<6; i++){
    setTimeout(()=>{
        console.log(i)
    },0)
}
复制代码

因为在for语句里用let声明变量是局部变量遵循块作用域,所以每次for循环执行时都会生成一个单独的作用域,也会生成一个新的i,相当于有6个 i。 此时,每次执行setTimeout()时都会打印出对应的i,打印结果就是0、1、2、3、4、5了。

使用递归

function showTime(count) {
  console.log("count is : ", count);
  if (count == 5) {
      console.log("All is Done!");
  } else {
      count ++;
      setTimeout(function() {
          showTime(count);
      }, 0);
  }
}

showTime(0)
// count is :  0
// count is :  1
// count is :  2 
// count is :  3
// count is :  4
// count is :  5
复制代码

使用自执行函数

function test() {
  for (var i = 0; i < 6; ++i) {
      (function(i){
      setTimeout(function() {
          console.log("index is :", i);
      }, 1000)
      })(i)
  }
}
test();
//index is : 0
//index is : 1
//index is : 2
//index is : 3
//index is : 4
//index is : 5
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享