var关键字
- var 操作符用来声明一个变量,只是简单的对变量进行赋值,并不能标识变量的类型。
var message = 'hi'
//message是一个占位符,保存了'hi'
- 函数内部使用var声明的变量,即全局变量,在函数调用时创建变量并赋值,函数调用结束,变量就会被销毁。
function test(){
var name = "li"
}
console.log(name) //报错
- 在函数内部,不适用任何操作符定义的变量是全局变量(不推荐使用,不好维护)。
function test(){
name = "qq"
}
console.log(name) // qq name为全局变量
- 使用var声明的变量,会存在声明提升,提升到他的作用域顶部,并且JS引擎会将重复的声明合并成一个。
function test(){
console.log(name)
var name = "ll"
}
test() // undefined
以上代码等价于:
function test(){
var name;
console.log(name);
name = "ll"
}
test()
- 使用var声明的变量会挂载到window对象上
var name = "ll"
console.log(window.nam) // ll
- var可以重复声明变量且赋值
var a = '11';
var a = '22';
var a = '33';
console.log(a) // 33
- 因为ECMAScript类型是松散类型,不同类型的初始化可以使用一条语句来声明,使用逗号
var a = 'll',
b = 22,
c = false;
let关键字
- let操作符声明的变量存在临时性死区,不可以先使用在声明
function test(){
console.log(name)
let name = "ll"
}
test() // 报错Cannot access 'name' before initialization
- let会创建块级作用域
if(true){
let a = "ll"
console.log(a) // ll
}
console.log(a) // a is not defined
// a 只在if的代码块内有效
- let 声明的变量不会挂载到window上,但依旧是全局作用域发生,变量会在页面的生命周期内存在
let a = '222'
console.log(window.a) // undefined
- let 不可以重复声明,即使let和var混用也不可以,因为他们不是生命不同类型的变量,只是决定变量的作用域
let a;
let a;
let a;
var a;
var a;
let a;
//以上都会报错
- let 可以重复赋值
let a = '111'
a = '222'
console.log(a) // 222
对于for ,let和var对他的影响
- for循环定义的迭代变量,使用var声明会渗透到循环体外部
for(var i = 0; i < 5; i++){
}
console.log(i) // 5
- for循环定义的迭代变量,使用let声明只在for循环块内部有效
for(let i = 0; i < 5; i++){
}
console.log(i) // i is not defined
- 对于以下代码
for(var i = 0; i < 5; i++){
setTimeout(() => {
console.log(i)
},0)
}
打印结果为5,5,5,5,5,因为在退出循环时,迭代变量被保存为退出循环的值5,那么在执行setTimeout打印出的都是5 4. 对于以下代码
for(let i = 0; i < 5; i++){
setTimeout(() => {
console.log(i)
},0)
}
打印出的结果为0,1,2,3,4;因为JS引擎会在后台为每个迭代变量声明一个新的迭代变量,每个setTimeout()都引用的不同的变量实例,所以输出结构就是期望值
以上代码,适用于所有的for风格,包括for...in / for ...of