小生现在还是一名大三学生,本专业是工程管理,因为喜欢前端,从大二开始自学,大二上中期加入学院一个前端工作室。工作室从大三开始每周会有一次技术的分享(大三的会讲讲深一点的JavaScript和css知识,大二会把自己平时学习的体会心得拿出来讲),有一次我在讲到JavaScript的异步执行的运行机制,使用setTimeout来做的例子。
首先写一小段代码:
setTimeout( function () { console.log(1); } , 1000);
setTimeout( function () { console.log(2); } , 800);
setTimeout( function () { console.log(3); } , 600);
明白异步执行的,相信大家都知道打印的顺序吧
具体来说,异步执行的运行机制如下:
(1)所有同步任务都在主线程上执行,形成一个执行栈。
(2)主线程之外,还存在一个"任务队列"。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
根据每个函数的设置的时间,第三个函数最先进入任务队列,第二个函数第二,第一个函数最后进入。所以弹出3 2 1.
但是又有一种情况:
setTimeout( console.log(1) , 1000);
setTimeout( console.log(2) , 800);
setTimeout( console.log(3) , 600);
这里涉及到另外一个问题:回调函数
"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。
所谓"回调函数"(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。
console.log(1) ,console.log(2),console.log(3)并不是构成回调函数,所以它们根本没有进入任务队列:而是按照正常的顺序在执行栈中被执行了。
第二种情况是我在讲的时候,下面一位听讲的同学在自己电脑控制台执行出来的。当时问题没有的到解决,后来我再去搜了一些资料。后面一次分享会,把自认为准确的答案给大家讲了,一位问题就这么解决了。没想到又有一个问题抛出来,把console.log(1) ,console.log(2),console.log(3)各自都加上引号就可以像第一个情况那样运行。
这时的我又蒙了,分享会完之后我就马上去查了资料,可是做了无用功,并没有找到答案,后来在看一本JavaScript的书时,找到了答案。就是标题所说的双重求值。
JavaScript像其他其他语言一样,允许在程序中提取一个包含代码的字符串,然后动态执行。有四种表中方法可以实现:eval()、Function()构造函数、setTimeout()和setInterval()
var num=1,num2;
//eval()执行代码字符串
sum = eval("num1 + num2");
//Function()构造函数执行代码字符串
sum=Function("num1","num2","return num1 +num 2");
//setTimeout()执行代码字符串
setTimeout("sum=num1 +num2",100);
//setInterval()执行代码字符串
现在问题终于都解决了~~这以前都是些知识点类随笔,这是我第一次写学习总结类的随笔。