ES6
let
let 关键字用来声明变量,使用 let 声明的变量有几个特点:
- 不允许重复声明
- 块儿级作用域
- 不存在变量提升
- 不影响作用域链
应用场景:以后声明变量使用 let 就对了
//声明变量
let a;
let b,c,d;
let e = 100;
let f = 521, g = 'iloveyou', h = [];
//1. 变量不能重复声明
// let star = '罗志祥';
// let star = '小猪';
//2. 块儿级作用域 全局, 函数, eval
// if else while for
// {
// let girl = '周扬青';
// }
// console.log(girl);
//3. 不存在变量提升
// console.log(song);
// let song = '恋爱达人';
//4. 不影响作用域链
{
let school = '尚硅谷';
function fn(){
console.log(school);
}
fn();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>点击 DIV 换色</title>
<link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css"
rel="stylesheet">
<style>
.item {
width: 100px;
height: 50px;
border: solid 1px rgb(42, 156, 156);
float: left;
margin-right: 10px;
}
</style>
</head>
<body>
<div class="container">
<h2 class="page-header">点击切换颜色</h2>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script>
//获取div元素对象
let items = document.getElementsByClassName('item');
//遍历并绑定事件
for(let i = 0;i<items.length;i++){
items[i].onclick = function(){
//修改当前元素的背景颜色
// this.style.background = 'pink';
items[i].style.background = 'pink';
}
}
</script>
</body>
</html>
const
const 关键字用来声明常量,const 声明有以下特点
- 声明必须赋初始值
- 标识符一般为大写
- 不允许重复声明
- 值不允许修改
- 块儿级作用域
注意: 对象属性修改和数组元素变化不会出发 const 错误
应用场景:声明对象类型使用 const,非对象类型声明选择 let
//声明常量
const SCHOOL = '尚硅谷';
//1. 一定要赋初始值
// const A;
//2. 一般常量使用大写(潜规则)
// const a = 100;
//3. 常量的值不能修改
// SCHOOL = 'ATGUIGU';
//4. 块儿级作用域
// {
// const PLAYER = 'UZI';
// }
// console.log(PLAYER);
//5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const TEAM = ['UZI','MXLG','Ming','Letme'];
// TEAM.push('Meiko');
变量解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称
为解构赋值。//数组的解构赋值 const arr = ['张学友', '刘德华', '黎明', '郭富城']; let [zhang, liu, li, guo] = arr; //对象的解构赋值 const lin = { name: '林志颖', tags: ['车手', '歌手', '小旋风', '演员'] }; let {name, tags} = lin; //复杂解构 let wangfei = { name: '王菲', age: 18, songs: ['红豆', '流年', '暧昧', '传奇'], history: [ {name: '窦唯'}, {name: '李亚鹏'}, {name: '谢霆锋'} ] }; let {songs: [one, two, three], history: [first, second, third]} = wangfei;
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
字符串中可以出现换行符
可以使用
${xxx}
形式输出变量// 定义字符串 let str = `<ul> <li>沈腾</li> <li>玛丽</li> <li>魏翔</li> <li>艾伦</li> </ul>`; // 变量拼接 let star = '王宁'; let result = `${star}在前几年离开了开心麻花`;
注意:当遇到字符串与变量拼接的情况使用模板字符串
对象简化写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这
样的书写更加简洁。
let name = '尚硅谷'; let slogon = '永远追求行业更高标准'; let improve = function () { console.log('可以提高你的技能'); } //属性和方法简写 let atguigu = { name, slogon, improve, change() { console.log('可以改变你') } };
注意:对象简写形式简化了代码,所以以后用简写就对了
箭头函数
ES6 允许使用「箭头」(=>)定义函数。
/** * 1. 通用写法 */ let fn = (arg1, arg2, arg3) => { return arg1 + arg2 + arg3; }
箭头函数的注意点:
如果形参只有一个,则小括号可以省略
函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
箭头函数 this 指向声明时所在作用域下 this 的值
箭头函数不能作为构造函数实例化
不能使用 arguments
/** * 2. 省略小括号的情况 */ let fn2 = num => { return num * 10; }; /** * 3. 省略花括号的情况 */ let fn3 = score => score * 20; /** * 4. this 指向声明时所在作用域中 this 的值 */ let fn4 = () => { console.log(this); }
注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适
//需求-1 点击 div 2s 后颜色变成『粉色』
//获取元素
let ad = document.getElementById('ad');
//绑定事件
ad.addEventListener("click", function(){
//保存 this 的值
// let _this = this;
//定时器
setTimeout(() => {
//修改背景颜色 this
// console.log(this);
// _this.style.background = 'pink';
this.style.background = 'pink';
}, 2000);
});
//需求-2 从数组中返回偶数的元素
const arr = [1,6,9,10,100,25];
// const result = arr.filter(function(item){
// if(item % 2 === 0){
// return true;
// }else{
// return false;
// }
// });
const result = arr.filter(item => item % 2 === 0);
console.log(result);
箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
参数默认值
ES6 允许给函数参数赋值初始值
- 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
function add(a,c=10,b) { return a + b + c; } let result = add(1,2); console.log(result);
- 与解构赋值结合
function connect({host="127.0.0.1", username,password, port}){ console.log(host) console.log(username) console.log(password) console.log(port) } connect({ host: 'atguigu.com', username: 'root', password: 'root', port: 3306 })
rest参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
/** * 作用与 arguments 类似 */ function add(...args){ console.log(args); } add(1,2,3,4,5); /** * rest 参数必须是最后一个形参 */ function minus(a,b,...args){ console.log(a,b,args); } minus(100,1,2,3,4,5,19);
注意:rest 参数非常适合不定个数参数函数的场景
spread 扩展运算符
扩展运算符(spread)也是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
/** * 展开数组 */ let tfboys = ['德玛西亚之力','德玛西亚之翼','德玛西亚皇子']; function fn(){ console.log(arguments); } fn(...tfboys) /** * 展开对象 */ let skillOne = { q: '致命打击', }; let skillTwo = { w: '勇气' }; let skillThree = { e: '审判' }; let skillFour = { r: '德玛西亚正义' }; let gailun = {...skillOne, ...skillTwo,...skillThree,...skillFour};
//1. 数组的合并 情圣 误杀 唐探
const kuaizi = ['王太利','肖央'];
const fenghuang = ['曾毅','玲花'];
// const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
console.log(zuixuanxiaopingguo);
//2. 数组的克隆
const sanzhihua = ['E','G','M'];
const sanyecao = [...sanzhihua];// ['E','G','M']
console.log(sanyecao);
//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments
symbol
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点
Symbol 的值是唯一的,用来解决命名冲突的问题
Symbol 值不能与其他数据进行运算
Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用 Reflect.ownKeys 来获取对象的所有键名
//创建 Symbol let s1 = Symbol(); console.log(s1, typeof s1); //添加标识的 Symbol let s2 = Symbol('尚硅谷'); let s2_2 = Symbol('尚硅谷'); console.log(s2 === s2_2); //使用 Symbol for 定义 let s3 = Symbol.for('尚硅谷'); let s3_2 = Symbol.for('尚硅谷'); console.log(s3 === s3_2);
注 遇到唯一性的场景时要想到 Symbol
//向对象中添加方法 up down
let game = {
name:'俄罗斯方块',
up: function(){},
down: function(){}
};
//声明一个对象
let methods = {
up: Symbol(),
down: Symbol()
};
game[methods.up] = function(){
console.log("我可以改变形状");
}
game[methods.down] = function(){
console.log("我可以快速下降!!");
}
console.log(game);
//
let youxi = {
name:"狼人杀",
[Symbol('say')]: function(){
console.log("我可以发言")
},
[Symbol('zibao')]: function(){
console.log('我可以自爆');
}
}
console.log(youxi)
迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费
原生具备 iterator 接口的数据(可用 for of 遍历)
a) Array
b) Arguments
c) Set
d) Map
e) String
f) TypedArray
g) NodeList
//声明一个数组 const xiyou = ['唐僧','孙悟空','猪八戒','沙僧']; //使用 for...of 遍历数组 for(let value of xiyou){ console.log(v); } //使用 for...in 遍历数组 for(let key of xiyou){ console.log(v); }
工作原理
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
d) 每调用 next 方法返回一个包含 value 和 done 属性的对象
注:需要自定义遍历数据的时候,要想到迭代器。
let iterator = xiyou[Symbol.iterator]();
console.log(iterator)
自定义遍历数据
<script>
//声明一个对象
const banji = {
name: "终极一班",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
[Symbol.iterator]() {
//索引变量
let index = 0;
//
let _this = this;
return {
next: function () {
if (index < _this.stus.length) {
const result = { value: _this.stus[index], done: false };
//下标自增
index++;
//返回结果
return result;
}else{
return {value: undefined, done: true};
}
}
};
}
}
//遍历这个对象
for (let v of banji) {
console.log(v);
}
</script>
生成器
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
//生成器其实就是一个特殊的函数 //异步编程 纯回调函数 node fs ajax mongodb //函数代码的分隔符 function * gen(){ yield '一只没有耳朵'; yield '一只没有尾巴'; return '真奇怪'; } let iterator = gen(); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next());
代码说明:
*的位置没有限制
生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值
yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码
next 方法可以传递实参,作为 yield 语句的返回值
生成器函数参数
function * gen(arg){ console.log(arg); 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()); //next方法可以传入实参 console.log(iterator.next('BBB')); console.log(iterator.next('CCC')); console.log(iterator.next('DDD')); //输出结果 AAA {value: 111, done: false} BBB {value: 222, done: false} CCC {value: 333, done: false} DDD {value: undefined, done: true}
生成器函数实例
// 异步编程 文件操作 网络操作(ajax, request) 数据库操作 // 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();
//模拟获取 用户数据 订单数据 商品数据 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();
set
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新元素,返回当前集合
- delete 删除元素,返回 boolean 值
- has 检测集合中是否包含某个元素,返回 boolean 值
- clear 清空集合,返回 undefined
//创建一个空集合
let s = new Set();
//创建一个非空集合
let s1 = new Set([1,2,3,1,2,3]);
//集合属性与方法
//返回集合的元素个数
console.log(s1.size);
//添加新元素
console.log(s1.add(4));
//删除元素
console.log(s1.delete(1));
//检测是否存在某个值
console.log(s1.has(2));
//清空集合
console.log(s1.clear());
//声明一个 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
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);
class
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
- class 声明类
- constructor 定义构造函数初始化
- extends 继承父类
- super 调用父级构造方法
- static 定义静态方法和属性
- 父类方法可以重写
//手机
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);
//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);
继承
//手机
function Phone(brand, price){
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function(){
console.log("我可以打电话");
}
//智能手机
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("我可以拍照")
}
SmartPhone.prototype.playGame = function(){
console.log("我可以玩游戏");
}
const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch');
console.log(chuizi);
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();
get & set
// get 和 set
class Phone{
get price(){
console.log("价格属性被读取了");
return 'iloveyou';
}
set price(newVal){
console.log('价格属性被修改了');
}
}
//实例化对象
let s = new Phone();
// console.log(s.price);
s.price = 'free';
数值扩展
//0. Number.EPSILON 是 JavaScript 表示的最小精度
//EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
// function equal(a, b){
// if(Math.abs(a-b) < Number.EPSILON){
// return true;
// }else{
// return false;
// }
// }
// console.log(0.1 + 0.2 === 0.3);
// console.log(equal(0.1 + 0.2, 0.3))
//1. 二进制和八进制
// let b = 0b1010;
// let o = 0o777;
// let d = 100;
// let x = 0xff;
// console.log(x);
//2. Number.isFinite 检测一个数值是否为有限数
// console.log(Number.isFinite(100));
// console.log(Number.isFinite(100/0));
// console.log(Number.isFinite(Infinity));
//3. Number.isNaN 检测一个数值是否为 NaN
// console.log(Number.isNaN(123));
//4. Number.parseInt Number.parseFloat字符串转整数
// console.log(Number.parseInt('5211314love'));
// console.log(Number.parseFloat('3.1415926神奇'));
//5. Number.isInteger 判断一个数是否为整数
// console.log(Number.isInteger(5));
// console.log(Number.isInteger(2.5));
//6. Math.trunc 将数字的小数部分抹掉
// console.log(Math.trunc(3.5));
//7. Math.sign 判断一个数到底为正数 负数 还是零
console.log(Math.sign(100));
console.log(Math.sign(0));
console.log(Math.sign(-20000));
对象扩展
//1. Object.is 判断两个值是否完全相等
// console.log(Object.is(120, 120));// ===
// console.log(Object.is(NaN, NaN));// ===
// console.log(NaN === NaN);// ===
//2. Object.assign 对象的合并
// const config1 = {
// host: 'localhost',
// port: 3306,
// name: 'root',
// pass: 'root',
// test: 'test'
// };
// const config2 = {
// host: 'http://atguigu.com',
// port: 33060,
// name: 'atguigu.com',
// pass: 'iloveyou',
// test2: 'test2'
// }
// console.log(Object.assign(config1, config2));
//3. Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
name: '尚硅谷'
}
const cities = {
xiaoqu: ['北京','上海','深圳']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);
Promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
- Promise 构造函数: Promise (excutor) {}
- Promise.prototype.then 方法
- Promise.prototype.catch 方法
promide 介绍
//实例化 Promise 对象
//形参名称约定为 rsolve,reject
const p = new Promise(function(resolve, reject){
//异步操作
setTimeout(function(){
// let data = '数据库中的用户数据';
// resolve
// resolve(data); //异步操作成功,调用resolve方法
console.log("zs")
let err = '数据读取失败';
reject(err);//异步操作出现异常调用reject方法
}, 5000);
});
//调用 promise 对象的 then 方法 执行对应的回调方法
p.then(function(value){//resolve
console.log(value);
}, function(reason){//reject
console.error(reason);
})
promise封装读取文件
//1. 引入 fs 模块
const fs = require('fs');
//2. 调用方法读取文件
// fs.readFile('./resources/为学.md', (err, data)=>{
// //如果失败, 则抛出错误
// if(err) throw err;
// //如果没有出错, 则输出内容
// console.log(data.toString());
// });
//3. 使用 Promise 封装
const p = new Promise(function(resolve, reject){
fs.readFile("./resources/为学.md", (err, data)=>{
//判断如果失败
if(err) reject(err);
//如果成功
resolve(data);
});
});
p.then(function(value){
console.log(value.toString());
}, function(reason){
console.log("读取失败!!");
});
promise封装Ajax
// 接口地址: https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "https://api.apiopen.top/api/getHaoKanVideo?page=0&size=10");
//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);
});
promise的then方法
//创建 promise 对象
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('用户数据');
// reject('出错啦');
}, 1000)
});
//调用 then 方法 then方法的返回结果是 Promise 对象, 对象状态由回调函数的执行结果决定
//1. 如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, 返回值为对象的成功的值
// const result = p.then(value => {
// console.log(value);
// //1. 非 promise 类型的属性
// // return 'iloveyou';
// //2. 是 promise 对象
// // return new Promise((resolve, reject)=>{
// // // resolve('ok');
// // reject('error');
// // });
// //3. 抛出错误
// // throw new Error('出错啦!');
// throw '出错啦!';
// }, reason=>{
// console.warn(reason);
// });
//链式调用
p.then(value=>{
}).then(value=>{
});
promise实践
//引入 fs 模块
const fs = require("fs");
// fs.readFile('./resources/为学.md', (err, data1)=>{
// fs.readFile('./resources/插秧诗.md', (err, data2)=>{
// fs.readFile('./resources/观书有感.md', (err, data3)=>{
// let result = data1 + '\r\n' +data2 +'\r\n'+ data3;
// console.log(result);
// });
// });
// });
//使用 promise 实现
const p = new Promise((resolve, reject) => {
fs.readFile("./resources/为学.md", (err, data) => {
resolve(data);
});
});
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/插秧诗.md", (err, data) => {
resolve([value, data]);
});
});
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/观书有感.md", (err, data) => {
//压入
value.push(data);
resolve(value);
});
})
}).then(value => {
console.log(value.join('\r\n'));
});
promise的catch
const p = new Promise((resolve, reject)=>{
setTimeout(()=>{
//设置 p 对象的状态为失败, 并设置失败的值
reject("出错啦!");
}, 1000)
});
// p.then(function(value){}, function(reason){
// console.error(reason);
// });
p.catch(function(reason){
console.warn(reason);
});
模块化
模块化简介
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势有以下几点:
- 防止命名冲突
- 代码复用
- 高维护性
ES6 之前的模块化规范有:
- CommonJS => NodeJS、Browserify
- AMD => requireJS
- CMD => seaJS
模块化语法
//分别暴露
export let school = '尚硅谷';
export function teach() {
console.log("我们可以教给你开发技能");
}
//统一暴露
let school = '尚硅谷';
function findJob(){
console.log("我们可以帮助你找工作!!");
}
//
export {school, findJob};
//默认暴露
export default {
school: 'ATGUIGU',
change: function(){
console.log("我们可以改变你!!");
}
}
<script type="module">
//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";
</script>
引入语法
<script type="module">
//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);
</script>
引入入口文件
//入口文件
//模块引入
import * as m1 from "./m1.js";
import * as m2 from "./m2.js";
import * as m3 from "./m3.js";
// console.log(m1);
// console.log(m2);
// console.log(m3);
// m1.teach();
// m2.findJob();
// m3.default.change();
//修改背景颜色为粉色
import $ from 'jquery';// const $ = require("jquery");
$('body').css('background','pink');
<script src="./src/js/app.js" type="module"></script>
将高级语法编译为ES5语法
<!--
1. 安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D
2. 编译 npx babel src/js -d dist/js --presets=babel-preset-env
3. 打包 npx browserify dist/js/app.js -o dist/bundle.js
-->
<script src="dist/bundle.js"></script>
ES7 新特性
Array.prototype.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 函数执行的返回值决定
//async 函数
async function fn(){
// 返回一个字符串
// return '尚硅谷';
// 返回的结果不是一个 Promise 类型的对象, 返回的结果就是成功 Promise 对象
// return;
//抛出错误, 返回的结果是一个失败的 Promise
// throw new Error('出错啦!');
//返回的结果如果是一个 Promise 对象
return new Promise((resolve, reject)=>{
resolve('成功的数据');
// reject("失败的错误");
});
}
const result = fn();
//调用 then 方法
result.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
})
await函数
- await 必须写在 async 函数中
- await 右侧的表达式一般为 promise 对象
- await 返回的是 promise 成功的值
- await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
//创建 promise 对象
const p = new Promise((resolve, reject) => {
// resolve("用户数据");
reject("失败啦!");
})
// await 要放在 async 函数中.
async function main() {
try {
let result = await p;
//
console.log(result);
} catch (e) {
console.log(e);
}
}
//调用函数
main();
async 和 await 结合使用
//1. 引入 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();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>发送 AJAX 请求</title>
</head>
<body>
<script>
// 发送 AJAX 请求, 返回的结果是 Promise 对象
function sendAJAX(url) {
return new Promise((resolve, reject) => {
//1. 创建对象
const x = new XMLHttpRequest();
//2. 初始化
x.open('GET', url);
//3. 发送
x.send();
//4. 事件绑定
x.onreadystatechange = function () {
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
//成功啦
resolve(x.response);
}else{
//如果失败
reject(x.status);
}
}
}
})
}
//promise then 方法测试
// sendAJAX("https://api.apiopen.top/getJoke").then(value=>{
// console.log(value);
// }, reason=>{})
// async 与 await 测试 axios
async function main(){
//发送 AJAX 请求
let result = await sendAJAX("https://api.apiopen.top/getJoke");
//再次测试
let tianqi = await sendAJAX('https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')
console.log(tianqi);
}
main();
</script>
</body>
</html>
对象方法扩展
//声明对象
const school = {
name:"尚硅谷",
cities:['北京','上海','深圳'],
xueke: ['前端','Java','大数据','运维']
};
//获取对象所有的键
console.log(Object.keys(school));
//获取对象所有的值
console.log(Object.values(school));
//entries
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 参数和扩展运算符
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'
});
//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: '金钟罩'
正则扩展-命名捕获分组
//声明一个字符串
// 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]);
// // console.log(result[2]);
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模式
//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
//二维数组
// 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
let str = ' iloveyou ';
console.log(str);
console.log(str.trimStart());
console.log(str.trimEnd());
flat 与 flatMap
//flat 平
//将多维数组转化为低位数组
// 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]);
console.log(result);
Symbol.prototype.description
//创建 Symbol
let s = Symbol('尚硅谷');
//通过 description 可以获取到属性
console.log(s.description);
ES11
私有属性
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('晓红', 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]);
// const res = Promise.all([p1, p2]);
console.log(res);
String.prototype.matchAll
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>.*?<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
<button id="btn">点击</button>
<script src="./js/app.js" type="module"></script>
// import * as m1 from "./hello.js";
//获取元素
const btn = document.getElementById('btn');
btn.onclick = function(){
import('./hello.js').then(module => {
module.hello();
});
}
export function hello(){
alert('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))
globalThis
全局this