Lesson2:ES6简易入门(let、const关键字,结构赋
1. let关键字
let的用途:
在之前写js时候,用var来声明一个变量,es6里面除了var还有其他的声明变量的关键字,let就是其中之一,那么let的用途就是用来声明变量的。
let与var
既然都是声明变量的关键字,那肯定就有区别,要不就不会有第二个了,看看有什么区别。
使用 var 的不足之处:
1.var声明的变量作用于函数内,let声明的变量作用与块级作用域。
任何一对“大括号{ }”中的语句都属于一个块,在大括号里面用let定义的所有变量在大括号外是不可见的,我们称之为块级作用域。
2.用var声明变量的时候会导致“变量提升”。
JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:
'use strict';
function foo() {
var x = 'Hello, ' + y;
alert(x);
var y = 'Bob';
}
foo();
虽然是strict模式,但语句var x = 'Hello, ' + y;
并不报错,原因是变量y
在稍后申明了。但是alert
显示Hello, undefined
,说明变量y
的值为undefined
。这正是因为JavaScript引擎自动提升了变量y
的声明,但不会提升变量y
的赋值。
对于上述foo()
函数,JavaScript引擎看到的代码相当于:
function foo() {
var y; // 提升变量y的申明
var x = 'Hello, ' + y;
alert(x);
y = 'Bob';
}
如果用let重写foo()
:
'use strict';
function foo() {
var x = 'Hello, ' + y;
alert(x);
let y = 'Bob';
}
foo(); //结果:报错 y is not defined
用let关键字来定义y
;这样y
在代码块内就不会提升了。报错是因为用let声明的变量要先声明再使用,上面代码里未声明定义就使用,就只有报错了。
使用let的注意点:
注意1:同一个块级作用域内,不允许重复声明同一个变量。
// 错误示范一:
{
var a =1;
let a =2; //报错,因为a已经用var声明过
}
// 错误示范二:
{
let a =1;
let a= 2; //还是报错,a已经用let声明过。
}
注意2:函数内不能用let重新声明函数的参数
// 错误示范:
function say(word){
let word = 'hello Jack'; //报错:用let重新声明word参数
alert(word)
}
say('hello Lili');
// 函数内用let重新声明word这个参数,会报错的,千万别这么干。
2. const关键字
const 的作用
const是constant(常量)的缩写,const和let一样,也是用来声明变量的,但是const是专门用于声明一个常量的,顾名思义,常量的值是不可改变的。
常量的特点:
1、不可修改
const Name = '张三';
Name = '李四'; // 错误,企图修改常量Name
2、只在块级作用域起作用,这点与let关键字一样。
if(1){
const Name = '张三';
}
alert(Name); //错误,在代码块{ }外,Name失效
3、不存在变量提升,必须先声明后使用,这点也跟let关键字一样。
if(1){
alert(Name);//错误,使用前未声明
const Name = '张三';
}
4、不可重复声明同一个变量,这点跟let也一样。
var Name = '张三';
const Name = '李四';//错误,声明一个已经存在的变量Name
5、声明后必须要赋值
const NAME; //错误,只声明不赋值
使用const的注意点:
const Person = {"name":"张三"};
Person.name = "李四";
Person.age = 20;
console.log(Person);
//结果:正常输出{name: "李四", age: 20}
如上常量是一个对象,常量是可以修改的,为什么呢?
这里用到了传址赋值,什么叫传址赋值?
传址:在赋值过程中,变量实际上存储的是数据的地址(对数据的引用),而不是原始数据或者数据的拷贝。
用const来声明一个对象类型的常量,就是传址赋值。而不可修改的是对象在内存中的地址,而不是对象本身。
所以,这就很好的解释刚刚的这段代码为什么不会报错,而是正常输出了。
上面代码中修改的只是Person本身,修改的是name属性和增加一个属性age,而地址没变,也不可变,所以并没有违背常量不可修改的约定。
但是,如果这样写呢,就会报错:
const Person = {"name":"张三"};
Person.age = 20;
Person = {};
//错误,企图给常量Person赋新值(新地址)
9.12更新
3. 解构赋值
官方的解释:
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
上一段代码进一步解释一下什么叫解构赋值:
var arr = [1,2,3]; // 把数组的值分别赋给下面的变量;
var a = arr[0];
var b = arr[1];
var c = arr[2];
console.log(a); // a的值为1
console.log(b); // b的值为2
console.log(c); // c的值为3
以上是传统的变量赋值,将数组的元素值1,2,3分别赋值给变量a,b,c,结果也是如我们所愿,赋值成功。
var [a,b,c] = [1,2,3]; //把数组的值分别赋给下面的变量;
console.log(a); // a的值为1
console.log(b); // b的值为2
console.log(c); // c的值为3
以上是变量的解构赋值,赋值的代码减少了,只需要将变量a,b,c作为一个数组的元素,然后将数组[1,2,3]赋值给数组[a,b,c]即可,变量a,b,c即可分别得到对应的值,这种叫做数组的解构赋值。
数组的解构赋值注意点:
1、结构赋值可以嵌套的
var [ a,b,[ c1,c2 ] ] = [ 1,2,[ 3.1,3.2 ] ];
console.log(c1); // 结果:c1的值为3.1
console.log(c2); // 结果:c2的值为3.2
2、不完全解构
var [a,b,c] = [1,2];
console.log(a); // 结果:a的值为1
console.log(b); // 结果:b的值为2
- 赋值不成功,变量的值为undefined
var [a,b,c] = [1,2];
console.log(a); // 结果:a的值为1
console.log(b); // 结果:b的值为2
console.log(c); // 结果:c的值为undefined
- 允许设定默认值
var [a,b,c=3] = [1,2];
console.log(a); // 结果:a的值为1
console.log(b); // 结果:b的值为2
console.log(c); // 结果:c的值为3
- 重新赋值会覆盖默认值
var [a,b,c=3] =[1,2,4];
console.log(a); // 结果:a的值为1
console.log(b); // 结果:b的值为2
console.log(c); // 结果:c的值为4
⚠️ 注意:当新的值为undefined的时候,是不会覆盖默认值的。
对象的解构赋值
对象的解构赋值跟数组的解构赋值很类似,上代码:
var {a, b, c} = {a: 1, b: 2, c: 3};
console.log(a); // 结果:a的值为1
console.log(b); // 结果:b的值为2
console.log(c); // 结果:c的值为3
对象的解构赋值不会受到属性的排列次序影响(数组则会受影响),它是跟属性名关联起来的,变量名要和属性名一致,才会成功赋值。
var { a, b, c } = {a: 1, c: 3, b: 2};
console.log(a); // 结果:a的值为1
console.log(b); // 结果:b的值为2
console.log(c); // 结果:c的值为3
如果变量找不到与其名字相同的属性,就会赋值不成功:
var { a } = {"b":2};
console.log(a); // 结果:a的值为undefined
💡 变量名与属性名不一样的变量解构赋值:
var { b: a} = {b: 2};
console.log(a); // 结果:a的值为2
对象的结构赋值注意点:
1、对象解构赋值可以嵌套
var {a: {b}} = {a: {b: 1}};
console.log(b); // 结果:b的值为1
2、可以指定默认值
var {a, b=2} = {a: 1};
console.log(b); // 结果:b的值为默认值2
字符串的解构赋值
除了对象和数组可以解构赋值外,字符串也可以结构赋值,上代码:
var [a, b, c, d, e, f] = "热忱一直在!";
console.log(a); // 热
console.log(b); // 忱
console.log(c); // 一
console.log(d); // 直
console.log(e); // 在
console.log(f); // !
解构赋值的用途
一、交换变量的值
var x = 1;
var y = 2;
[x, y] = [y, x];
简单的一行代码即可成功交换x,y的值。
二、提取函数返回的多个值
函数只能返回一个值,我们可以将多个值装在一个数组或者对象中,再用解构赋值获取其中的值。
function foo(){
return {name: "neo", age: 31}
}
var {name, age} = foo();
console.log(name); // 结果:neo
console.log(age); // 结果:31
将foo()的返回值直接通过结构赋值赋给变量name和age,实现快速的提取对应的值。
三、定义函数参数
function foo({name, age}){
console.log(`姓名:${name}`);
console.log(`年龄:${age}`);
}
foo({name: "neo", age: "31", sex: "male"});
通过这种写法, 很方便就能获取JSON对象中想要的参数,例如案例中,只需要获取实参中的:name,age而不需要管其他的参数。