ES6
let
- 变量声明不能重复。
let star = 'jay';
let star = 'chou'; // error
- 块级作用域 全局 函数 eval
{
let girl = 'si';
}
console.log(girl); // error
- 不存在变量提升
console.log(song); // undefined
var song = 'song';
代码语言:javascript复制console.log(song); // error
let song = 'song';
- 不影响作用域链
{
let school = 'clyz';
function fn() {
console.log(school)
}
fn();
}
const
- 声明常量 一般大写
const SCHOOL = 'CLYZ';
console.log(SCHOOL); // 'CLYZ'
- 必须有初始值
const A; // error
- 常量的值不能修改
SCHOOL = 'YLZX'; // error
- 块级作用域
{
const PLAYER = 'UZI';
}
- 对于数组和对象的元素修改,不算做对常量的修改,不会报错(引用类型)
const TEAM = ['UZI', 'MXLG', 'Ming', 'Letme'];
TEAM.push('Meiko');
解构赋值
代码语言:javascript复制const F4 = ['a', 'b', 'c', 'd'];
let [e, f, g, h] = F4;
console.log(e); // 'a'
console.log(f); // 'b'
console.log(g); // 'c'
console.log(h); // 'd'
- 对象的解构赋值
const zhao = {
name: '赵本山',
age: '50',
xiaopin: function() {
console.log('I can play xiaopin');
}
};
let {name, age, xiaopin} = zhao;
console.log(name); // '赵本山'
xiaopin(); // 'I can play xiaopin'
模板字符串
- 声明
let str = `I am a string`;
- 内容中可以出现换行符
let str = `<ul>
<li>aaa</li>
</ul>
<ul>
<li>aaa</li>
</ul>`
- 变量拼接
let a = '123';
let b = '456';
let out = `${a}---${b}`; // '123---456'
简化对象写法
代码语言:javascript复制let name = 'chen';
let change = function() {
console.log('We can change you');
}
const SCHOOL = {
name, // equals name: name
change, // equals change: change
improve() { // equals improve: function() { return }
return
}
}
箭头函数
代码语言:javascript复制let fn = function(a, b) {
return a b;
}
let fn = (a, b) => {
return a b;
}
- 箭头函数的this是静态的,始终指向函数声明时所在作用域,不受call、apply等改变
function getName() {
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
window.name = 'chen';
const school = {
name: 'chenshuai';
}
// 直接调用
getName(); // 'chen'
getName2(); // 'chen'
// call 方法调用
getName.call(school); // 'chenshuai'
getName2.call(school); // 'chen'
- 箭头函数不能作为构造器实例化对象
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('chen', 23);
console.log(me); // error
- 不能使用arguments变量
let fn = () => {
console.log(arguments);
}
fn(1, 2, 3); // error
- 箭头函数的简写
let add = (n) => { return n 1 };
// 1. 当形参有且只有1个时可以省略参数体处的小括号
let add = n => { return n 1 };
// 2. 当形参有且只有1个时可以省略方法体处的花括号
// 此时 return 必须省略,并且执行结果就是函数返回值
let add = n => n 1;
- 剪头函数适合与this无关的回调、定时器、数组方法,不适合与this有关的回调、dom事件回调、对象的方法
// 获取元素
let ad = document.getElementById('ad');
// 绑定事件
ad.addEventListener('click', function() {
// 保存外层this值供内部使用
let _that = this;
setTimeOut(function() {
this.style.background = 'pink';
// background is undefined
console.log(this);
// Window
}, 2000);
setTimeOut(() => {
this.style.background = 'pink';
console.log(this); // ad
}, 2000);
})
代码语言:javascript复制const arr = [1, 6, 9, 10, 100, 123];
const result = arr.filter(function(item) {
if(item % 2 === 0) {
return true;
} else {
return false;
}
})
console.log(result); // [6, 10, 100]
--------------------------------------------------------
const result = arr.filter(item => item % 2 === 0);
console.log(result); // [6, 10, 100]
- 函数默认参数
// 1. 形参初始值,具有默认值的参数位置一般靠后
function add(a, b, c) {
return a b c;
}
add(1, 2, 3); // 6
add(1, 2); // NaN
function add3(a, b, c = 10) {
return a b c;
}
add3(1, 2, 3); // 6
add3(1, 2); // 13
// 2. 与解构赋值结合
function connect(options) {};
connect({
host: 'localhost',
username: 'root',
password: 'pwd',
// port: 3306
})
function connect({host, username, password = 'root', port = 3306) {
console.log(host); // 'localhost'
console.log(password); // 'root'
console.log(port); // 3306
}
rest参数
- 用于获取函数实参,代替arguments
function data() {
console.log(arguments);
}
data(1, 2, 3); // Arguments(3) [1, 2, 3]
function data2(...args) {
console.log(args); // filter some array map
}
data2(1, 2, 3); // [1, 2, 3]
// rest 参数必须放在最后
function fn(a, b, ...args) {
console.log(a);
console.log(b);
console.log(args);
}
fn(1, 2, 3, 4, 5, 6);
// 1
// 2
// [3, 4, 5, 6]
扩展运算符
代码语言:javascript复制const tfboys = ['易烊千玺', '王俊凯', '王源'];
function chunwan() {
console.log(arguments);
}
chunwan(tfboys); // ['易烊千玺', '王俊凯', '王源']
chunwan(...tfboys); // { 0:'易烊千玺', 1:'王俊凯', 2:'王源'}
- 数组合并
const arr = [1, 2, 3];
const arr2 = ['a', 'b', 'c'];
const _arr = arr.concat(arr2); // [1, 2, 3, 'a', 'b', 'c']
const _arr2 = [...arr, ...arr2]; // [1, 2, 3, 'a', 'b', 'c']
- 数组克隆
const arr = ['E', 'G', 'M'];
const _arr = [...arr]; // ['E', 'G', 'M']
- 将伪转为数组
const divs = document.querySelectorAll('div');
const divArr = [...divs]; // [div, div, div]
Symbol
- es6引入的第七种原始数据类型,是一种类似字符串的类型,表示独一无二的值
- Symbol 的值是唯一的,可以用于解决命名冲突的问题;
- Symbol 的值不能与其他数据进行运算;
- Symbol 定义的对象属性不能使用 for...in...循环遍历,但是可以使用Reflect.ownKeys 来获取对象的所有键名;
// 1. 创建 Symbol,内部实现唯一性,外部不显示
let s = Symbol();
console.log(s, typeof s); // Symbol() 'symbol'
// 2. 内部可以传入一个标识
let s2 = Symbol('s');
let s3 = Symbol('s');
console.log(s2 === s3); // false
// 3. 通过 Symbol.for 创建
let s4 = Symbol.for('s');
let s5 = Symbol.for('s');
console.log(s4 === s5); // true
// 4. 不能与其他数据进行运算
let result = s 100; // error
let result = s > 100; // error
let result = s '100'; // error
- Symbol 创建对象属性
// 使用 Symbol 向对象中添加方法
let game = {
name: '贪吃蛇'
};
let methods = {
up: Symbol();
down: Symbol();
}
game[methods.up] = function() {
console.log('up');
}
game[methods.down] = function() {
console.log('down');
}
console.log(game);
----------------------------------------------------
let game2 = {
name: '狼人杀',
[Symbol('say')]: function() {
console.log('I can say');
},
[Symbol('boom')]: function() {
console.log('I can boom');
}
}
console.log(game2);
- Symbol 内置值
class Person {
static [Symbol.hasInstance](param) {
console.log('我被用来检测类型了');
console.log(param);
}
}
let o = {};
console.log(o instanceof Person); // false
迭代器
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制
- es6 创造了一种新的遍历命令 for..of 循环,Iterator 主要供 for...of 消费
- 原生具备iterator接口的数据(可用 for...of 遍历)
- Array
- Arguments
- Set
- Map
- String
- TypedArray
- NodeList
- 工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
coonst xyj = ['唐僧', '孙悟空', '猪八戒', '沙悟净'];
for(let v of xyj) {
console.log(v);
}
let iterator = xyj[Symbol.iterator()]();
console.log(iterator.next()); // { value: '唐僧', done: false }
console.log(iterator.next()); // { value: '孙悟空', done: false }
console.log(iterator.next()); // { value: '猪八戒', done: false }
console.log(iterator.next()); // { value: '沙悟净', done: false }
console.log(iterator.next()); // { value: undefined, done: true }
- 需要自定义遍历数据的时候要想到迭代器
// 声明一个对象
const c = {
name: '高一1班',
students: ['liu', 'chen', 'wang']
}
// 遍历这个对象
for(let i of c) {
console.log(i); // c is not iterator
}
----------------------------------------------------
const d = {
name: '高一1班',
students: ['liu', 'chen', 'wang'],
[Symbol.iterator]() {
let index = 0;
let _that = this;
return {
next: function() {
if(index < _that.students.length) {
const result = {
value: _that.students[index],
done: false
};
index ;
return result;
} else {
return {
value: undefined,
done: true
}
}
}
};
}
}
for(let i of d) {
console.log(i);
}
// 'liu'
// 'chen'
// 'wang'
// 'undefined'
生成器
- 生成器函数(generator / yield)是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
// 生成器其实就是一个特殊的函数(以前的异步就是纯回调函数)
function * gen() {
console.log('hello generator');
}
let iterator = gen();
console.log(iterator); // gen()
iterator.next(); // 'hello generator'
- yield
// 函数代码的分隔符
function * gen() {
console.log('1');
yield 'a';
console.log('2');
yield 'b';
console.log('3');
yield 'c';
console.log('4');
}
let iterator = gen();
iterator.next(); // '1'
iterator.next(); // '2'
iterator.next(); // '3'
iterator.next(); // '4'
for(let v of fen()) {
console.log(v);
}
// 'a'
// 'b'
// 'c'
console.log(iterator.next()); // { value: 'a', done: false }
console.log(iterator.next()); // { value: 'b', done: false }
console.log(iterator.next()); // { value: 'c', done: false }
console.log(iterator.next()); // { value: undefined, done: true }
- 生成器函数参数
// next 方法可以传入实参,该实参作为对应yield语句的返回结果
function * gen(args) {
console.log(args);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
let iterator = gen('AAA');
console.log(iterator.next());
// AAA
// { value: 111, done: false }
console.log(iterator.next('BBB'));
// BBB
// { value: 222, done: false }
console.log(iterator.next('CCC'));
// CCC
// { value: 333, done: false }
console.log(iterator.next('DDD'));
// DDD
// { value: undefined, done: true }
- 生成器函数实例
// 异步编程 文件操作 网络操作 数据库操作
// 1s后输出111 2s后输入222 3s后输入333
// 回调地狱
setTimeOut(() => {
console.log(111);
setTimeOut(() => {
console.log(222);
setTimeOut(() => {
console.log(333);
}, 3000)
}, 2000)
}, 1000)
// 生成器函数
function one() {
setTimeout(() => {
console.log(111);
iterator.next();
}, 1000)
}
function two() {
setTimeout(() => {
console.log(222);
iterator.next();
}, 2000)
}
function three() {
setTimeout(() => {
console.log(333);
iterator.next();
}, 3000)
}
function * gen() {
yield one();
yield two();
yield three();
}
let iterator = gen();
iterator.next();
// 111
// 222
// 333
代码语言:javascript复制// 模拟获取 用户数据 订单数据 商品数据
function getUsers() {
setTimeout(() => {
let data = 'user data';
// 调用 next 方法,并将数据传入
iterator.next(data);
}, 1000)
}
function getOrders() {
setTimeout(() => {
let data = 'order data';
iterator.next(data);
}, 1000)
}
function getGoods() {
setTimeout(() => {
let data = 'good data';
iterator.next(data);
}, 1000)
}
function * gen() {
let users = yield getUsers();
console.log(users); // 'user data'
let orders = yield getOrders();
console.log(orders); // 'order data'
let goods = yield getGoods();
console.log(goods); // 'good data'
};
Promise
- Promise 是ES6引入的异步编程的新解决方案,语法上Promise是一个构造函数。用来封装异步操作并获取其成功或失败的结果
- Promise构造函数: Promise(excutor) {}
- Promise.prototype.then() 方法
- Promise.prototype.catch() 方法
// 实例化 Promise 对象
const p = new Promise(function(resolve, reject) {
setTimeout(function() {
if(Math.random() > 0.5) {
resolve('>')
} else {
reject('<')
}
}, 1000);
})
// 调用 Promise 的 then 方法
p.then(function(value) {
console.log(value);
},
function(reason) {
console.error(reason);
});
- Promise 读取文件
const fs = require('fs');
fs.readFile('./a.txt', (err, data) => {
if(err) throw err;
console.log(data);
});
// 使用 promise 封装
const p = new Promise(function(resolve, reject) {
fs.readFile('./a.txt', (err, data) => {
if(err) reject(err);
resolve(data);
});
});
p.then(function(value) {
console.log(value.toString());
},
function(reason) {
console.log('read faild');
});
- Promise 封装 ajax
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://localhost:8080/getToken');
xhr.send();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
} else {
console.error(xhr.status)
}
}
}
// 使用 Promise 封装
const p = new Promise((resolve, reject) => {
xhr.open('GET', 'https://localhost:8080/getToken');
xhr.send();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr.status)
}
}
}
});
p.then(function(value) {
console.log(value);
},
function(reason) {
console.log(reason);
});
- Promise.prototype.then() 方法
const p = new Promise((resolve, reject) => {
setTimeout(function() {
resolve('用户数据');
});
})
// 调用then方法,返回结果是Promise对象,对象状态由回调函数的执行结果决定
// 1. 如果回调函数中返回的结果是非promise类型数据,状态为成功,返回值为对象的成功的值
// 2. 如果回调函数中返回的结果是promise类型数据
const result = p.then(value => {
// 1. 返回非 promise 类型的属性
// console.log(value);
// return 'ok';
// 2. 返回 promise 类型的属性
return new Promise((resolve, reject) => {
resolve('ok');
})
// 3. 抛出错误
// throw new Error('出错了');
}, reason => {
console.warn(reason);
});
console.log(p); // Promise(...)
// 链式调用
p.then(value => {}, reason => {}).then(value => {});
- Promise 读取多个文件
const fs = require('fs');
fs.readFile('./a.txt', (err1, data1) => {
fs.readFile('./b.txt', (err2, data2) => {
fs.readFile('./c.txt', (err3, data3) => {
let result = data1 'rn' data2 'rn' data3;
console.log(result);
});
});
});
// 使用 promise
const p = new Promise((resolve, reject) => {
fs.readFile('./a.txt', (err, data) => {
resolve(data);
});
});
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile('./b.txt', ), (err, data) => {
resolve([value, data]);
};
});
}).then(value => {
fs.readFile('./c.txt', (err, data) => {
value.push(data);
resolve(value);
});
}).then(value => {
console.log(value.join('rn');
});
- Promise.prototype.catch() 方法
const p = new Promise((resolve, reject) => {
setTimeout(function() {
reject('出错了');
});
});
p.then(value => {}, reason => {
console.error(reason);
});
p.catch(reason => {
console.warn(reason);
});
Set
- ES6提供了新的数据结构 Set(集合),它类似于数组,但成员的值都是唯一的,接口实现了iterator接口,因此可以使用扩展运算符和for...of进行遍历
- 集合的属性和方法
- size 返回集合元素的个数
- add 新增一个元素,返回当前集合
- delete 删除元素,返回boolean值
- has 检测集合中是否包含某个元素,返回boolean值
let s = new Set();
let s2 = new Set([1, 2, 3, 4, 1]);
console.log(s, typeof s); // Set(0) {} 'object'
console.log(s2); // Set(4) {1, 2, 3, 4}
console.log(s2.size); // 4
s2.add(5);
console.log(s2); // Set(5) {1, 2, 3, 4, 5}
console.log(s2.size); // 5
s2.delete(1);
console.log(s2); // Set(4) {2, 3, 4, 5}
console.log(s2.size); // 4
console.log(s2.has(3)); // true
console.log(s2.has(6)); // false
s2.clear();
console.log(s2); // Set(0) {}
for(let i of s2) {
console.log(i);
}
// 1
// 2
// 3
// 4
- Set实践
// 1. 数组去重
let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let result = [...new Set(arr)]; // [1, 2, 3, 4, 5]
// 2. 交集
let arr2 = [3, 4];
let result2 = [...new Set(arr)].filter(item => {
let s2 = new Set(arr2);
if(s2.has(item)) {
return true;
} else {
return false;
}
})
/* 简化 */
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
// 3. 并集
let union = [...new Set([...arr, ...arr2])];
// 4. 差集(arr对arr2取差集)
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
Map
- ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是键的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,因此可以使用扩展运算符和for...of进行遍历
- Map的属性和方法
- size 返回Map的元素个数
- set 新增一个元素,返回当前Map
- get 返回键名对象的键值
- has 检测Map中是否包含某个元素,返回boolean值
- clear 清空集合,返回undefined
let m = new Map();
m.set('name', 'chenshuai');
m.set('change', function() {
console.log('change');
});
let key = {
token: 'md5'
};
m.set(key, 'nkghr458g674r8483434h');
Class
- ES6提供了更接近传统语言的写法,引入类这个概念,作为对象的模板,通过class关键字可以定义类。基本上es的class可以看作只是一个语法糖,它的绝大部分功能es5都可以做到,新的class写法只是让对象原型的写法更清晰、更像面向对象编程的语法而已
- 知识点
- class 声明类
- constructor 定义构造函数初始化
- extends 继承父类
- super 调用父级构造方法
- static 定义静态方法和属性
- 父类方法可以重写
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function() {
console.log('I can call');
}
let Huawei = new Phone('华为', 5999);
Huawei.call(); // 'I can call'
console.log(Huawei); // { brand: '华为', price: 5999 }
// class 语法
class Phone {
// 构造方法
constructor(brand, price) {
this.brand = brand;
this.price = price;
},
call() {
console.log('I can call');
}
}
let onePlus = new Phone('1 ', 3999);
console.log(onePlus); // { brand: '1 ', price: 3999 }
- 类的静态成员
// 实例对象与函数对象属性不相通
function Phone() {}
// 类的属性,不属于实例
Phone.name = 'name';
Phone.change = function() {
console.log('I can change');
};
let nokia = new Phone();
console.log(nokia.name); // undefined
nokia.change(); // nokia.change is mot a function
Phone.prototype.size = '5.5 inch';
console.log(nokia.size); // '5.5 inch'
代码语言:javascript复制class Phone {
static name = '手机';
static change() {
console.log('I can change');
}
}
let nokia = new Phone();
console.log(nokia.name); // undefined
console.log(Phone.name); // '手机'
- 构造函数继承
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function() {
console.log('I can change');
}
function SmartPhone(brand, price, color, size) {
Phone.call(this, brand, price);
this.color = color;
this.size = size;
}
// 设置子级构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone;
// 声明子类的方法
SmartPhone.prototype.photo = function() {
console.log('I can take a photo');
}
SmartPhone.prototype.playGame = function() {
console.log('I can play game');
}
const chuizi = new SmartPhone('锤子', 2499, 'black', '5.5 inch');
- 类继承
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, size) {
super(brand, price);
this.color = color;
this.size = size;
}
photo() {
console.log('I can take a photo');
}
playGame() {
console.log('I can play game');
}
}
const xiaomi = new SmartPhone('小米', 3999, 'blcak', '5.8inch');
xiaomi.call(); // 'I can call'
xiaomi.photo(); // 'I can take a photo'
- 子类对父类方法的重写
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, size) {
super(brand, price);
this.color = color;
this.size = size;
}
photo() {
console.log('I can take a photo');
}
playGame() {
console.log('I can play game');
}
// 重写父类 call 方法
call() {
console.log('I can call with video');
}
}
const xiaomi = new SmartPhone('小米', 3999, 'blcak', '5.8inch');
xiaomi.call(); // 'I can call with video'
- get和set
class Phone {
get price() {
console.log('get price');
return 6688
}
set price(newVal) {
console.log('set price:' newVal);
}
}
let s = new Phone();
console.log(s.price); // 6688
s.price = 1688;
数值扩展
- Number.EPSILON 是 js 表示的最小精度
// 用于浮点数运算
console.log(0.1 0.2 === 0.3); // false
function equal(a, b) {
if(Math.abs(a - b) < Number.EPSILON) {
return true;
} else {
return false;
}
}
equal(0.1 0.2, 0.3); // true
- 二进制和八进制
let b = 0b1010;
let o = 0o777;
let d = 100;
let x = 0xff;
- Number.isFinite 检测一个数值是否为有限数
console.log(Number.isFinite(100)); // true
console.log(Number.isFinite(100/0)); // flase
console.log(Number.isFinite(Infinity)); // false
- Number.isNaN 检测一个数值是否为NaN
console.log(Number.isNaN(123)); // false
- Number.parseInt Number.parseFloat 字符串转数值
console.log(Number.parseInt('5201314qs')); // 5201314
console.log(Number.parseFloat('3.1415yzl')); // 3.1415
- Number.isInteger 判断一个数是否为整数
console.log(Number.isInteger(5)); // true
console.log(Number.isInteger(2.5)); // false
- Math.trunc 将数字的小数部分抹掉
console.log(Math.trunc(2.5)); // 2
- Math.sign 判断一个数是正数、负数、还是0
console.log(Math.sign(100)); // 1
console.log(Math.sign(0)); // 0
console.log(Math.sign(-99)); // -1
对象方法扩展
- Object.is 判断两个值是否完全相等
- Object.assign 对象的合并
- Object.setPrototypeOf 设置原型对象
- Object.getPrototypeOf
// 1.
console.log(Object.is(NaN, NaN)); // true
console.log(NaN === NaN); // false
// 2.
const conf1 = {
host: '127.0.0.1',
port: 3306,
name: 'root',
pass: 'root'
}
const conf2 = {
host: 'localhost',
port: 27017,
name: 'admin',
pass: 'admin'
}
console.log(Object.assign(conf1, conf2).host); // 'localhost'
// 3.
const school = {
name: 'sch'
}
const cities = {
xiaoqu: ['bj', 'sh', 'sz'];
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);
模块化
- 好处
- 防止命名冲突
- 代码复用
- 高维护性
- 产品
- CommonJS => NodeJS、Browserify
- AMD => requireJS
- CMD => seaJS
- ES6模块化语法
- export 命令用于规定模块的对外接口
- import 命令用于输入其他模块提供的功能
// main.js
// 分别暴露
export let name = 'chen';
export function skill() {
console.log('my skill');
}
// 统一暴露
let name = 'chen';
function tech() {
console.log('tech you');
}
export { school, tech() };
// 默认暴露
export default {
name: 'chen',
change: function() {
console.log('change');
}
}
代码语言:javascript复制/* index.html */
<script type='module'>
//引入 main.js
import * as main from './main.js';
m1.name; // 'chen'
m1.tech(); // 'tech you'
m1.default.change(); // 'change'
</script>
<script type='module' src='./main.js'></script>
代码语言:javascript复制// 1. 通用导入方式
import * as m1 from './m1.js';
// 2. 解构赋值形式
import { school, teach } from './m2.js';
import { school as clyz, teach } from './m2.js';
import { default as sch } from './m2.js';
// 3. 简写(针对默认暴露)
import m3 from './m3.js';
- ES6 引入 npm 包
// npm i jquery
// const $ = require('jquery');
import $ from 'jquery';
$('body').css('background', 'pink');
ES7
数组新增方法
- Array.prototype.includes 监测数组中是否包含某个元素,返回布尔值
const f4 = ['西游记', '红楼梦', '三国演义', '水浒传'];
f4.includes('西游记'); // true
f4.includes('金瓶梅'); // false
- 指数操作符
// equals Math.pow(2, 10);
console.log(2 ** 10); // 1024
ES8
async和await
- async和await两种语法结合可以让异步代码像同步代码一样
- async函数
- async函数的返回值为promise对象
- promise对象的结果由async函数执行的返回值决定
- await表达式
- await必须写在async函数中
- await右侧的表达式一般为promise对象
- await返回的是promise成功的值
- await的promise失败了会抛出异常,需要try...catch捕获处理
async function fn() {
// 返回字符串
// 1. 返回的结果不是一个promise对象则函数返回的结果就会是一个成功的promise
return 'abc';
// 2. 抛出错误返回的结果是一个失败的promise
throw new Error('error');
// 3. 返回的结果是一个promise对象
// async函数的返回值与该promise对象状态一致
return new Promise((resolve, reject) => {
resolve('success');
// reject('faild');
});
}
const result = fn();
console.log(result); // Promise {...}
// 通过try...catch捕获异常
const p = new Promise((resolve, reject) => {
resolve('ok');
// reject('no');
})
async function main() {
try {
let result = await p;
console.log(p); // 'ok'
} catch(e) {
console.log(e); // 'no'
}
}
代码语言:javascript复制// 使用promise读取文件
const fs = require('fs');
function read1() {
return new Promise((resolve, reject) => {
fs.readFile('./1.txt', (err, data) => {
if(err) reject(err);
resolve(data);
})
})
}
function read2() {
return new Promise((resolve, reject) => {
fs.readFile('./2.txt', (err, data) => {
if(err) reject(err);
resolve(data);
})
})
}
function read3() {
return new Promise((resolve, reject) => {
fs.readFile('./3.txt', (err, data) => {
if(err) reject(err);
resolve(data);
})
})
}
async function main() {
let one = await read1();
let two = await read2();
let three = await read3();
console.log(one);
console.log(two);
console.log(three);
}
main();
// 使用promise发送ajax请求
function sendAjax(url) {
return new Promise((resolve, reject) => {
const x = new XMLHttpRequest();
x.open('GET', url);
x.send();
x.onreadystatechange = function() {
if(x.readyState === 4) {
if(x.statue >= 200 && x.status < 300) {
resolve(x.response);
} else {
reject(x.status);
}
}
}
})
}
senAjax('https://xxx.com/token').then(value => {
console.log(value);
});
// 使用async与await发送请求
async function main() {
let result = await senAjax('https://xxx.com/token');
console.log(result);
}
对象方法扩展
- Object.values 和 Object.entries
- Object.values() 方法返回一个给定对象的所有可枚举属性值的数组
- Object.entries() 方法返回一个给定对象自身可遍历属性[k,v]的数组
const school = {
name: 'clyz',
city: ['hn', 'zjj', 'cl']
}
// 获取所有键
Object.keys(school); // ['name', 'city', 'sub']
// 获取所有值
Object.values(school); // ['clyz', ['hn', 'zjj', 'cl']]
// entries
Object.entries(school);
// [['name', 'clyz'], ['city', ['hn', 'zjj', 'cl']]]
const m = new Map(Object.entries(school));
console.log(m); // Map(3)
m.get('name'); // 'clyz'
- Object.getOwnPropertyDescriptors 该方法返回指定对象所有自身属性的描述对象
const obj = Object.create(null, {
name: {
value: 'clyz',
writable: true,
enumerable: true,
configuarble: true
}
})
Object.getOwnPropertyDescriptors(obj);
// { name: { value: 'clyz', writable: true, enumerable: true, configuarble: true }}
ES9
扩展运算符与rest参数
Rest 参数与 spread 扩展运算符在es6中已经引入,但仅限于数组,es9中为对象提供了像数组一样的 rest 参数和扩展运算符
代码语言:javascript复制function connect(host, port, name, pass) {
console.log(host);
console.log(port);
console.log(name);
console.log(pass);
}
connect({
host: '127.0.0.1',
port: 3306,
name: 'root',
pass: 'root'
});
// use spread
function connect(host, port, ...user) {
console.log(host); // '127.0.0.1'
console.log(port); // 3306
console.log(user); // { name: 'root', pass: 'root' }
}
connect({
host: '127.0.0.1',
port: 3306,
name: 'root',
pass: 'root'
});
代码语言:javascript复制const skill1 = {
q: 'qqq'
}
const skill2 = {
w: 'www'
}
const skill3 = {
e: 'eee'
}
const skill4 = {
r: 'rrr'
}
const ms = { ...skill1, ...skill2, ...skill3, ...skill4,};
// { q: 'qqq', w: 'www', e: 'eee', r: 'rrr' }
正则扩展
- 命名捕获分组
let str = '<a href="https://chen97.cn">匠新</a>';
// 提取 url 与标签文本
const reg = /<a href="(.*)">(.*)</a>/
const result = reg.exec(str);
-----------------------------------------------------------
let str = '<a href="https://chen97.cn">匠新</a>';
// 提取 url 与标签文本
const reg = /<a href="(?<url>.*)">(?<text>.*)</a>/
const result = reg.exec(str); // groups
- 反向断言
let str = 'JS5201314你知道吗555哈哈哈';
// 正向断言
const reg = /d (?=啦)/;
reg.exec(str); // '555'
// 反向断言
const reg = /(?<=么)d /;
reg.exec(str); // '555'
- dotAll 模式
// dot . 元字符 除换行符外的任意单个字符
let str = `
<ul>
<li>
<a>肖申克的救赎</a>
<p>1997-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>1997-07-06</p>
</li>
</ul>
`
const reg = /<li>s <a>(.*?)</a>s <p>(.*?)</p>/;
reg.exec(str); // 0: <li>, 1: '肖申克的救赎', 2: '1997-09-10'
const reg2 = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/gs;
reg2.exec(str);
ES10
Object
- Object.formEntries
// 二维数组
const result = Object.formEntries([
['name': 'chenshuai'],
['age': 23]
])
// Map
const m = new Map();
m.set('name', 'chenshuai');
const result = Object.formEntries(m);
字符串
- trimStart 与 trimEnd 清除字符串左侧和右侧的空格
数组
- flat 和 flatMap 将多维数组转为低维数组
const arr = [1,2,3,4,[5,6]];
const arr2 = [1,2,3,4,[5,6,[7,8,9]]];
arr.flat(); // [1,2,3,4,5,6]
arr2.flat(); // [1,2,3,4,5,6,[7,8,9]]
// 传入数字深度,默认1,使用 Infinity可展开任意深度的嵌套数组
arr2.flat(2); // [1,2,3,4,5,6,7,8,9]
代码语言:javascript复制const arr = [1,2,3,4];
const result = arr.map(item => item * 10);
// [[10],[20],[30],[40]]
const result = arr.flatMap(item => item * 10);
// [10,20,30,40]
Symbol
- Symbol.prototype.description
let s = Symbol('sys');
console.log(s.description); // 'sys'
ES11
私有属性
代码语言:javascript复制class Person {
// 公有属性
name;
// 私有属性
#age;
#weight;
// 构造方法
constructor(name, age, weight) {
this.name = name;
this.#age = age;
this.#weight = weight;
}
intro() {
console.log(this.name);
console.log(this.#age);
console.log(this.#weight);
}
}
// 实例化
const girl = new Person('jay', 18, '45kg');
girl.age; // error
girl.intro(); // ...ok
Promise
- Promise.allSettled
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('goods1');
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('error');
}, 1000)
})
const result = Promise.allSettled([p1, p2]);
// Promise { pstatus: 'resolved', pvalue: [{ status: 'fulfilled', value: 'goods1'}, { status: 'rejected', value: 'error'}]}
const result = Promise.all([p1, p2]);
// Promise { pstatus: 'rejected', pvalue: 'error'}
String
- String.prototype.matchAll
let str = `
<ul>
<li>
<a>肖申克的救赎</a>
<p>1997-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>1997-07-06</p>
</li>
</ul>
`
const reg = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/gs;
const result = str.matchAll(reg);
for(let v of result) {
console.log(v);
}
const arr = [...result];
可选链操作符
代码语言:javascript复制function main(config) {
// const h = config && config.db && config.db.host;
const h = config?.db?.host;
}
main({
db: {
host: '127.0.0.1',
username: 'root'
},
cache: {
host: '192.168.1.1',
username: 'admin'
}
});
动态 import
代码语言:javascript复制// hello.js
export function hello() {
console.log('hello');
}
// app.js
function fun() {
import('./hello.js').then(modlue => {
module.hello();
});
}
BigInt 类型
代码语言:javascript复制let n = 520n;
console.log(n, typeof n); // 521n 'bigint'
let m = 123;
console.log(BigInt(m)); // 123n
console.log(BigInt(1.5)); // error
// 大数值运算
let max = Number.MAX_SAFE_INTEGER;
console.log(max); // 9007199254740991
console.log(max 1); // 9007199254740992
console.log(max 2); // 9007199254740992
console.log(BigInt(max)); // 9007199254740991n
console.log(BigInt(max) BigInt(1)); // 9007199254740992n
console.log(BigInt(max) BigInt(2)); // 9007199254740993n
绝对全局对象 globalThis
代码语言:javascript复制console.log(globalThis); // window {...}