JavaScript同步和异步

  • 同步:从上到下按顺序执行,默认情况下, 编写的代码都是同步的
  • 异步:随时可以执行,所有函数的执行都是异步的
    异步典型:for循环中定义函数
    // 只有i加到10才不满足条件, 所以循环执行完毕i=10
    for(var i = 0; i < 10; i++){
        // 所有函数的执行都是异步的
        function test() {
            // 当函数调用时循环已经执行完毕了, 所以拿到的是10,
           //此处定义函数但并未执行,所以不会打印i
            console.log(i);
        }
    }
    // 只有for循环执行完毕, 才会执行调用test的代码
    test();  //10

改进:如果想要使for循环中的i和函数保持同步

    for(var i = 0; i < 10; i++){
        // 想要test函数中输入的i和循环的i同步, 必须每次执行循环都调用一次
        function test() {
            // 每次执行循环都调用了一次函数, 所以i就是当前的值
            console.log(i);
        }
        test();
    }

优化:上述代码的另一种写法

    for(var i = 0; i < 10; i++){
//    立即执行函数,定义后马上执行
        (function(index) {
            console.log(index);
        })(i);
    }
  • 范例

    // 1.拿到所有的按钮
    var oBtns = document.querySelectorAll("button");
    // 2.给所有按钮添加点击事件
    // 默认情况下所有的代码都是同步的
    for(var i = 0, len = oBtns.length; i < len; i++){
        var oBtn = oBtns[i];
        // 这里的立即执行函数是为了保证index的值和循环的值同步
        // 这里的立即执行函数保存了将来事件异步函数要用到的index
        (function (index) {
            // 这里注册的事件是一个闭包, 闭包中用到了刚才同步的index,
            // 所以每一个立即执行函数都不会被销毁,而是保留在内存中
            // 所以将来执行闭包时可以拿到index(闭包的要义)
            oBtn.onclick = function () {
                // 监听点击事件的函数, 用到了其它函数中的变量
                // 所以这里监听事件的函数, 是一个闭包
                console.log(index);
            }
        })(i);
    }
  • ES6解决了这个问题
    上代码
        window.onload=function (){
            let aInput = document.querySelectorAll('input');

            for(let i=0; i
  • 原因:因为ES6新增了块级作用域的概念
    变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是对应的i值。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

你可能感兴趣的:(JavaScript同步和异步)