在ES6之前,var是声明变量的唯一关键字,但在ES6开始,增加了let和const
var
使用var 声明变量时,变量会添加到最接近的上下文
function add(n1,n2){
var sum = n1+n2;
return sum
}
let result = add(1,2) //返回的是3
console.log(sum) //报错,sum在这里不是有效变量
在add()定义了一个局部变量sum,但是函数外部是无法访问到的
如果省略上方的关键字var,那么sum就能在函数add()之外可以访问;
sum被函数操作结果初始化且并没有使用var声明。在被调用后,sum就被添加到全局上下文。在函数退出后,也会存在。
function add(n1,n2){
sum = n1+n2;
return sum
}
let result = add(1,2) //返回的是3
console.log(sum) //3
var声明会被拿到函数或全局作用域的顶部,位于作用域中所有代码之前。这个现象叫做“提升”。提升让同一作用域中的代码都可以直接使用
- 等价的代码
var name = "mike";
//等价于:
name = "mike"
var name;
function f1(){
var name = "mike"
}
//等价于:
function f2(){
var name ;
name = "mike"
}
在通过声明之前打印变量,可以验证变量会被提升。声明的意味着会输出undefined而不是reference Error:
console.log(name);
var name = "Jake"
function(){
console.log(name);
var name = "Jake"
}
let
这是ES6新增的关键字let ,跟var相似,但是它的作用域是块级的
块级作用域是由最近的一对含花括号{}界定。
是就是语句块(if,function等)单独的块也是let声明变量的作用域
if(true){
let a;
}
console.log(a) //会报错:ReferenceError : a没有定义
while (true){
let b;
}
console.log(a) //会报错:ReferenceError : b没有定义
function foo(){
let c;
}
console.log(c) //会报错:ReferenceError : b没有定义
var声明的话也会导致报错
这不是对象字面量,而是一个独立的块
在此有一点需要声明:let与var不同,let是不能在同一个作用域内声明两次。重复的声明的let会抛出SyntaxError;
let适合在循环中声明迭代变量。使用var声明的迭代变量会泄露到循环外部
for(var i = 0;i<10;i++){}
console.log(i) //10
for( let j = 0;j<10;j++){}
console.log(j) // 抛出异常:ReferenceError :j没有定义
const
使用const的声明变量必须同时初始化某个值。其他方面与let声明一样
const a //SyntaxError :常量声明时没有初始化
const b = 3 ;
console.log(b); //3
b = 4 //TypeError 给常量赋值
const声明只应用到顶级原语或者对象。换句话说,赋值对象的const变量不能再被重新赋值为其他引用值,但还是对象的键则不受限制
const obj1 = {}
obj1 = {} //TypeError 给常量赋值
const obj2 = {}
obj2.name = "mike"
console.log(obj2.name) //"mike"
如果想让整个对象不能修改,可以使用Object.freeze()
const obj3 = Object.freeze({})
obj3 .name = "mike"
console.log(obj3 .name) //undefined