什么是var的变量提升,在js代码执行时,首先会预编译。
预编译的第一步就是把var的变量进行提升,并赋值undefined。
比如下面代码
var b = 0;
function test(){
console.log(b);
//undefined
var b = 123;
console.log(b);
//123
}
test();
为什么第一个log打印的是undefined,而不是0呢
在test()函数执行时,首先进行的是预编译,看到var b = 123;后,对b进行赋值undefined,
然后再执行函数里面,第一个log此时是undefined//如果函数内部的var 变为let,则不会有这样的问题,let不能变量提升
所以如果代码改成这样
var b = 0;
function test(){
console.log(b);
//Uncaught ReferenceError: Cannot access 'b' before initialization
let b = 123;
console.log(b);
}
test();
会报错,因为let有一个暂时性死区,他不能在定义之前使用
在有形参时,用同名的变量也会报错
function test(b){
let b = 123;
//Uncaught SyntaxError: Identifier 'b' has already been declared
console.log(b);
}
test(123);
但是在for循环时,条件里面的变量和循环体中是两个不同的变量,即使都使用let,也依然不会报错
for(let i = 0; i < 3; i++){
let i = 'mm'
console.log(i);
//mm
//mm
//mm
}
//打印了三次mm
关于for循环 执行函数
let a = [];
for(var i =0; i< 10; i++){
a[i] = function(){
console.log(i);
}
}
a[6]();
//10
//为什么,在这段代码中首先执行for循环,从a[0]开始给a对象添加function,然后执行完毕后,
//i变为10,而这里i是泄漏了的,他在全局中可访问,所以在执行a[6]()时打印的是10
//如果把var改为let
let a = [];
for(let i =0; i< 10; i++){
a[i] = function(){
console.log(i);
}
}
a[6]();
//6
//这里每一个i的结果都可以被保存,所以a[6]()是6
const是一个常量,不能被改变
但是做了一这样写,
const abc = [];
abc.name='daisy';
//这样时可以的,因为这里的abc是一个引用你类型,在修改name时并没有改变abc的引用地址。