js提前声明了全局变量,然后在局部作用域里面赋值,再到全局作用域取值就获取不到变量了?

js提前在局部作用域的外面声明了一个变量, 然后在局部作用域里面赋值,再到全局外面取这个赋值后的变量,.却读取不到是什么原因呢?

            var new_time;
            setInterval(function(){
                if(code_time<=30&&code_time>0){
                    code_time--;
                    $("#send-code").text(code_time+"S");
                    new_time=code_time;
                    console.log(new_time) //输出正常值
                }
                // else{
                //     $("#send-code").removeAttr("disabled");
                //     $("#send-code").text("发送验证码");
                //     $("#send-code").css("background","#e32f1c");
                // }
            },1000);
            console.log(new_time) // 输出undefined

图片描述

想在全局外面读取局部里面赋值后的变量 new_time.. 但是读取到最上面未赋值的变量输出undefined

阅读 8.7k
7 个回答

setInterval异步执行,也就是说打印的时候,该函数还没执行,也就没有作出改变,也就返回undefined。你可以这么修改:

       var new_time;
       async function fn(){
            if(code_time<=30&&code_time>0){
                code_time--;
                $("#send-code").text(code_time+"S");
                new_time=code_time;
                console.log(new_time) //输出正常值
            }
            // else{
            //     $("#send-code").removeAttr("disabled");
            //     $("#send-code").text("发送验证码");
            //     $("#send-code").css("background","#e32f1c");
            // }
        }
        let timer = setInterval(fn,1000);
        fn().then(() => {console.log(new_time)})
 

你这个setInterval是异步的 执行顺序是 var new_time; console.log(new_time); 最后再执行setTinterval

setInterval 函数调用时不会立即执行它的回调函数,而是异步执行的。

执行到 console.log 时候,setInterval 的回调(也就是去给 new_time 赋值的函数)还没有执行,也就没有给 new_time 赋值。

先理解异步再说

var new_time;
console.log(new_time);
setInterval(...)

这是你截图代码的执行顺序,你先定义了变量new_time,1s后进行赋值,打印在定时器外面。

简化代码,做个实验就能明白个七七八八

function test() {
    var new_time;
    console.log("[1]", new_time);
    let counter = 0;
    const timer = setInterval(function() {
        new_time = new Date();
        console.log("[2]", new_time);
        if (++counter > 5) {
            clearInterval(timer);
        }
    }, 1000);
    console.log("[3]", new_time);
}

test()

运行结果

[1] undefined
[3] undefined
[2] 2019-07-11T03:51:39.235Z
[2] 2019-07-11T03:51:40.236Z
[2] 2019-07-11T03:51:41.237Z
[2] 2019-07-11T03:51:42.237Z
[2] 2019-07-11T03:51:43.238Z
[2] 2019-07-11T03:51:44.238Z

注意,[1] 后面是 [3],不是 [2]

可以看出来,setInterval() 中的代码是在一定时间之后才执行的(如果给 new_time 赋了初始值就更明显。这是因为 setInterval() 中的是异步代码,它和主流程中的代码不是走在同一个阻塞线上。

接下来改造一个,我们用 async/await 来等待异步过程结束

async function testAsync() {
    var new_time;
    console.log("[1]", new_time);
    let counter = 0;
    await new Promise(resovle => {
        const timer = setInterval(function() {
            new_time = new Date();
            console.log("[2]", new_time);
            if (++counter > 5) {
                clearInterval(timer);
                resovle();
            }
        }, 1000);
    });
    console.log("[3]", new_time);
}

testAsync()

输出

[1] undefined
[2] 2019-07-11T03:54:52.675Z
[2] 2019-07-11T03:54:53.675Z
[2] 2019-07-11T03:54:54.675Z
[2] 2019-07-11T03:54:55.675Z
[2] 2019-07-11T03:54:56.675Z
[2] 2019-07-11T03:54:57.675Z
[3] 2019-07-11T03:54:57.675Z

可以看到 [3] 是在异步结束之后执行的,因为异步过程用 Promise 封装之后,还使用 await 来等待它结束。

关于异步过程,我一时半会儿也不好解释清楚,给你推荐几个参考:

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题