var关键字
var可以声明一个变量,当未赋值时其值未undefined,var声明的变量不仅可以重新赋值,还可以改变指的类型,例如:
var message='hi'
message=100
上面的例子对var声明的变量,不仅重新赋值也改变了变量的类型。
1. var声明作用域
var声明的变量也分为全局变量和局部变量:
全局变量:在js文件函数体外定义的变量为全局变量,在函数体中也可以使用。
局部变量:在函数中定义的var 变量为局部变量,该变量只在函数中奏效,随着函数体}结束而销毁。
注意:在函数体中直接用 a=10,的方式定义的变量为全局变量,一般不建议这种方式定义。
例如:
function test(){
message=10
}
console.log(message) //输出为10,变为了全局变量
拓展:声明多个变量还可以使用var a='xxx',b=10,c=true;
2. var声明提升
使用var声明的变量,下面代码不会报错,这是因为是用这个关键字提升的变量会自动提升到函数作用域顶部:
function foo(){
console.log(message)
var message=10
}
foo() //输出为undefined
上面的代码不会报错即因为变量提升的缘故,但是变量提升并不会对值的提升所以上面的例子输入为undefined,即等价于:
function foo(){
var message;
conole.log(message)
message=10
}
foo()
另外反复多次声明一个变量也没有问题,例如:
function foo(){
var age=10
var age=20
var age=30
}
上述例子并不会报错即因为var可以反复多次声明一个变量,后面的const却不可以。
let声明
let跟var作用差不多,但最大的区别时var声明的变量作用域是函数作用域,而let是块作用域,例如:
//var声明
if(true){
var name='xxx'
console.log(name) //输出:xxx
}
console.log(name) //输出:xxx
//let声明
if(true){
let age=26
console.log(age) //输出:26
}
console.log(age) //报错
let不允许同一个块作用域中出现冗余声明,这点即和var不一样。
//var冗余声明不会报错
var name;
var name;
//let冗余声明会报错
let age;
let age;
拓展
- 嵌套声明的let变量不会报错,如下:
let age=20
console.log(age)
if(true){
let age=26
console.log(age)
}
上述例子let重复声明并不会报错是因为let声明的变量不在一个块级作用域内
- 声明的变量并不会因为var let混用而不出现冗余报错:
let age=22
var age=33
var name='w'
let name='e'
上述的声明依然会出现冗余报错
let的其他特性
1. let声明的变量在作用域中不会被提升
console.log(age) //报错
let age=10
2. let全局声明的变量并不会成为window对象的属性,而var声明的变量会成为window对象的属性
var name=10
console.log(window.name)//输出为10
let name=10
console.log(window.name) //undefined
3. for循环中的let声明
- let的for循环变量不会渗透到循环体外面,而for循环的变量会渗透到循环体的外面:
for(var i=0;i<5;i++){
}
console.log(i) //输出5
for(let i=0;i<5;i++){
}
console.log(i) //报错
- for循环中let和var迭代变量的声明和修改:
let的迭代声明:
for(let i=0;i<5;i++){
setTimeout(()=>{console.log(i)},0)
}
//输出 0,1,2,3,4
上述例子中会为每个迭代循环声明一个新的迭代变量,每个setTimeout引用的都是不同的迭代变量。
var的迭代声明:
for(var i=0;i<5;i++){
setTimeout(()=>{console.log(i)},0)
}
//输出:5,5,5,5,5
上述例子中迭代变量保存的是导致退出循环的i值,所以输出:5,5,5,5,5。
const声明
const与let基本相同,区别在于声明变量的同时必须初始化,且const初始化好的变量不可修改。
const age=16
age=18 //会报错,给常量赋值
const不允许重复赋值
const age=18
const age=12 //报错
const声明的作用域也是块
const name=16
if(true){
const name=18
}
console.log(name) //输出16
const声明的限制只适用于它指向的变量的引用,即const引用的是一个对象,修改对象内部的属性不会报错。
const person={}
person.name='david'
const在for循环中不可作为迭代变量,因为修改了其值,但是在for-of,for-in中可以使用,每次迭代相当于创建了一个新的变量。
for(const i=0;i<10;i++){} //报错
for(const key in {a:1,b:2}){
console.log(key)
}
//输出:a b
for(const value of [1,2,3]){
console.log(value)
}
//输出:1,2,3