一、let语句
1、新增概念:块级作用域(全局作用域、函数作用域--局部作用域)
let
允许你声明一个作用域被限制在 块
级中的变量、语句或者表达式。与 var
关键字不同的是, var
声明的变量只能是全局或者整个函数块的。 var
和 let
的不同之处在于后者是在编译时才初始化,没有预编译,var申明变量提升。
比如 :if块中
let a = 1;
if(a){
var c = 3;
let b = 2;
}
console.log(b);//b is not defined
console.log(c);// 3
for循环块中
for(let i = 0; i < 3; i++){
console.log(i);
}
console.log(i);//i is not undefined
通过var的声明,没有块作用域的概念,在一个块中声明,就是在当前作用域中声明(全局作用域、函数作用域)
下面实例中,i是全局变量,a是函数中的局部变量,没有块作用域的概念。
for(var i = 0; i< 2; i++){
}
function func(){
if(true){
var a = 3;
}
console.log(a);//3
}
func();
console.log(i);//2
2、就像const
一样,let
不会在全局声明时(在最顶部的范围)创建window
对象的属性。
var a = 1;
console.log(window.a); //1
let b = 2;
console.log(window.b); //undefined
3、同一个块中,不可以用重复声明
if(true){
let a = 1;
var a = 2; //Identifier 'a' has already been declared
}
4、暂时性死区(没有变量声明提升)
在未声明前,不能使用变量
console.log(b); //报错
console.log(typeof b); //报错
let b = 1;
实例:
let arr = [];
for(let i = 0; i < 10; i++){
arr[i] = function(){
console.log(i);
}
}
arr[5](); //5
二、const语句(Edge12)
常量是块级范围的,非常类似用 let 语句定义的变量,和let语句的特性一样。但常量的值是无法(通过重新赋值)改变的,也不能被重新声明。
我们知道js中的数据类型有原始值和引用值,变量在存储原始值时,变量所指的空间存储的是原始值本身;而变量在存储引用值时,变量所指的空间存储的是引用值的地址。
注意:当修改变量的原始值时,实际上是:变量所指的空间1改为指向空间2
当修改变量的引用值时,实际上是:变量所指的空间地址obj1改为指向空间obj2
var a = 1;
a = 2;
var obj = {};
obj = {name: "zhu"}
所以:在通过const声明赋值原始值和引用值时,不允许改变的变量所指的空间。
那么:赋值的原始值,不会被改变;但赋值的引用值,可以对值进行一些修改。
const a = 1;
const obj = {
name: "zhu"
}
obj.age = 24;
console.log(obj.name, obj.age);//zhu 24
Object.freeze()方法冻结对象:一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。
Object.freeze和const都是无法修改引用值的地址,但可以该地址内容值,除非把对象内的所有的引用值都冰冻住,这样才实现正真的常量无法被修改值的效果
let arr = [1,2,3]
const obj = {
a: arr,
b: 'str'
}
Object.freeze(obj.a);
obj.a[0] = 'b';
console.log(obj) //{a:[1, 2, 3], b: "str"}