1. 什么是 ES6
ES 全称 ECMAScript,它是由 ECMA 国际化标准组织制定的一项脚本语言的标准化规范。
2. 为什么使用 ES6
每一次新标准的诞生,都意味着语言的完善、功能的加强。JavaScript 语言本身有一些令人不满意的地方:
- 变量提升特性增加了程序运行时的不可预测性。
- 语法过于松散,实现相同的功能,不同的人可能会写出不同的代码。
3. ES6 新增语法
3.1 let
ES6 中新增了用于声明变量的关键字
3.1.1 let 声明的变量只在所处的块级有效
if (true) {
let a = 10;
}
console.log(a); // a is not defined
注意:使用 let 声明的变量才具有块级作用域,使用 var 声明的变量不具有块级作用域。
3.1.2 不存在变量提升
console.log(a); // a is not defined
let a = 10;
3.1.3 暂时性死区
利用 let 声明的变量会暂时绑定在这个块级作用域,不会受外界影响
var temp = 123;
if (true) {
temp = "abc"; // Cannot access 'temp' before initialization
let temp;
}
3.1.4 经典面试题
var arr = [];
for (var i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
结果:
2
2
let arr = [];
for (let i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
结果:
0
1
3.1.5 小结
- let 就是用来声明变量的
- 使用 let 声明的变量具有块级作用域
- 在一个打括号中使用 let 声明的变量才具有块级作用域,var 声明的变量不具有此特点
- 使用 let 声明可以防止循环变量成为全局变量
- 使用 let 关键字声明的变量不能进行变量提升
- 使用 let 声明的变量具有暂时性死区的特性
3.2 const
声明常量,常量的内存地址不能改变。
3.2.1 具有块级作用域
if (true) {
const a = 10;
}
console.log(a); // a is not defined
3.2.2 声明常量时必须赋值
const PI; // const variable without initializer is not allowed
3.2.3 不可以修改常量的值
const PI = 3.14;
// PI = 100; // Attempt to assign to const or readonly variable
const arr = [100, 200];
arr[0] = "a";
arr[1] = "b";
console.log(arr); // ["a", "b"]
arr = ["a", "b"]; // Attempt to assign to const or readonly variable
3.2.4 小结
- const 声明的变量是一个常量
- 如果声明为常量,基本类型不能更改值,复杂数据类型不能更改地址
- 使用 const 声明常量必须要赋值
3.3 let、const、var 的区别
- 使用 var 声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象
- 使用 let 声明的变量,其作用域为所在的代码块内,无法进行变量提升
-
使用 const 声明的变量,其作用域为所在的代码块内,声明后必须赋初始值
3.4 解构赋值
ES6 中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构。
3.4.1 数组解构
let [a, b, c, d] = [1, 2, 3];
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
console.log(d); // undefined
3.4.2 对象解构
let person = {
name: "lyman",
age: 22
};
let {name, age} = person;
console.log(name); // lyman
console.log(age); // 22
3.4.3 小结
- 解构赋值就是给数组分解,然后给变量赋值
- 如果解构不成功(变量的个数和值的个数不匹配),变量的值为 undefined
- 数组解构用中括号包裹,多个变量用逗号隔开,对象解构用花括号包裹,中间使用逗号隔开
- 利用解构函数可以方便我们去取对象中的属性和方法
3.5 箭头函数
ES6 中新增的定义函数的方式。
语法:
() => {} // () 代表是函数, => 必要的符号,指向哪一个代码块,{} 函数体
const fn = () => {}; // 代表把一个函数赋值给 fn
3.5.1 多参数写法
如果函数体中只有返回值一行代码,则可以省略 return 和大括号
// ES5
function sum(num1, num2) {
return num1 + num2;
}
// ES6
const sum = (num1, num2) => num1 + num2;
3.5.2 单参数写法
如果形参只有一个,可以省略小括号
// ES5
function fn(v) {
return v;
}
// ES6
const fn = v => v;
3.5.3 箭头函数中的 this 关键字
箭头函数不绑定 this 关键字,箭头函数中的 this,指向的是函数定义位置上下文的 this。
const obj = {name: "lyman"};
function fn() {
console.log(this); // obj
return () => {
// this 指向箭头函数定义的位置,那么这个箭头函数定义在 fn 里面
// 而这个 fn 指向的是 obj 对象,所以 this 也指向 obj 对象。
console.log(this);
}
}
const resFn = fn.call(obj);
resFn();
3.5.4 小结
- 箭头函数中不绑定 this,箭头函数中的 this 指向的是它所定义的位置,可以简单理解成,定义箭头函数的位置的 this 指向谁,箭头函数的 this 就指向谁。
- 箭头函数的优点在于解决了 this 指向环境所造成的一些问题,比如:解决了匿名函数的 this 指向问题(匿名函数的执行环境具有全局性),包括 setTimeout 和 setInterval 中使用 this 所造成的问题。
3.5.5 面试题
var age = 100;
var obj = {
age: 20,
say: () => {
alert(this.age)
}
}
obj.say();//箭头函数this指向的是被声明的作用域里面,而对象没有作用域的,所以箭头函数虽然在对象中被定义,但是this指向的是全局作用域
3.6 剩余参数
剩余参数语法允许我们将一个不定数量的参数表示为一个数组,不定参数定义方式,这种方式可以很方便的声明一个不知道参数情况的函数。
function sum(first, ...args) {
console.log(first); // 10
console.log(args); // 20, 30
}
sum(10, 20, 30);
3.6.1 剩余参数和解构赋值配合使用
let students = ["tom", "alice", "jack"];
let [s1, ...s2] = students;
console.log(s1); // tom
console.log(s2); // alice, jack
4. ES6 的内置对象扩展
4.1 Array 的扩展方法
4.1.1 扩展运算符(展开语法)
扩展运算符可以将数组或者对象转为用逗号分隔的参数序列
let arr = [1, 2, 3];
console.log(...arr); // 1, 2, 3
console.log(1, 2, 3); // 1, 2, 3
4.1.2 扩展运算符可以应用于合并数组
// 方法1
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let arr3 = [...arr1, ...arr2];
console.log(arr3); // 1, 2, 3, 4, 5, 6
// 方法2
arr1.push(...arr2);
console.log(arr1); // 1, 2, 3, 4, 5, 6
4.1.3 将伪数组或可遍历对象转换为真正的数组
let divs = document.querySelectorAll("div");
divs = [...divs];
console.log(divs);
4.1.4 构造函数方法
将伪数组或可遍历对象转换为真正的数组
// 创建可遍历对象
let arr = {
"0": "a",
"1": "b",
"2": "c",
length: 3
}
console.log(Array.from(arr)); // ["a", "b", "c"];
方法还可以接收第二个参数,作用类似于数组的 map 方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
// 创建可遍历对象
let arr = {
"0": 1,
"1": 2,
"2": 3,
length: 3
}
let newArr = Array.from(arr, item => item * 3);
console.log(newArr); // [3, 6, 9]
注意:如果是对象,那么属性要写对应的索引。
4.1.5 实例方法 find()
用于找出第一个 符合条件的数组成员,如果没有找到返回 undefined
let objs = [
{
id: 1,
name: "tom",
age: 18
},
{
id: 2,
name: "alice",
age: 22
}
];
console.log(objs.find(item => item.id === 2));
找数组里面符合条件的值,当数组中元素id等于2的查找出来,注意,只会匹配第一个。
4.1.6 实例方法 findIndex()
用于找出第一个符合条件的数组成员的索引,如果没有找到则返回 -1。
let arr = [1, 5, 10, 15];
let newArr = arr.findIndex(value => value > 9);
console.log(newArr);
4.1.7 实例方法 includes()
判断某个数组是否包含给定的值,返回 boolean 类型
let arr = [1, 5, 10, 15];
console.log(arr.includes(10)); // true
console.log(arr.includes(11)); // false
4.2 String 的扩展方法
4.2.1 模板字符串
ES6 新增的创建字符串的方式,使用反引号定义
let name = `lyman`;
模板字符串中可以包含解析变量
let name = "张三";
let sayHello = `hello, my name is ${name}`;
console.log(sayHello); // hello, my name is 张三
模板字符串中可以换行
let result = {
name: 'zhangsan',
age: 20,
sex: '男'
}
let html = `
${result.name}
${result.age}
${result.sex}
`;
在模板字符串中可以调用函数
const sayHello = function () {
return '哈哈哈哈 追不到我吧 我就是这么强大';
};
let greet = `${sayHello()} 哈哈哈哈`;
console.log(greet); // 哈哈哈哈 追不到我吧 我就是这么强大 哈哈哈哈
4.2.2 实例方法 startsWith() 和 endsWith()
- startsWith():表示参数字符串是否在原字符串的头部,返回布尔值
- endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
let str = 'Hello world!';
let flag1 = str.startsWith('Hello'); // true
let flag2 = str.endsWith('!'); // true
console.log(flag1);
console.log(flag2);
注意:区分大小写
4.6.3 实例方法 repeat()
repeat() 方法表示将原字符串重复 n 次,返回一个新字符串
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
4.3 Set 数据解构
ES6 提供了新的数据结构——Set,它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 本身是一个构造函数,用来生成 Set 数据结构
const s = new Set();
Set 构造函数可以接收一个数组作为参数,用来初始化。
const set = new Set([1, 2, 3, 4, 4]); // {1, 2, 3, 4}
4.3.1 实例方法
- add(value):添加某个值,返回 set 解构本身
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示该值是否为 set 的成员
- clear():清除所有成员,没有返回值。
let set = new Set();
set.add(1).add(2).add(3);
set.delete(2);
set.has(2);
set.has(3);
set.clear();
4.3.2 遍历 Set
set.forEach(value => console.log(value));