let与const命令(测试题)

一、CONST

let user = {name:'Lucy',age:17};
const USER_INFO = user;
console.log(user)
console.log(USER_INFO)
user.age = 32;
console.log(user)
console.log(USER_INFO)


结果:

{name:‘Lucy’,age:17}
{name:‘Lucy’,age:17}
{name:‘Lucy’,age:32}
{name:‘Lucy’,age:32}

二、未声明的变量将被自动作为全局变量声明

let a = 'aaa';
alert(window.a);  
var b = 'bbb';
alert(window.b);  
c = 'ccc'
alert(window.c);  


结果:
undefined
bbb
ccc


三、作用域

if(1){
   var a = 1;
   console.log(a)
}
console.log(a)



结果:
1
1

if(1){
  let a = 1;
  console.log(a)
}
console.log(a)



结果:
1
a is not defined

for (var i = 0; i < 3; i++) {
   console.log(i)
}
console.log(i)



结果:
0 1 2
3

for (let i = 0; i < 3; i++) {
   console.log(i)
}
console.log(i)



结果:
0 1 2
i is not defined

for (let i = 0; i < 3; i++) {
  let i = 'aaa';
  console.log(i);
}



结果:
aaa
aaa
aaa

解析:
for循环设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

for (var i = 0; i < 3; i++) {
    var i = 'bbb';
    console.log(i);
}




结果:
bbb

解析:
两个var声明的 i,都指向一个全局的变量 i 。

for (var i = 0; i < 3; i++) {
    let i = 'bbb';
    console.log(i);
}



结果:
bbb
bbb
bbb

for (let i = 0; i < 3; i++) {
    var i = 'aaa';
    console.log(i);
}



结果:
Identifier ‘i’ has already been declared.(已声明标识符“i”)

var a = [];
for (let i = 0; i < 10; i++) {
    console.log(i);
    a[i] = function () {
        console.log(i);//执行此代码时,for循环已经执行完毕。
    };
}
a[6]();




结果:
0 1 2 3 4 5 6 7 8 9
6

var a = [];
for ( var i = 0; i < 10; i++) {
 console.log(i);
 a[i] = function () {
   console.log(i);  //执行此代码时,for循环已经执行完毕,i 的值是10。
 };
}
a[6]();



结果:
0 1 2 3 4 5 6 7 8 9
10

四、变量提升

console.log(a)
var a = 1;



结果:
UNDEFINED

var a = 1;
function foo(){
   if(false){
       var a = 2;
   }
   console.log(a)
}
foo();



结果:
undefined

console.log(a)
let a = 1;



结果:
Cannot access ‘a’ before initialization

解析:
let命令不存在变量提升,所以声明前调用变量,都会报错,这就涉及到一个概念——暂时性死区。

ES6规定,如果区块中存在LET和CONST命令,这个区块对LET和CONST命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。这在语法上,称为“暂时性死区”(TEMPORAL TEAD ZONE,简称TDZ)。

五、暂时性死区

var a = 123;
if (true) {
	// 这里会产生 TDZ for a
   a = 'abc';
   let a;//if区块内, 在let命令声明变量a之前,都属于变量a的“死区”。这里结束 TDZ for a
}



结果:
Cannot access ‘a’ before initialization(初始化前无法访问“a”)

解析:
总之,变量一定要在声明之后使用!!!!!

六、结合SETTIMEOUT、闭包

调用SETTIMEOUT时,把函数参数,放到事件队列中,等主程序运行完,再调用。即便是时间值为0,它也会等主程序执行完再执行,如果主程序队列为空,就会直接调用。

闭包:对函数类型的值进行传递时,保留对它被声明的位置所处的作用域的引用。

for(var i = 0;i < 10; i++){
  console.log(i);
  setTimeout(function () {//同步注册回调函数到异步的宏任务队列
    console.log(i);//执行此代码时,for循环已经执行完毕。
  },0);
}



结果:
0 1 2 3 4 5 6 7 8 9
10 10 10 10 10 10 10 10 10 10

解析:
注意setTimeout函数里面有个匿名函数哦,在执行这个匿名函数中的console.log(i)的时候,因为闭包(保留了对声明i的作用域的引用),var作用域是全局的,现在for执行完了,i的值是10

for(let i = 0;i < 10; i++){
  console.log(i);
  setTimeout(function () {//同步注册回调函数到异步的宏任务队列
    console.log(i);//执行此代码时,for循环已经执行完毕。
  },0);
}



结果:
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9

function foo(){
  for(var i = 0;i < 10; i++){
    console.log(i);  
    setTimeout(function (i) { 
      console.log(i);
    },1000);
  }
  for(var i = 0;i < 3; i++){
    setTimeout(function (i) { 
      console.log(i);
    },1000);
    console.log(i);
  }
}
foo()


结果:
0 1 2 3 4 5 6 7 8 9
0 1 2
3 3 3 3 3 3 3 3 3 3
3 3 3

解析:
setTimeout的意思是传递一个函数,延迟一段时间把该函数添加到队列中,并不是立即执行。
如下图所说,异步任务会把回调函数加到任务队列,等主进程的空闲了,才被读取到主进程中执行。
也就是说所有传递给setTimeout的回调方法都会在整个环境下的所有代码运行完毕之后执行。(这就是为什么先输出for里面的,再输出setTimeout函数里面的)
又如下图所说,任务队列是先进先出的,所以先输出10个3,再输出3个3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JessicaLilyAn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值