pidtfork 发表于 2020-10-28 18:20:14

立即执行函数

本帖最后由 pidtfork 于 2020-10-28 18:23 编辑

立即执行函数

js立即执行函数可以让你的函数在创建后立即执行,js立即执行函数模式是一种语法,可以让你的函数在定义后立即被执行,这种模式本质上就是函数表达式(命名的或者匿名的),在创建后立即执行。



什么时候需要立即执行函数

你可能在ubains的模板程序讲过如下代码,里面的()()的写法就是一个立即执行函数,如果没见过也没事,我们一起来看看这个功能。

这个方法实现的效果就是每一秒改变按钮的文本“等待约10秒”、“等待约9秒”....这样的倒计时效果。

var secnum = 10;//倒计时10秒
varsecnumText = "showText"; //显示文本的按钮名称
for(vari = 0; i < secnum; i++) {
    (function(a) {
      delay(i, function() {
         setButtonText(secnumText, "等待约" + (secnum -a) + "秒")
       });
    })(i);
}

//例子2 为什么不能写成这样?
for(vari = 0; i < secnum; i++) {
    delay(i, function() {
      setButtonText(secnumText, "等待约" + (secnum -i) + "秒")
    });
}

分析

在for循环第一次时,这时i = 0,遇到()(i)立即执行函数,i的值作为参数传入了匿名函数,这时执行匿名函数且a的值等于0,匿名函数中执行到 delay时,由于这是一个延时函数,

JavaScript会将delay的参数2的匿名函数放入任务队列,等待主进程执行栈执行完成后再依次执行任务队列函数方法。delay的参数2的匿名函数是一个闭包函数,只有它能访问留在内存中的参数a=0这个值。

当一下次for循环时,i=1,a也等于1,delay的参数2的匿名函数又是一个闭包函数,并且也只有它能访问留在内存中的参数a=1这个值。

所以当任务队列执行时,因为secnum是全局变量固定的值,a的值跟着函数递增,所以 secnum - a会递减形成一个倒计时的效果。


为什么不能写成例子2

因为delay函数是异步函数,for循环10是瞬间完成的,并不会堵塞10s,这样写法虽然能添加10个延时执行,且每个间隔1s执行,但是按钮只会显示 “等待约0秒” 10次而已,因为for循环瞬间执行完后,i的值就等于10了。


立即执行函数的用法

立即执行函数的好处主要由以下两点

一是不必为函数命名,避免了污染全局变量

二是内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。


//声明函数printInfo
function printInfo(data){
    console.log("info 1 " +data);
    console.log("info 2 " +data);
    console.log("info 3 " +data);
}
printInfo("ubains");//通过()来调用此函数

//可以写成这样
(function(data){
    console.log("info 1 " +data);
    console.log("info 2 " +data);
    console.log("info 3 " +data);
})("ubains")


//如间隔5秒发送指令
function startInterval() {
    sendCodeString(COM1,"hello baby");
    delay(5,startInterval);
}
startInterval();

//可以改成这样
(function(){
    sendCodeString(COM1,"hello baby");
    delay(5,arguments.callee);
})()







页: [1]
查看完整版本: 立即执行函数