关键词
1. let
2. const
3. 解构赋值
4. 块级作用域
5. 暂时性死区
6. var const,let区别
let
//作用: 声明变量(可以修改)解决var声明的变量程序结果把控性弱的问题
//let 声明的变量 有全局作用域、函数作用域、块级作用域,初始值是undefined,
//声明的变量,只在`let`命令所在的代码块内有效。
//Es5中没有块级作用域,用立即执行函数模拟代替
//不存在变量提升
//不允许在相同作用域内,重复声明同一个变量。
❀块级作用域:
一个{}就是一个块级作用域 ;在哪个{}声明的变量,就只能在这个{}里用
1.let声明的变量只在其作用域内有效
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
2.`for`循环的计数器,就很合适使用`let`命令。
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function() {
console.log(i); //全局作用域。指向同一内存地址
};
};
//循环结束后i的值为结束条件不满足的情况,即10
a[6]();
// ---------------------------
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function() { //块级作用域,()父作用域,{}子作用域
console.log(i); //每次循环都会给i添加一个地址,值在本轮循环有效
};
}
console.log(a); //数组里存的是10个函数体
a[6](); // 6
❀ 暂时性死区
let声明的变量一定要先声明再使用,因为它不存在变量声明的提升,声明该变量之前的代码区域都称为暂时性死区
//当我们在使用let声明的变量,之前访问该变量时,就会报错
console.log(a);
let a = 10;//报错, Cannot access 'm' before initialization 初始化前无法访问
♥解决:我们使用let声明的变量时,必须先声明,后使用
let a = 'linhan';
console.log(a);//linhan
重名问题:
不允许在相同作用域内,重复声明同一个变量。
let a = 10;
let a = 'linhan';//报错 Identifier 'm' has already been declared 标识符“m"已声明
// -------不同作用域重名不报错-------
let a = 16;
{
let a = 10; //10块级作用域
}
const
//作用:声明一个只读的常量。一旦声明,常量的值就不能改变
//`const`声明的变量不得改变值,这意味着,`const`一旦声明变量,就必须立即初始化,不能留到以后赋值。
//不存在变量提升
//不允许在相同作用域内,重复声明同一个变量。
本质:const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
几种情况下的报错:
1.声明未赋值
const a
console.log(a); // 声明常量未赋值Missing initializer in const declaration
2.声明赋值后重新赋值
const a = 'linhan';
a = 5;
console.log(a); //常量变量不可重新赋值Assignment to constant variable.
//常量中存的是引用类型,直接赋值会报错,但使用方法或者给元素赋值即扩展内容
另外不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性
const arr = [1, 12, 3]
console.log(arr);//[1, 12, 3]
arr = [3, 4, 6]; //不可重新赋值---内存地址
arr.push('linhan') //可以传进去,,引用数据类型可以对内容进行扩展
console.log(arr);//[1, 12, 3,'linhan']
那么当我们需要将引用数据类型里面的属性和值变得不可以扩展,即不可以修改时
我们可以将其冻结
常量中存在的是引用类型,地址和内容都不能修改,需要引用类型冻结
语法:Object.freeze(具体对象名);
实例:
const arr = [1,3,4];
Object.freeze(arr);//冻结该数组
arr.push('linhan');
console.log(arr);//Cannot add property 4, object is not extensible属性不可进行扩展
除此之外,用const声明的常量,其用法和要注意的事项与let声明变量无异,具体可参考let
解构赋值
用法
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
以前,为变量赋值,只能直接指定值。
let a = 1;
let b = 2;
let c = 3;
ES6 允许写成下面这样。
let [a, b, c] = [1, 2, 3];
要点:按照对应位置,对变量赋值。即模式匹配,只要等号两边的模式相同,左边的变量就会被赋予对应的值
❀注意要点:
①:左右两边的数据结构保持一致,把右边的结构直接克隆一份给左边即可
②:变量的数量和数据的数量一般保持一致,变量少于数据,部分数据不会被赋值,变量多于数据,多余变量为undefined
③:解构时可以给变量默认值,解构时如果变量有赋值,就用赋的值,没有赋值就用默认值,其中赋的值为undefined的例外,任然用默认值
④要想被解构成功,就必须有Iterator接口,即可迭代
实例
1.解构一维数组
let arr1 = [1,2,3];//一维数组
let [a,b,c] = arr1;//解构
console.log(a,b,c);//1,2,3
2.解构二维/多维数组
let arr2 = [1,2,[3,'linhan',[null,undefined]]];//多维数组
let [a,b,[c,d,[e,f]]] = arr2
console.log(a,b,c,d,e,f);//1,2,3,'linhan',null,undefined
3.解构对象
const obj = {
name:'linhan',
age:21,
love:['读书','听歌']
};
const {name,age,love[a,b]} = obj
console.log(name,age,a,b)//'linhan',21,'读书','听歌'
❀:对象的解构赋值。变量名和属性名保持一致
一步到位的解构对象时,属性值是引用类型,保留属性名:解构的格式