let和const
在JavaScript中,我们经常使用var关键字声明变量。直到ES6的发布,增加了许多新特性,其中就有声明变量的关键字增加了let和const。let 声明的变量只在 let 命令所在的代码块内有效,const 声明一个只读的常量,一旦声明,常量的值就不能改变。在 ES6 之前,JavaScript 只有两种作用域:全局变量与函数内的局部变量。
全局变量和局部变量
全局变量声明在函数外部,在JS程序中都可以访问全局变量。
var str = "Hello World!";//全局变量
console.log(str);//外部访问全局变量
function myFun(){
console.log(str);//函数内部访问全局变量
}
myFun();
局部变量声明在函数内,只能在函数内部访问。
function myFun(){
var str = "Hello World!";
console.log(str);//可以访问局部变量
}
myFun();
console.log(str);//无法访问局部变量
块级作用域
块级作用域可以理解为花括号{ } 内的作用域,使用var声明的变量不具块级特性,它在{ }外部也能被访问。
{
var str = "Hello World!";
console.log(str);//可以访问
}
console.log(str);//可以访问
ES6新增的let关键字可以实现块级作用域,比如下面的例子:
{
let str = "Hello World!";
console.log(str);//可以访问
}
console.log(str);//可以访问
尽量声明局部或块级,避免造成全局污染。
变量重定义
由于var关键字没有块级作用域的特性,所以全局声明的变量会被后面相同变量名的变量重定义。
var str = "Hello World!";
{
console.log(str);//Hello World!
var str = "你好";
}
console.log(str);//你好
使用let关键字则会创建新变量,原来变量不会发生改变。
var str = "Hello World!";
{
let str = "你好";
console.log(str);//你好
}
console.log(str);//Hello World
在同一作用域中,var 变量可以重新定义,而let不允许定义存在的变量。
{
var str = "Hello World!";
var str = "你好";//不会报错
}
{
let str1 = "Hello World!";
let str1 = "你好";//会报错
}
{
var str2 = "Hello World!";//会报错
let str2 = "你好";
}
{
let str2 = "Hello World!";
var str2 = "你好";//会报错
}
变量提升
var关键字声明的变量存在变量提升,可以在变量声明之前访问它。
console.log(str);//可以访问
var str = "Hello World";
let关键字则不存在变量提升问题,在声明之前访问就会报错。
console.log(str);//访问不到
let str = "Hello World";
循环作用域
循环作用域也可以看作是块级作用域,使用let和var的效果和块级作用域一样。
for(var i = 0; i <=10; i++){
console.log(i);//可以访问
}
console.log(i);//可以访问
for(let m = 0; m <=10; m++){
console.log(m);//可以访问
}
console.log(m);//不可访问
const关键字
const关键字和let很类似,都是块级作用域,但是const用于声明一个只读的常量。const声明的常量必须赋值初始化,不可修改也不可重新定义,但是引用数据类型除外,这是因为引用数据类型的值指向的是另一个内存空间。
const no = 12;
no = 15;//报错
const no = 15;//也报错
const声明的引用类型常量其实是可以修改的,比如数组和对象,但不能对它重新赋值。
const arr = ["hello","world","你好"];
arr[2] = "大家好";//不会报错
arr = ["hello","world","大家好"];//报错