ES6新特性
变量声明
let a;
let b,c,d;
let e = 100;
let f = 521, g = iloveyou', h = [];
块级作用域
{
let girl = '周扬青';
}
console.log(girl); //这里会报错,变量不在作用域内,用var声明就可以
常量声明
const NAME = 'tom'; //必须赋予初始值,变量名大写,变量值不能被修改
解构赋值
数组:
const F4 = [1, 2, 3, 4];
let [a, b, c, d] = F4; //此时abcd的值分别对应1234
对象:
const person = {
name: 'tom',
age: 10,
say: function(){
console.log('i can say hello');
}
};
let {name, age, say} = person;//此时分别对应对象的属性
//也可以这样
let {say} = person; //say必须与person.say()相同
say();
简化对象
let name = 'tom';
let change = function(){
console.log('hello');
}
//直接对象赋值
const school = {
name,
change,
improve(){
console.log('123');
},
age:10 //旧的写法
};
箭头函数
let fn = function(){
...
}
//新特性
let fn = (a, b) => {
return a+b;
}
注意:
1.箭头函数不能作为构造实例化对象,例如:
let me = new Person('tom'); //Person不能用箭头函数声明
2.不能使用·arguments·变量
let fn = () => {
console.log(arguments);
}
fn(1,2,3);
3.只有一个参数时,()可以省略
let add = n =>{
return n+n;
}
4.只有一条语句时,return
必须省略
let pow = n => n * n;
rest参数
//ES5获取实参
function date(){
console.log(arguments);
}
date(1,2,3);
//ES6
function date(...args){
console.log(args);
}
date(1,2,3);
注意:rest参数必须放到参数最后
function fn(a, b, ...args){}
扩展运算符
const arr = [1,2,3,4];
function ex(){
console.log(arguments);
}
ex(...arr);
Symbol的使用
创建:
let s = Symbol();
let s2 = Symbol('hello');
let s3 = Symbol.for('hi');
使用场景:
迭代器
生成器
生成器是一个特殊的函数,用于一步编程,纯回调函数。
function * gen(){ //*号的其中一边可以不用空格,不做要求
console.log('123');
}
let iterator = gen();
iterator.netx(); // 调用
传参:
解决回调地狱(嵌套)问题:
异步编程
//模拟获取 用户数据 订单数据 商品数据
function getUsers(){
setTimeout(()=>{
let data = '用户数据';
//调用 next 方法, 并且将数据传入
iterator.next(data);
}, 1000);
}
function getOrders(){
setTimeout(()=>{
let data = '订单数据';
iterator.next(data);
}, 1000)
}
function getGoods(){
setTimeout(()=>{
let data = '商品数据';
iterator.next(data);
}, 1000)
}
function * gen(){
let users = yield getUsers();
let orders = yield getOrders();
let goods = yield getGoods();
}
//调用生成器函数
let iterator = gen();
iterator.next();
Promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数, 用来封装异步操作并可以获取其成功或失败的结果。
- Promise 构造函数: Promise (excutor) {}
- Promise.prototype.then 方法
- Promise.prototype.catch 方法
基础语法
//实例化 Promise 对象
const p = new Promise(function(resolve, reject){ //resolve:用于执行成功返回参数,reject用于执行失败返回参数,reject和resolve都会改变p的状态
setTimeout(function(){
// let data = '数据库中的用户数据';
// resolve
// resolve(data);
let err = '数据读取失败';
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法
p.then(function(value){ //Promise执行成功执行的回调方法,value是resolve返回的数据
console.log(value);
}, function(reason){ //Promise执行失败执行的回调方法,reason是reject返回的数据
console.error(reason);
})
//链式调用
p.then(value => {
}, reason => {
}).then(value => {
}, reason => {
});
//直接获取错误,相当于then不传第一个参数
p.catch(function(reason){
console.log(reason);
});
Promise封装异步ajax
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "https://api.apiopen.top/getJoke");
//3. 发送
xhr.send();
//4. 绑定事件, 处理响应结果
xhr.onreadystatechange = function () {
//判断
if (xhr.readyState === 4) {
//判断响应状态码 200-299
if (xhr.status >= 200 && xhr.status < 300) {
//表示成功
resolve(xhr.response);
} else {
//如果失败
reject(xhr.status);
}
}
}
})
//指定回调
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
});
集合Set
类似数组,但是元素是唯一的。基础方法:
//声明一个 set
let s = new Set();
let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);
//元素个数
// console.log(s2.size);
//添加新的元素
// s2.add('喜事儿');
//删除元素
// s2.delete('坏事儿');
//检测
// console.log(s2.has('糟心事'));
//清空
// s2.clear();
// console.log(s2);
for(let v of s2){
console.log(v);
}
去重、交集、并集、差集
let arr = [1,2,3,4,5,4,3,2,1];
//1. 数组去重
// let result = [...new Set(arr)];
// console.log(result);
//2. 交集
let arr2 = [4,5,6,5,6];
// let result = [...new Set(arr)].filter(item => {
// let s2 = new Set(arr2);// 4 5 6
// if(s2.has(item)){
// return true;
// }else{
// return false;
// }
// });
// let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
// console.log(result);
//3. 并集
// let union = [...new Set([...arr, ...arr2])];
// console.log(union);
//4. 差集
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff);
Map
//声明 Map
let m = new Map();
//添加元素
m.set('name','尚硅谷');
m.set('change', function(){
console.log("我们可以改变你!!");
});
let key = {
school : 'ATGUIGU'
};
m.set(key, ['北京','上海','深圳']);
//size
// console.log(m.size);
//删除
// m.delete('name');
//获取
// console.log(m.get('change'));
// console.log(m.get(key));
//清空
// m.clear();
//遍历
for(let v of m){
console.log(v);
}
类Class
//ES5定义类
function Phone(brand, price){
this.brand = brand;
this.price = price;
}
//添加方法
Phone.prototype.call = function(){
console.log("我可以打电话!!");
}
//实例化对象
let Huawei = new Phone('华为', 5999);
Huawei.call();
console.log(Huawei);
//ES6 class
class Shouji{
//构造方法 名字不能修改
constructor(brand, price){
this.brand = brand;
this.price = price;
}
//方法必须使用该语法, 不能使用 ES5 的对象完整形式
call(){
console.log("我可以打电话!!");
}
}
let onePlus = new Shouji("1+", 1999);
console.log(onePlus);
静态成员
// function Phone(){
// }
// Phone.name = '手机'; 这样定义的是静态属性只属于类,不属于实例化对象
// Phone.change = function(){ //静态方法
// console.log("我可以改变世界");
// }
// Phone.prototype.size = '5.5inch';//实例化对象可以使用的属性要这样定义,对象方法同理
// let nokia = new Phone();
// console.log(nokia.name); //这里会报错
// // nokia.change();//这里会报错
// console.log(nokia.size);//这里会成功
class Phone{
//静态属性
static name = '手机';
static change(){
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia.name);
console.log(Phone.name);
继承
class Phone{
//构造方法
constructor(brand, price){
this.brand = brand;
this.price = price;
}
//父类的成员属性
call(){
console.log("我可以打电话!!");
}
}
class SmartPhone extends Phone {
//构造方法
constructor(brand, price, color, size){
super(brand, price);// Phone.call(this, brand, price)
this.color = color;
this.size = size;
}
photo(){
console.log("拍照");
}
playGame(){
console.log("玩游戏");
}
call(){
console.log('我可以进行视频通话');
}
}
const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
// console.log(xiaomi);
xiaomi.call();
xiaomi.photo();
xiaomi.playGame();
模块化
模块功能主要由两个命令构成:export 和 import。
- export 命令用于规定模块的对外接口 (暴露功能)
- import 命令用于输入其他模块提供的功能(引入暴露的功能)
基本语法:
首先在html文件中引入js文件,并声明type=“module”
<script src="./src/js/app.js" type="module"></script>
引入和暴露模块
//1. 通用的导入方式
//引入 m1.js 模块内容
import * as m1 from "./src/js/m1.js";
//引入 m2.js 模块内容
import * as m2 from "./src/js/m2.js";
//引入 m3.js
import * as m3 from "./src/js/m3.js";
//2. 解构赋值形式
import {school, teach} from "./src/js/m1.js";
import {school as guigu, findJob} from "./src/js/m2.js";
import {default as m3} from "./src/js/m3.js"; //针对默认暴露
//3. 简便形式 针对默认暴露
import m3 from "./src/js/m3.js";
console.log(m3);
//2.暴露的几种方式
//m1.js 分别暴露
export let school = '尚硅谷';
export function teach() {
console.log("我们可以教给你开发技能");
}
//m2.js 统一暴露
let school = '尚硅谷';
function findJob(){
console.log("我们可以帮助你找工作!!");
}
export {school, findJob};
//m3.js 默认暴露
export default {
school: 'ATGUIGU',
change: function(){
console.log("我们可以改变你!!");
}
}
注意:
1.一般不在html
中直接引入模块,而是在入口文件app.js
文件中统一引入,然后在html文件
中引入app.js
文件
2.模块化不是所有浏览器都支持,一般开发完需要通过工具转为ES5代码再上线,工具例如:babel
ES7新特性
includes
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
指数运算符
在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同
示例:
// includes indexOf
// const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];
//判断
// console.log(mingzhu.includes('西游记'));
// console.log(mingzhu.includes('金瓶梅'));
// **
console.log(2 ** 10);//
console.log(Math.pow(2, 10));
ES8新特性
async函数
- async 函数的返回值为 promise 对象
- promise 对象的结果由 async 函数执行的返回值决定
await 表达式
- await 必须写在 async 函数中
- await 右侧的表达式一般为 promise 对象
- await 返回的是 promise 成功的值
- await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
async和await结合读取文件案例:
//1. node引入 fs 模块
const fs = require("fs");
//读取『为学』
function readWeiXue() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/为学.md", (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
})
})
}
function readChaYangShi() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/插秧诗.md", (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
})
})
}
function readGuanShu() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/观书有感.md", (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
})
})
}
//声明一个 async 函数
async function main(){
//获取为学内容
let weixue = await readWeiXue();
//获取插秧诗内容
let chayang = await readChaYangShi();
// 获取观书有感
let guanshu = await readGuanShu();
console.log(weixue.toString());
console.log(chayang.toString());
console.log(guanshu.toString());
}
main();
对象方法扩展
- Object.values()方法返回一个给定对象的所有可枚举属性值的数组
- Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组
//声明对象
const school = {
name:"尚硅谷",
cities:['北京','上海','深圳'],
xueke: ['前端','Java','大数据','运维']
};
//获取对象所有的键
// console.log(Object.keys(school));
//获取对象所有的值
// console.log(Object.values(school));
//entries:将对象键值转为数组键值,类似map
// console.log(Object.entries(school));
//创建 Map
// const m = new Map(Object.entries(school));
// console.log(m.get('cities'));
//对象属性的描述对象
// console.log(Object.getOwnPropertyDescriptors(school));
// const obj = Object.create(null, {
// name: {
// //设置值
// value: '尚硅谷',
// //属性特性
// writable: true,
// configurable: true,
// enumerable: true
// }
// });
ES9新特性
Rest/Spread 属性
Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组, 在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
//rest 参数,将...后面的参数放到另一个对象中
function connect({host, port, ...user}){
console.log(host);
console.log(port);
console.log(user);
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
});
//对象合并
const skillOne = {
q: '天音波'
}
const skillTwo = {
w: '金钟罩'
}
const skillThree = {
e: '天雷破'
}
const skillFour = {
r: '猛龙摆尾'
}
const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};
console.log(mangseng)
// ...skillOne => q: '天音波', w: '金钟罩'
正则表达式命名捕获组
ES9 允许命名捕获组使用符号(?<name>)
,这样获取捕获结果可读性更强
//声明一个字符串
// let str = '<a href="http://www.atguigu.com">尚硅谷</a>';
// //提取 url 与 『标签文本』
// const reg = /<a href="(.*)">(.*)<\/a>/;
// //执行
// const result = reg.exec(str);
// console.log(result);
// console.log(result[1]); //获取到url
// console.log(result[2]); //获取到text
let str = '<a href="http://www.atguigu.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 = 'JS5211314你知道么555啦啦啦';
//正向断言
const reg = /\d+(?=啦)/; //获取'啦'前面的数字
const result = reg.exec(str);
//反向断言
const reg = /(?<=么)\d+/; //获取'么'后面的数字
const result = reg.exec(str);
console.log(result);
正则表达式 dotAll 模式
正则表达式中点.匹配除回车外的任何单字符,标记『s』改变这种行为,允许行 终止符出现
//dot . 元字符 除换行符以外的任意单个字符
let str = `
<ul>
<li>
<a>肖生克的救赎</a>
<p>上映日期: 1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映日期: 1994-07-06</p>
</li>
</ul>`;
//声明正则
// const reg = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/;
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
//执行匹配
// const result = reg.exec(str);
let result;
let data = [];
while(result = reg.exec(str)){
data.push({title: result[1], time: result[2]});
}
//输出结果
console.log(data);
ES10新特性
Object.fromEntries
用entries创建对象
//二维数组
// const result = Object.fromEntries([
// ['name','尚硅谷'],
// ['xueke', 'Java,大数据,前端,云计算']
// ]);
//Map
// const m = new Map();
// m.set('name','ATGUIGU');
// const result = Object.fromEntries(m);
//Object.entries ES8
const arr = Object.entries({
name: "尚硅谷"
})
console.log(arr);
trimStart 和 trimEnd
与trim类似,分别是用于清除左右空格
// trim
let str = ' iloveyou ';
console.log(str);
console.log(str.trimStart());
console.log(str.trimEnd());
Array.prototype.flat 与 flatMap
//将多维数组转化为低位数组
// const arr = [1,2,3,4,[5,6]];
// const arr = [1,2,3,4,[5,6,[7,8,9]]];
//参数为深度 是一个数字
// console.log(arr.flat(2));
//flatMap:遍历处理数组元素
const arr = [1,2,3,4];
const result = arr.flatMap(item => [item * 10]); //每个元素*10
console.log(result);
Symbol.prototype.description
获取Symbol描述
//创建 Symbol
let s = Symbol('尚硅谷');
console.log(s.description);
ES11新特性
私有属性
//公有属性
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('晓红', 18, '45kg');
// console.log(girl.name);
// console.log(girl.#age); //打印报错
// console.log(girl.#weight);//打印报错
girl.intro();
Promise.allSettled
//声明两个promise对象
const p1 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('商品数据 - 1');
},1000)
});
const p2 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('商品数据 - 2');
// reject('出错啦!');
},1000)
});
//调用 allsettled 方法
// const result = Promise.allSettled([p1, p2]);//不管如何,返回结果都是成功的promise
// const res = Promise.all([p1, p2]); //两个promise都成功才会返回成功
console.log(res);
String.prototype.matchAll
用于正则批量匹配
//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg
//调用方法
const result = str.matchAll(reg);
// for(let v of result){
// console.log(v);
// }
const arr = [...result];
console.log(arr);
可选链操作符
如果操作对象属性的层级比较深,可以用来简化访问
// ?. //属性不存在也不会报错
function main(config){
// const dbHost = config && config.db && config.db.host;
const dbHost = config?.db?.host;
console.log(dbHost);
}
main({
db: {
host:'192.168.1.100',
username: 'root'
},
cache: {
host: '192.168.1.200',
username:'admin'
}
})
动态import
可以实现模块化按需加载
// import * as m1 from "./hello.js"; //静态引入
//获取元素
const btn = document.getElementById('btn');
btn.onclick = function(){
import('./hello.js').then(module => { //动态引入
module.hello();
});
}
BigInt大整形
//大整形
// let n = 521n;
// console.log(n, typeof(n));
//函数
// let n = 123;
// console.log(BigInt(n));
// console.log(BigInt(1.2));
//大数值运算
let max = Number.MAX_SAFE_INTEGER;
console.log(max);
console.log(max + 1);
console.log(max + 2);//计算出问题
console.log(BigInt(max))
console.log(BigInt(max) + BigInt(1))
console.log(BigInt(max) + BigInt(2))
glabalThis
操作全局对象
console.log(globalThis);