|
本帖最后由 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);
- })()
复制代码
|
|