`
唯一602
  • 浏览: 24439 次
  • 性别: Icon_minigender_1
  • 来自: 太原
社区版块
存档分类
最新评论

对JavaScript调用堆栈和setTimeout用法的深入研究

阅读更多

Javascript中会经常用到setTimeout来推迟一个函数的执行,如:

 

setTimeout(function(){alert("Hello World");},1000);

 

会在执行到这句话后延迟1秒钟来弹出alert窗口。那么再看这一段:

 

function a(){
    setTimeout(function() {alert(1)}, 0);
    alert(2);4
}
a();  

 

注意这段代码中的setTimeout延迟设为了0,就是延迟0毫秒,貌似是不做任何延迟立刻执行,即1,2。但实际的执行结果确是2,1。为什么?这得从Javascript调用堆栈(call stack)和setTimeout的功能说起。

首先,JavaScript是单线程的,即同一时间只执行一条代码,所以每一个JavaScript代码执行块会“阻塞”其它异步事件的执行。其次,和其他的编程语言一样,Javascript中的函数调用也是通过堆栈实现的。在执行函数a的时候,a先入栈,如果不给alert(1)加setTimeout,那么alert(1)第2个入栈,最后是alert(2)。但现在给alert(1)加上setTimeout后,alert(1)就被加入到了一个新的堆栈中等待,并“尽可能快”的执行。这个尽可能快就是指在a的堆栈完成后就立刻执行,因此实际的执行结果就是先alert(2),再alert(1)。在这里setTimeout实际上是让alert(1)脱离了当前函数调用堆栈。看下面一个例子:

<input name="input" onkeydown="alert(this.value)" type="text" value="a" />

 

这样一段函数意图是每输入一个字符就把当前input里的所有字符都alert出来,但实际效果确是alert出按键之前的内容。这里,我们就可以利用setTimeout(0)来实现。

<input onkeydown="var me=this; setTimeout(function(){alert(me.value)}, 0)" name="input" type="text" value="a" />

 

这样当onkeydown事件触发的时候,alert就被放入了下一个调用堆栈,一旦onkeydown事件触发的堆栈关闭后就开始执行。当然浏览器还有个onkeyup事件也可以实现我们的需求。

这样的setTimeout用法在实际项目中还是会时常遇到。比如浏览器会聪明的等到一个函数堆栈结束后才改变DOM,如果再这个函数堆栈中把页面背景先从白色设为红色,再设回白色,那么浏览器会认为DOM没有发生任何改变而忽略这两句话,因此我们可以通过setTimeout把“设回白色”函数加入下一个堆栈,那么就可以确保背景颜色发生过改变了(虽然速度很快可能无法被察觉)。

总之,setTimeout增加了Javascript函数调用的灵活性,为函数执行顺序的调度提供极大便利。

分享到:
评论

相关推荐

    JavaScript调用堆栈及setTimeout使用方法深入剖析

    Javascript中会经常用到setTimeout来推迟一个函数的执行并且会在执行到这句话后延迟1秒钟来弹出alert窗口,接下来将介绍一下JavaScript调用堆栈和setTimeout用法,感兴趣的你可不要错过了哈

    JavaScript深入编程网页收集

    VBScript & DHTML 脚本技术讨论版 - 无忧脚本 ---体验编写HTML代码的乐趣 - 51JS_COM_files对JavaScript调用堆栈和setTimeout用法的深入研究 - Felix Woo_files关于Javascript的内存泄漏问题的整理稿 - tim-wu - ...

    JavaScript 对引擎、运行时、调用堆栈的概述理解

    总的来说,深入理解JavaScript的引擎、运行时和调用堆栈对于任何JavaScript开发者来说都是至关重要的。通过这些基础知识,开发者不仅可以编写出更优秀的代码,还能更好地应对性能优化、错误调试等问题,从而提升应用...

    javaScript深入大纲

    ### JavaScript深入大纲知识点详解 #### 一、重识JavaScript及...以上是《JavaScrip深入大纲》中的主要知识点梳理,每个部分都详细介绍了核心概念和技术细节,旨在帮助开发者全面掌握JavaScript的核心技术和最新进展。

    javascript中clipboardData对象用法详解.docx

    -- 不能直接在oncopy中调用ModifyCopyData函数,需设定定时器,0.1秒后执行,这样就不再oncopy的执行调用堆栈上了 --&gt; ``` #### 六、注意事项 1. **兼容性问题**:`clipboardData`仅适用于Internet Explorer...

    微信小程序—setTimeOut定时器的问题及解决

    初始尝试中,开发者使用了递归调用`startReportHeart`来实现定时获取位置,但由于理解错误,导致了无限递归和堆栈溢出的问题。错误代码如下: ```javascript startReportHeart() { var timerTem = setTimeout...

    JavaScript 50道面试题和答案.docx

    JavaScript是一种广泛应用于Web开发的脚本语言,尤其在前端领域占据主导地位。了解JavaScript的基础和高级概念对于成为一名合格的前端...深入理解和掌握这些概念,能够帮助开发者编写更高效、更健壮的JavaScript代码。

    突破JavaScript编程实例五十讲

    - 回调函数:介绍异步编程的基础,如setTimeout和XMLHttpRequest,以及回调地狱的问题。 - Promise与async/await:讲解Promise解决回调问题的方式,以及async/await语法糖带来的更简洁的异步编程体验。 7. **模块...

    prod_server:音乐制作人和 DJ 的堆栈溢出

    开发者需要对JavaScript的内存模型有深入理解,并且熟练运用上述技巧来预防和解决堆栈溢出问题。 在"prod_server-master"这个压缩包中,可能包含了该服务器应用的源代码、配置文件、文档和其他资源。通过分析这些...

    JavaScript 50道面试题及答案.docx

    - JavaScript数组提供了`shift`、`unshift`、`push`和`pop`等方法来模拟堆栈操作。 - `shift`用于移除并返回数组的第一个元素。 - `unshift`在数组开头添加元素并返回新长度。 - `push`在数组末尾添加元素并返回...

    javascript技术文档

    本技术文档旨在深入解析JavaScript的核心概念、语法特性以及实际应用,帮助开发者更好地理解和掌握这门语言。 1. **基本概念** - **解释型语言**: JavaScript是一种解释型的、面向对象的语言,代码无需预编译,...

    【JavaScript源代码】代码解析React中setState同步和异步问题.docx

    React仍然可能会对这些状态更新进行延迟或合并,特别是当它们发生在同一堆栈中时。如果需要确保状态更新后的操作基于最新状态,可以提供一个回调函数给`setState`,该回调将在组件完成渲染后被调用: ```jsx this....

    JS调试.zip

    2. **断点调试**:在源代码的特定行设置断点,当程序运行到这一行时会暂停,让你有机会检查此时的变量值、调用堆栈等信息。这对于理解代码流程和查找错误非常有帮助。 3. **步进执行**:在暂停后,可以通过“步入”...

    javascript定时器完整实例

    7. 定时器的嵌套调用也有可能导致所谓的“堆栈溢出”,特别是当定时器设置过于频繁时。因为每次调用 `setTimeout()` 都会在浏览器的事件队列中添加一个任务,如果嵌套层次过深,会导致调用栈过长,从而可能导致...

    node-superstack:node.js 的长堆栈跟踪

    超级堆栈 node.js 在 async/io 边界上的长堆栈跟踪 ... 您的堆栈跟踪现在将超出异步调用边界。 从上面的代码。 超级堆栈之前 Error: foo at f [as _onTimeout] (.../node-superstack/foobar.js:2:11)

    recursive-visualizations:一点JS来可视化可步进树中的递归函数

    7. **调试技巧**:学习如何使用浏览器的开发者工具进行函数调用堆栈的分析,这对于理解和优化递归函数非常有用。 8. **性能优化**:在处理大量递归调用时,可能需要考虑性能优化,例如减少不必要的计算或使用尾递归...

Global site tag (gtag.js) - Google Analytics