ES6-11
ES6
同步与异步
同步任务和异步任务
为了防止某个耗时任务导致程序假死的问题,JavaScript 把待执行的任务分为了两类:
同步任务(synchronous)
又叫做非耗时任务,指的是在主线程上排队执行的那些任务 只有前一个任务执行完毕,才能执行后一个任务
异步任务(asynchronous)
又叫做耗时任务,异步任务由 JavaScript 委托给宿主环境进行执行
当异步任务执行完成后,会通知 JavaScript 主线程执行异步任务的回调函数
同步任务和异步任务的执行过程
let
特性
<!-- let.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script>
//声明变量
let a;
let b,c,d;
let e = 100;
let f = 521,g = 'iloveyou',h = [];
//1.变量不能重复声明
/* let star = '罗志祥';
let star = '小猪';
*/
//2.块级作用域
/* {
let man = '钢铁侠';
}
console.log(man); */
//3.不存在变量提升
/* console.log(song);
let song = 'aaa'; */
</script>
</body>
</html>
实践案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<!-- 用var会使i在页面渲染完成后就处于3,因此无法成功触发事件 -->
<body>
<div class="container">
<h2>点击切换颜色</h2>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script type="text/javascript">
let items = document.getElementsByClassName('item');
for(let i = 0;i<items.length;i++)
{
items[i].onclick = function(){
items[i].style.background = 'pink';
}
}
</script>
<style type="text/css">
.item{
width: 100px;
height: 100px;
border-style:solid;
border-color:black;
}
</style>
</body>
</html>
const
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>const</title>
</head>
<body>
<script type="text/javascript">
//声明常量
const SCHOOL = '催眠师';
//1.一定要赋初始值
// const A;
// 2.一般常量使用大写(潜规则)
// 3.常量的值不能修改
SCHOOL = 'cms';
// 4.块级作用域
/* {
const PLAYER = 'THE SHY';
}
console.log(PLAYER); */
// 5.对于数组和对象的元素修改,不算作对常量的修改,不会报错
/* const TEAM = ['Viper','THESHY','Jackeylove','ON'];
TEAM.push('SOFM'); */
</script>
</body>
</html>
变量的解构赋值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>变量的解构赋值</title>
</head>
<body>
<script>
//ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,
//这被称为解构赋值。
//1. 数组的结构
// const F4 = ['小沈阳','刘能','赵四','宋小宝'];
// let [xiao, liu, zhao, song] = F4;
// console.log(xiao);
// console.log(liu);
// console.log(zhao);
// console.log(song);
//2. 对象的解构
// const zhao = {
// name: '赵本山',
// age: '不详',
// xiaopin: function(){
// console.log("我可以演小品");
// }
// };
// let {name, age, xiaopin} = zhao;
// console.log(name);
// console.log(age);
// console.log(xiaopin);
// xiaopin();
let {xiaopin} = zhao;
xiaopin();
</script>
</body>
</html>
模板字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板字符串</title>
</head>
<body>
<script>
// ES6 引入新的声明字符串的方式 『``』 '' ""
//1. 声明
// let str = `我也是一个字符串哦!`;
// console.log(str, typeof str);
//2. 内容中可以直接出现换行符
let str = `<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
//3. 变量拼接
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`;
console.log(out);
</script>
</body>
</html>
对象的简化写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简化对象写法</title>
</head>
<body>
<script>
//ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
//这样的书写更加简洁
let name = '尚硅谷';
let change = function(){
console.log('我们可以改变你!!');
}
const school = {
name,
change,
improve(){
console.log("我们可以提高你的技能");
}
}
console.log(school);
</script>
</body>
</html>
箭头函数以及声明特点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>箭头函数</title>
</head>
<body>
<script>
// ES6 允许使用「箭头」(=>)定义函数。
//声明一个函数
// let fn = function(){
// }
// let fn = (a,b) => {
// return a + b;
// }
//调用函数
// let result = fn(1, 2);
// console.log(result);
//1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置 window 对象的 name 属性
window.name = '尚硅谷';
const school = {
name: "ATGUIGU"
}
//直接调用
// getName();
// getName2();
//call 方法调用
// getName.call(school);
// getName2.call(school);
//2. 不能作为构造实例化对象
// let Person = (name, age) => {
// this.name = name;
// this.age = age;
// }
// let me = new Person('xiao',30);
// console.log(me);
//3. 不能使用 arguments 变量
// let fn = () => {
// console.log(arguments);
// }
// fn(1,2,3);
//4. 箭头函数的简写
//1) 省略小括号, 当形参有且只有一个的时候
// let add = n => {
// return n + n;
// }
// console.log(add(9));
//2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
// 而且语句的执行结果就是函数的返回值
let pow = n => n * n;
console.log(pow(8));
</script>
</body>
</html>
箭头函数实践
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>箭头函数实践</title>
<style>
div {
width: 200px;
height: 200px;
background: #58a;
}
</style>
</head>
<body>
<div id="ad"></div>
<script>
//需求-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 有关的回调. 事件回调, 对象的方法
</script>
</body>
</html>
函数参数的默认值设置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>函数参数默认值</title>
</head>
<body>
<script>
//ES6 允许给函数参数赋值初始值
//1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
// function add(a,b,c=10) {
// return a + b + c;
// }
// let result = add(1,2);
// console.log(result);
//2. 与解构赋值结合
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
})
</script>
</body>
</html>
rest参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>rest参数</title>
</head>
<body>
<script>
// ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
// ES5 获取实参的方式
// function date(){
// console.log(arguments);
// }
// date('白芷','阿娇','思慧');
// rest 参数
// function date(...args){
// console.log(args);// filter some every map
// }
// date('阿娇','柏芝','思慧');
// rest 参数必须要放到参数最后
// function fn(a,b,...args){
// console.log(a);
// console.log(b);
// console.log(args);
// }
// fn(1,2,3,4,5,6);
</script>
</body>
</html>
扩展运算符的介绍
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>扩展运算符</title>
</head>
<body>
<script>
// 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』
//声明一个数组 ...
const tfboys = ['易烊千玺','王源','王俊凯'];
// => '易烊千玺','王源','王俊凯'
// 声明一个函数
function chunwan(){
console.log(arguments);
}
chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯')
</script>
</body>
</html>
扩展运算符的应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>扩展运算符应用</title>
</head>
<body>
<div></div>
<div></div>
<div></div>
<script>
//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
</script>
</body>
</html>
rest参数和扩展运算符的区别
rest 参数与扩展运算符
1.rest 参数
ES6 引入 rest 参数(形式为...
变量名),用于获取函数的多余参数,这样就不需要使用arguments
对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
上面代码的add
函数是一个求和函数,利用 rest 参数,可以向该函数传入任意数目的参数。
2.扩展运算符
扩展运算符(spread)是三个点(...
)。它将一个数组或对象转为用逗号分隔的参数序列。
对数组
console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]
对对象
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
3.分析
rest 参数与扩展运算符可以理解为互为逆运算
Symbol的介绍与创建
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>symbol</title>
</head>
<!-- ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。 -->
<body>
<script>
//创建Symbol
let s = Symbol();
// console.log(s, typeof s);
let s2 = Symbol('尚硅谷');
let s3 = Symbol('尚硅谷');
//Symbol.for 创建
let s4 = Symbol.for('尚硅谷');
let s5 = Symbol.for('尚硅谷');
//不能与其他数据进行运算
// let result = s + 100;
// let result = s > 100;
// let result = s + s;
// USONB you are so niubility
// u undefined
// s string symbol
// o object
// n null number
// b boolean
</script>
</body>
</html>
对象添加Symbol类型的属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Symbol 创建对象属性</title>
</head>
<body>
<script>
//向对象中添加方法 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)
</script>
</body>
</html>
Symbol的内置属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Symbol内置属性</title>
</head>
<body>
<script>
// class Person{
// static [Symbol.hasInstance](param){
// console.log(param);
// console.log("我被用来检测类型了");
// return false;
// }
// }
// let o = {};
// console.log(o instanceof Person);
// const arr = [1,2,3];
// const arr2 = [4,5,6];
// arr2[Symbol.isConcatSpreadable] = false;
// console.log(arr.concat(arr2));
</script>
</body>
</html>
迭代器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>迭代器</title>
</head>
<!-- 迭代的过程如下:
通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置
随后通过 next 方法进行向下迭代指向下一个位置,
next 方法会返回当前位置的对象,对象包含了 value 和 done 两个属性,
value 是当前属性的值, done 用于判断是否遍历结束
当 done 为 true 时则遍历结束 -->
<body>
<script>
//声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
//使用 for...of 遍历数组
// for(let v of xiyou){
// console.log(v);
// }
let iterator = xiyou[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
</script>
</body>
</html>
迭代器自定义遍历
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自定义遍历数据</title>
</head>
<body>
<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>
</body>
</html>
生成器函数声明与调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生成器</title>
</head>
<!-- 生成器函数在执行时能暂停 ,后面又能从暂停处继续执行。
调用一个生成器函数并不会马上执行它里面的语句,
而是返回一个这个生成器的迭代器对象。当这个迭代器的next()方法被首次调用,
其内的语句会执行到第一个出现yield的位置位置,yield后紧跟迭代器 -->
<body>
<script>
//生成器其实就是一个特殊的函数
//异步编程 纯回调函数 node fs ajax mongodb
//函数代码的分隔符
function * gen(){
// console.log(111);
yield '一只没有耳朵';
// console.log(222);
yield '一只没有尾部';
// console.log(333);
yield '真奇怪';
// console.log(444);
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//遍历
// for(let v of gen()){
// console.log(v);
// }
</script>
</body>
</html>
生成器函数的参数传递
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生成器函数参数</title>
</head>
<body>
<script>
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'));
</script>
</body>
</html>
生成器函数实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生成器函数实例</title>
</head>
<body>
<script>
// 异步编程 文件操作 网络操作(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();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生成器函数</title>
</head>
<body>
<script>
//模拟获取 用户数据 订单数据 商品数据
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();
</script>
</body>
</html>
Promise
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise基本语法</title>
</head>
<!-- Promise是异步编程的一种解决方案,
可以替代传统的解决方案--回调函数和事件。
ES6统一了用法,并原生提供了Promise对象。作为对象,Promise有一下两个特点:
*(1)对象的状态不受外界影响。
*(2)一旦状态改变了就不会在变,也就是说任何时候Promise都只有一种状态。 -->
<!-- Promise对象代表一个异步操作,有三种状态:Pending(进行中)
、Resolved(已完成 ,又称Fulfilled)和 Rejected(已失败)。
resolve(data)将这个promise标记为resolved,然后进行下一步
then((data)=>{//do something}),resolve里的参数就是传入then的数据 -->
<body>
<script>
//实例化 Promise 对象
const p = new Promise(function(resolve, reject){
setTimeout(function(){
//
// let data = '数据库中的用户数据';
// resolve
// resolve(data);
let err = '数据读取失败';
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法
p.then(function(value){
console.log(value);//输出 数据库中用户的数据
}, function(reason){
console.error(reason);//输出 数据读取失败
})
</script>
</body>
</html>
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/为学.mda", (err, data)=>{
//判断如果失败
if(err) reject(err);
//如果成功
resolve(data);
});
});
p.then(function(value){
console.log(value.toString());
}, function(reason){
console.log("读取失败!!");
});
Promise封装AJAX请求
<!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>
// 接口地址: https://api.apiopen.top/getJoke
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);
});
</script>
</body>
</html>
Promise.prototype…then方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise.prototype.then</title>
</head>
<body>
<script>
//创建 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=>{
});
</script>
</body>
</html>
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) => {
// 把第一个文件内容(value)和第二个文件内容(data)进行合并
resolve([value, data]);
});
});
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/观书有感.md", (err, data) => {
//在value中压入data
value.push(data);
resolve(value);
});
})
}).then(value => {
// 进行三个内容的拼接,用'\r\n'作为分隔
console.log(value.join('\r\n'));
});
Promise对象catch方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>catch方法</title>
</head>
<body>
<script>
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);
});
</script>
</body>
</html>
set集合
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>集合</title>
</head>
<!-- Set 是 ES6 提供的新的数据结构,类似于数组,但是成员的值都是唯一的,没有重复的值。(可以用于去重)
Set本身是一个构造函数,用来生成Set数据结构。 -->
<body>
<script>
//声明一个 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);
}
</script>
</body>
</html>
集合实践
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Set 实践</title>
</head>
<body>
<script>
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);
</script>
</body>
</html>
Map
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Map</title>
</head>
<!-- Map 对象
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
Maps 和 Objects 的区别
一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。
Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。 -->
<body>
<script>
//声明 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);
}
// console.log(m);
</script>
</body>
</html>
class
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>类声明</title>
</head>
<body>
<script>
//手机
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);
</script>
</body>
</html>
class静态成员
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>静态成员</title>
</head>
<!-- 静态成员的声明即在普通成员的声明前加static,其必须在类外定义,在定义时不加static;
当一个成员被声明为静态成员后这个成员就不属于某个具体的实例,而是为所有的类对象所共享 -->
<body>
<script>
// 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);//undefined
console.log(Phone.name);//手机
</script>
</body>
</html>
ES5构造函数继承
子类对父类方法的重写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>类继承-2</title>
</head>
<body>
<script>
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);// 调用父类的构造方法constructor,相当于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();
</script>
</body>
</html>
class的类继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象继承</title>
</head>
<body>
<script>
//手机
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);
</script>
</body>
</html>
class中get和set
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>get 和 set</title>
</head>
<!-- get 语句作为函数绑定在对象的属性上,当访问该属性时调用该函数。
set 语法可以将一个函数绑定在当前对象的指定属性上,
当那个属性被赋值时,你所绑定的函数就会被调用 -->
<body>
<script>
// get 和 set
class Phone{
get price(){
console.log("价格属性被读取了");
return 'iloveyou';
}
set price(newVal){//把新的price的值(free)传给newVal
console.log('价格属性被修改了');
}
}
//实例化对象
let s = new Phone();
// console.log(s.price);
s.price = 'free';
</script>
</body>
</html>
ES6的数值扩展
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数值扩展</title>
</head>
<body>
<script>
//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));
</script>
</body>
</html>
ES6的对象方法扩展
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象方法扩展</title>
</head>
<body>
<script>
//1. Object.is 判断两个值是否完全相等
// console.log(Object.is(120, 120));// true
// console.log(Object.is(NaN, NaN));// true
// console.log(NaN === NaN);// false
//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);
</script>
</body>
</html>
实现继承的几种方式
原型链继承
父类的实例作为子类的原型
function Woman(){
}
Woman.prototype= new People();
Woman.prototype.name = 'haixia';
let womanObj = new Woman();
优点:
简单易于实现,父类的新增的实例与属性子类都能访问
缺点:
可以在子类中增加实例属性,如果要新增加原型属性和方法需要在new 父类构造函数的后面
无法实现多继承
创建子类实例时,不能向父类构造函数中传参数
借用构造函数继承(伪造对象、经典继承)
复制父类的实例属性给子类
function Woman(name){
//继承了People
People.call(this); //People.call(this,'wangxiaoxia');
this.name = name || 'renbo'
}
let womanObj = new Woman();
优点:
解决了子类构造函数向父类构造函数中传递参数
可以实现多继承(call或者apply多个父类)
缺点:
方法都在构造函数中定义,无法复用
不能继承原型属性/方法,只能继承父类的实例属性和方法
实例继承(原型式继承)
function Wonman(name){
let instance = new People();
instance.name = name || 'wangxiaoxia';
return instance;
}
let wonmanObj = new Wonman();
优点:
不限制调用方式
简单,易实现
缺点:不能多次继承
Call bind apply的区别
apply方法
apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入,且当第一个参数为null、undefined的时候,默认指向window(在浏览器中),使用apply方法改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次。
call方法
call方法的第一个参数也是this的指向,后面传入的是一个参数列表(注意和apply传参的区别)。当一个参数为null或undefined的时候,表示指向window(在浏览器中),和apply一样,call也只是临时改变一次this指向,并立即执行。
bind方法
bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数。
模块化介绍、优势以及产品
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES6 模块化</title>
</head>
<!-- 模块化
说明:模块化是指将一个很大的程序文件,拆分为许多个小的文件,然后将多个小文件组合起来
模块化的好处:
① 阻止命名冲突; ② 代码复用; ③ 高维护性
-->
<body>
<script type="module">
//1. 通用的导入方式
//引入 m1.js 模块内容
// import * as m1 from "./src/js/m1.js";
// //引入 m2.js 模块内容
//import * as m2 from "./src/js/m2.js";
// console.log(m2)
// //引入 m3.js
// import * as m3 from "./src/js/m3.js";
console.log(m3);
// m3.default.change();
//2. 解构赋值形式
/* import {school, teach} from "./src/js/m1.js";
console.log(school); */
/* import {school as guigu, findJob} from "./src/js/m2.js";//school跟上面重名可以用school as guigu当别名
console.log(guigu,findJob); */
/* import {default as m3} from "./src/js/m3.js";
console.log(m3.school); */
//3. 简便形式 针对默认暴露
// import m3 from "./src/js/m3.js";
// console.log(m3);
</script>
<script src="./src/js/app.js" type="module"></script><!-- 使用入口文件导入 -->
</body>
</html>
//入口文件app.js
//模块引入
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');
//m1.js分别暴露
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.teach = teach;
//分别暴露
var school = exports.school = '尚硅谷';
function teach() {
console.log("我们可以教给你开发技能");
}
//m2.js统一暴露
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
//统一暴露
var school = '尚硅谷';
function findJob() {
console.log("我们可以帮助你找工作!!");
}
//
exports.school = school;
exports.findJob = findJob;
//m3.js默认暴露
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
//默认暴露
exports.default = {
school: 'ATGUIGU',
change: function change() {
console.log("我们可以改变你!!");
}
};
babel对ES6模块化代码转换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<!-- babel是一个广泛使用的转码器,可以将ES6代码转化为ES5代码,
从而在现有环境执行,这意味着,你可以现在就用ES6编写程序,
而不用担心现有环境是否支持。 -->
<body>
<!--
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
执行完目录下会出现bundle.js文件
每次修改dist/js目录下的js文件都要再执行2,3步才能生效
-->
<script src="dist/bundle.js"></script>
</body>
</html>
Null 和 undefined 的区别
undefined和null的区别:. ● undefined 表示一个变量没有被声明,或者被声明了但没有被赋值(未初始化),一个没有传入实参的形参变量的值为undefined,如果一个函数什么都不返回,则该函数默认返回undefined。. null 则表示"什么都没有",即"空值"。. ● Javascript将未赋值的变量默认值设为 undefined ;Javascript从来不会将变量设为 null 。. 它是用来让程序员表明某个用var声明的变量时没有值的;
前端缓存的理解 或者 前端数据持久化的理解
前端缓存分为HTTP缓存和浏览器缓存
其中HTTP缓存是在HTTP请求传输时用到的缓存,主要在服务器代码上设置;而浏览器缓存则主要由前端开发在前端js上进行设置。
缓存可以说是性能优化中简单高效的一种优化方式了。一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷。
对于一个数据请求来说,可以分为发起网络请求、后端处理、浏览器响应三个步骤。浏览器缓存可以帮助我们在第一和第三步骤中优化性能。比如说直接使用缓存而不发起请求,或者发起了请求但后端存储的数据和前端一致,那么就没有必要再将数据回传回来,这样就减少了响应数据。
强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程,强制缓存的情况主要有三种,如下:
①不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求
②存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存
③存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
①协商缓存生效,返回304
②协商缓存失效,返回200和请求结果
ES7
ES7新特性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES7 新特性</title>
</head>
<body>
<script>
// includes indexOf
// const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];
//判断
// console.log(mingzhu.includes('西游记'));
// console.log(mingzhu.includes('金瓶梅'));
// **
console.log(2 ** 10);// 等价于Math.pow(2, 10)
console.log(Math.pow(2, 10));
</script>
</body>
</html>
ES8
async函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>async函数</title>
</head>
<!-- 先从字面意思来理解。async 是“异步”的简写
,而 await 可以认为是 async wait 的简写。所以应该很好理解
async 用于申明一个 function 是异步的,
而 await 用于等待一个异步方法执行完成。
async与await分别都有语法,
两种语法结合就可以使异步代码像同步代码一样 -->
<body>
<script>
//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);
})
</script>
</body>
</html>
await表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>await</title>
</head>
<body>
<script>
//创建 promise 对象
const p = new Promise((resolve, reject) => {
// resolve("用户数据");
reject("失败啦!");
})
// await 要放在 async 函数中.
async function main() {
try {
let result = await p;
//await p返回的结果是p的状态和携带的值
console.log(result);
} catch (e) {
console.log(e);
}
}
//调用函数
main();
</script>
</body>
</html>
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();
async与await结合发送ajax请求
<!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>
ES8对象方法扩展
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES8 对象方法扩展</title>
</head>
<body>
<script>
//声明对象
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
// }
// });
</script>
</body>
</html>
ES9
ES9扩展运算符与rest参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象展开</title>
</head>
<body>
<!--
Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,
在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
-->
<script>
//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: '金钟罩'
</script>
</body>
</html>
正则扩展-命名捕获分组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>正则扩展-命名捕获分组</title>
</head>
<body>
<script>
//声明一个字符串
// 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);
</script>
</body>
</html>
正则扩展-反向断言
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>正则扩展-反向断言</title>
</head>
<body>
<script>
//声明字符串
let str = 'JS5211314你知道么555啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);
//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str);
console.log(result);
</script>
</body>
</html>
正则扩展-dotAll模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>正则扩展-dotAll模式</title>
</head>
<body>
<script>
//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;/* /s可以匹配所有空字符 */
//执行匹配
// 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);
</script>
</body>
</html>
ES10
对象与数组map互相转化方法Object.fromEntries
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Object.fromEntries</title>
</head>
<!-- Object.entries() 是将对象转成一个
自身可枚举属性的键值对数组。
Object.fromEntries 方法就是 entries 的逆操作,
作用是将一个键值对数组或者Map转化为一个对象 -->
<body>
<script>
//二维数组
// 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);
</script>
</body>
</html>
字符串清除空格-trimStrimStart 与 trimEnd
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>trimStart 与 trimEnd</title>
</head>
<!-- trim()方法是清除字符串两侧的空格
trimStart()是清除字符串左侧的空格
trimEnd()是清除字符串右侧的空格 -->
<body>
<script>
// trim
let str = ' iloveyou ';
console.log(str);
console.log(str.trimStart());
console.log(str.trimEnd());
</script>
</body>
</html>
数组方法扩展-flat与flatMap
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>flat 与 flatMap</title>
</head>
<body>
<script>
//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);
</script>
</body>
</html>
Symbol.prototype.description
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Symbol.prototype.description</title>
</head>
<body>
<script>
//创建 Symbol
let s = Symbol('尚硅谷');
console.log(s.description);
</script>
</body>
</html>
ES11
私有属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>私有属性</title>
</head>
<body>
<script>
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();
</script>
</body>
</html>
Promise.allSettled
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise.allSettled</title>
</head>
<!--
概念:
在es6推出的Promise实例中,有一个方法叫allSettled()。
通过Promise.allSettled()可以接收一个数组,并且在数组里面的所有实例,
全部执行完,再通过then方法或者catch方法,对数组里面的实例进行遍历与操作。
Promise.all()和Promise.allSettled()的区别
Promise.all()
如果其中一个 promise 失败了,则 Promise.all 整体将会失败。
例如,我们传递2个 promise, 一个完成的 promise 和
一个 失败的promise,那么 Promise.all 将立即失败。
Promise.allSettled()
从 ES2020 开始,你可以使用 Promise.allSettled。
当所有的 promises 都已经结束无论是完成状态或者是失败状态,
它都会返回一个 promise,这个 promise 将会包含一个关于描述
每个 promise 状态结果的对象数组。
对于每个结果对象,都有一个状态字符串:
fulfilled(完成) ✅
rejected(失败) ❌
-->
<body>
<script>
//声明两个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);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>String.prototype.matchAll</title>
</head>
<!-- matchAll() 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。 -->
<body>
<script>
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);
</script>
</body>
</html>
可选链操作符
let nestedProp = obj.first?.second;
通过使用 ?.
操作符取代 .
操作符,JavaScript
会在尝试访问 obj.first.second
之前,先隐式地检查并确定 obj.first
既不是 null
也不是 undefined
。如果obj.first
是 null
或者 undefined
,表达式将会短路计算直接返回 undefined
。
这等价于以下表达式,但实际上没有创建临时变量:
let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>可选链操作符</title>
</head>
<body>
<script>
// ?.
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'
}
})
</script>
</body>
</html>
动态import
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态 import </title>
</head>
<!-- 动态导入和静态导入的语法几乎相同,
区别在于不是将 import 作为语句使用,而是将 import 作为函数使用。
该函数接受一个参数,即模块的路径,并返回一个promise。 -->
<body>
<button id="btn">点击</button>
<script src="./js/app.js" type="module"></script>
</body>
</html>
// hello.js
export function hello(){
alert('Hello');
}
//app.js
// 动态导入和静态导入的语法几乎相同,
// 区别在于不是将 import 作为语句使用,而是将 import 作为函数使用。
// 该函数接受一个参数,即模块的路径,并返回一个promise。
// import * as m1 from "./hello.js";
//获取元素
const btn = document.getElementById('btn');
btn.onclick = function(){
import('./hello.js').then(module => {
module.hello();
});
}
BigInt类型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BigInt</title>
</head>
<!-- BigInt数据类型提供了一种方法来表示大于2^53-1的整数。BigInt可以表示任意大的整数 -->
<body>
<script>
//大整形
// 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))
</script>
</body>
</html>
绝对全局对象globalThis
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>globalThis</title>
</head>
<!-- 全局对象提供可在任何地方使用的变量和函数。默认情况下,这些全局变量内置于语言或环境中。
在浏览器中,它的名字是 "window",对 Node.js 而言,它的名字是 "global",其它环境可能用的是别的名字 -->
<body>
<script>
console.log(globalThis);
</script>
</body>
</html>