此文为学习 尚硅谷Web前端ES6教程,涵盖ES6-ES11 记录的笔记
ES6
let变量声明
- 变量不能重复声明
let i = 1;
let i = 2; // error
- 块级作用域
{
let i = 1;
}
console.log(i); // error
- 不存在变量提升
console.log(i); // error
let i = 1;
- 不影响作用域链
{
let i = 1;
function fn() {
console.log(i); // 1
}
fn();
}
const声明常量
- 常量声明时需要赋初始值,一般常量名使用大写
const ERROR; // error
- 常量值不能修改
const ERROR = "error";
ERROR = ""; // error
- 块级作用域(同let)
- 对于数组和对象值的修改,不算对常量的修改
const ARR = ["a", "b"];
ARR[0] = "c";
ARR.push("d");
const OBJ = {
name: "a"
}
OBJ[name] = "b";
OBJ.age = 10;
变量的解构赋值
- 数组解构
let arr = ["a", "b"];
const [a, b] = arr;
- 对象解构
let obj = {
name: 'horizon',
age: 23
};
const {name, age} = obj;
模板字符串
// 使用 `` 定义模板字符串
const key = "key"
const str = `${key}-value`
对象的简化写法
const name = "horizon";
const age = 23;
const user = {
name,
age
eat() {
console.log('eat');
}
};
箭头函数
- this是静态的。this 始终指向函数声明时所在作用域下的 this 的值
function getName() {
console.log(this.name);
}
const getName2 = () => {
console.log(this.name);
}
window.name = 'horizon';
getName(); // horizon
getName2(); // horizon
const user = {
name: 'jeson'
}
getName.call(user); // jeson
getName2.call(user); // horizon
- 不能作为构造实例化对象
const Persion = (name) => {
this.name = name;
}
const me = new Persion('horizon'); // error
- 不能使用 arguments 变量
const fn = () => {
console.log(arguments); // error
}
- 箭头函数的简写
// 1. 当形参有且只有一个时,可以省略小括号
const fn = n => {
return n + n;
}
// 2. 当代码体只有一条语句时,可以省略花括号,且如果该语句是返回值的语句,必须省略 return
const pw = n => n * n;
- 箭头函数的使用场景
- 适合与 this 无关的回调,如定时器、数组的方法回调
- 不适合与 this 有关的回调,如事件回调,对象的方法
函数参数的初始值,一般位置要靠后
- 形参初始值,
function incr(a, b = 1) {
return a + b;
}
console.log(incr(10)); // 11
- 与解构赋值结合
function getName({name = 'horizon'}) {
console.log(name);
}
getName(); // horizon
getName({name: 'jeson'}); // jeson
rest参数
rest参数用于获取函数的实参,用来代替 arguments
// arguments是对象
function output() {
console.log(arguments);
}
// args是数组,必须放在参数的最后一个位置
const output2 = (...args) {
console.log(args);
}
扩展运算符
[…] 扩展运算符能够将【数组】转换为逗号分隔的【参数序列】
function output(a, b) {
return a + b;
}
const arr = [1, 2];
console.log(output(...arr)); // 3
- 扩展运算符的应用
- 数组的合并
- 数组的克隆
- 将伪数组转为真正的数组
Symbol
新的原始数据类型,表示独一无二的值,Symbol的特点:
- Symbol的值是唯一的,用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol定义的对象不能使用 for…in 循环符,但是可以使用 Reflect.ownKeys 来获取对象的所有键名
迭代器
迭代器是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署了 Iterator 接口(对象里的一个属性:Symbol.iterator),就可以完成遍历操作
- ES6创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费
- 原生具备 Iterator 接口的数据(可用 for…of 循环)
- Array
- Arguments
- Set
- Map
- String
- TypeArray
- NodeList
- 工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的 next 方法,指针自动指向数据的第一个成员
- 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个
- 每调用 next 方法返回一个包含 value 和 done 属性的对象
const user = {
name: 'horizon',
skill: ['java', 'js', 'ts'],
[Symbol.iterator]() {
let i = 0;
return {
next: () => {
if (i < this.skill.length) {
const result = {
value: this.skill[i],
done: false
}
i++;
return result;
} else {
return {
value: undefined,
done: true
}
}
}
}
}
}
for (const each of user) {
console.log(each);
}
生成器函数
生成器函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完成不同
- 使用
// 加"*"表明是生成器函数
function * gen() {
console.log('1'); // code1
yield '1';
console.log('2'); // code2
yield '2';
}
let iterator = gen(); // 调用生成器函数返回的是一个迭代器对象
iterator.next(); // 执行code1
iterator.next(); // 执行code2
// 输出 yield 返回的结果
for (const v of iterator) {
console.log(v);
}
- 实例 模拟获取:用户数据 -> 订单数据 -> 商品数据
// 调用生成器函数
let iterator = gen();
iterator.next();
function getUsers() {
setTimeout(() => {
let data = "用户数据";
iterator.next(data);
}, 1000)
}
function getOrders() {
setTimeout(() => {
let data = "订单数据";
// 第二次调用 next 传入的实参将作为第一个 yield 语句返回的结果
iterator.next(data);
}, 1000)
}
function getProducts() {
setTimeout(() => {
let data = "商品数据";
iterator.next(data);
}, 1000)
}
function * gen() {
const users = yield getUsers();
const orders = yield getOrders();
const products = yield getProducts();
}
Promise
Promise是ES6引入的异步编程的新解决方案,语法上Promise是一个构造函数,用来封装异步操作并可以获取成功或失败的结果。
Set
常用API
- add
- delete
- has
- clear
- size(属性)
const set = new Set([1, 2, 3, 1]);
for (const num of set) {
console.log(num);
}
Map
常用API
- set
- delete
- get
- clear
- size(属性)
let m = new Map();
m.set('name', 'horizon');
for (const o of m) {
console.log(o); // 输出长度为2的数组,第一个元素为key,第二个元素为value
}
Class类
通过class关键字可以定义类,基本上ES6的class可以看做是一种语法糖,它的绝大部分功能ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
- class声明类
- constructor定义构造函数初始化
- extends继承父类
- super调用父类构造方法
- static定义静态方法和属性
- 父类方法可以重写
// ES5实现类的写法
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.eat = function() {
console.log('eat');
}
// ES6实现类的写法
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
eat() {
console.log('eat');
}
}
Person person = new Person('horizon', 23);
person.call();
// ES5实现继承
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function() {
console.log('I can call');
}
function SmartPhone(brand, price, color) {
Phone.call(this, brand, price);
this.color = color
}
// 设置子级构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.contructor = SmartPhone
SmartPhone.prototype.photo = function() {
console.log('I can photo');
}
// ES6实现继承
class Phone {
constructor(brand, price) {
this.brand = brand;
this.price= price;
}
call() {
console.log('I can call');
}
}
class SmartPhone extends Phone {
constructor(brand, price, color) {
super(brand, price);
this.color = color;
}
photo() {
console.log('I can photo');
}
}
数值扩展
- Math.EPSILON:js表示的最小精度
- 二进制和八进制
- Number.isFinite:检测一个数值是否为有限数
- Number.isNaN:检测一个数值是否为NaN
- Number.isInteger:判断一个数是否为整数
- Math.trunc:将数字的小数部分抹掉
- Math.sign:判断一个数是正数、零还是负数
对象方法扩展
- Object.is:判断两个值是否相等
console.log(Object.is(1, 1)); // true
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
- Object.assign:对象的合并
- Object.setPropertyOf、Object.getPropertyOf:设置原型对象
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来
- 模块化的好处
- 防止命名冲突
- 代码复用
- 高维护性
- 模块化规范产品
- CommonJS => NodeJS、Browserify
- AMD => requireJS
- CMD => seaJS
- ES6模块化语法
- export命令用于规定模块的对外接口
- import命令用于输入其他模块提供的功能
ES7
Array.prototype.includes
includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
指数操作符
在ES7中引入了指数运算符[**],用来实现幂运算,功能与Math.pow结果相同
ES8
async和await
async和await两种语法结合可以让异步代码像同步代码一样
async函数
- async函数的返回值为Promise对象
- Promise对象的结果由async函数执行的返回值决定
await表达式
- await必须写在async函数中
- await右侧的表达式一般为Promise对象
- await返回的是Promise成功的值
- await的Promise失败了,就会抛出异常,需要通过try…catch捕获处理
对象方法扩展
- Object.values():返回一个给定对象的所有可枚举属性值的数组
- Object.entries():返回一个给定对象自身可遍历属性[key,value]的数组
- Object.getOwnPropertyDescriptors():返回指定对象所有自身属性的描述对象
ES9
扩展运算符与rest参数
扩展运算符与rest参数在ES6中已引入,但只针对数组,在ES9中为对象提供了像数组一样的扩展运算符与rest参数
正则扩展
- 命名捕获分组(?
)
let str = '<a href="http://www.baidu.com">百度</a>';
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result = reg.exec(str)
console.log(result.groups.url);
console.log(result.groups.text);
- 反向断言(?<=)
let str = "ES110哔哔120哩哩";
// 正向断言
const reg = /\d+(?=哩)/;
console.log(reg.exec(str)); // 120
// 反向断言
const reg2 = /(?<=哔)\d+/;
console.log(reg2.exec(str)); // 120
- dotAll模式
正则的dot(.)匹配除换行符以外的任意一个字符,dotAll模式下dot(.)将可以匹配任意字符(包括换行符)。
// 正则表达式的最后加了s符号
const reg = /.*/s;
ES10
对象扩展方法Object.fromEntries
接收一个二维数组或Map将其转换为对象,与ES8的Object.entries方法互为逆运算
const res = Object.fromEntries([
['name', 'horizon']
])
console.log(res); // {name: 'horizon'}
const m = new Map();
m.set('name', 'horizon');
const obj = Object.fromEntries(m);
console.log(obj); // {name: 'horizon'}
字符串扩展方法trimStart与trimEnd
- trimStart:清除字符串左侧空白字符
- trimEnd:清除字符串右侧空白字符
数组扩展方法flat与flatMap
- flat:将多维数组转化为低维数组,参数可传入需要降几维,默认值为1
- flatMap:将map的结果进行维度降低
const array = [1,2,[3,4,[5,6]]];
console.log(array.flat()); // [1,2,3,4,[5,6]]
console.log(array.flat(2)); // [1,2,3,4,5,6]
const arr = [1,2,3,4,5];
const newArr = arr.flatMap(each => [each * 10]); // [10,20,30,40,50]
Symbol.prototype.description
const s = Symbol('horizon');
console.log(Symbol.description); // horizon
ES11
私有属性
class Person {
// 公有属性
name;
// 私有属性
#age;
constructor(name, age) {
this.name = name;
this.#age = age;
}
}
const person = new Person('horizon', 23);
console.log(person.name); // horizon
console.log(person.#age); // error
Promise.allSettled
接收一个Promise数组,不管Promise数组内的Promise是否成功或失败,allSettled返回的Promise都是成功状态的,这与all不同。
字符串扩展String.matchAll
将所有的匹配结果取出来,返回一个可迭代的对象,可用for…of循环遍历
可选链操作符(?.)
function main(config) {
// const host = config && config.db && config.db.host;
const host = config?.db?.host;
}
const config = {
db: {
host: '127.0.0.1'
}
}
动态import
使用 import(’/path’) 动态导入模块,返回一个Promise对象
BigInt类型
const num1 = 123n;
const num2 = BigInt(123);