Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
1.可以避免多层异步调用嵌套问题(即回调地狱)
2.Promise 对象提供了简洁的API,使得控制异步操作更加容易(js执行机制导致的异步问题)
这三种状态不受外界影响,而且状态只能从pending改变为resolved或者rejected,并且不可逆
then方法可以接受两个函数,第一个函数为promise状态为成功的回调函数,第二个函数为promise状态为失败的回调函数(可以不写,一般用catch方法捕获promise状态为失败的异常信息)
Promise.all([p1, p2, p3]).then((result) => {
console.log(result);
})
Promise.race ( [p1,p2,p3] ).then ((result) => {
console. log (result)
})
用来处理Promise的状态变化,这个函数的第一个参数表示promise的状态为成功,第二个参数表示promise的状态为失败,这两个参数(名字可以自己命名)都为一个函数,他们的作用分别是将promise状态修改为resolved(成功)和rejected(失败)。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.log(reason);
});
// 1. 引入fs模块
const fs = require('fs');
const { writer } = require('repl');
// 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("读取失败!!!");
})
打开终端,输入:node 02/Promise读取文件.js
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>发送AJAXtitle>
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>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise.prototype.thentitle>
head>
<body>
<script>
// 创建promise对象
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('用户数据');
}, 1000);
});
// 调用then方法 then方法的返回结果时Promise对象 对象状态由回调函数阿执行结果决定
// 1. 如果回调函数中返回的结果是 非promise类型的属性 状态为成功 返回值为对象的成功的值
// const result = p.then(value => {
// console.log(value);
// 1. 非promise类型的属性
// return 123;
// 2. 是promise对象
// return new Promise((resolve, reject) => {
// // resolve('ok');
// reject('error');
// });
// 3. 抛出错误
// throw '出错啦!';
// }, reason => {
// console.warn(reason);
// })
// console.log(result);
// 链式调用
p.then(value => {
}).then(value => {
})
script>
body>
html>
// 引入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'));
})
相当于then方法没有第一个函数参数, 处理失败状态
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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(reaosn){
// console.log(reason);
// });
p.catch(function(reason) {
console.log(reason);
})
script>
body>
html>
ES6提供了新的数据结构Set(集合)。它类似于数组,但成员的值都是唯
一的,集合实现了iterator接口,所以可以使用「扩展运算符」和「for…of…」进行遍历,集合的属性和方法:
// 创建一个空集合
let s = new Set();
// 创建一个非空集合
let s1 = new Set([1, 2, 3, 1, 2, 3]);
// 返回集合元素个数
console.log(s2.size);
// 添加新的元素
s2.add('喜事儿');
// 删除元素
s2.delete('坏事儿');
// 检测是否存在某个值
console.log(s2.has('糟心事'));
// 清空集合
s2.clear();
ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”
的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现
了iterator接口,所以可以使用[扩展运算]和[for…of…]进行遍历。Map
的属性和方法:
// 创建一个空map
let m = new Map();
// 创建一个非空map
let m2 = new Map([
['name','尚硅谷'],
['slogon','不断提高行业标准']
]);
//属性和方法
//获取映射元素的个数
console. log(m2.size);
//添加映射值
console.log(m2.set('age'
, 6));
//获取映射值
console.log(m2.get('age'));
//检测是否有该映射
console.log(m2.has('age'));
//清除
console.log (m2.clear());
ES6提供了更接近传统语言的写法,引入了Class (类)这个概念,作为对
象的模板。通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而己。
知识点:
eg:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>类声明title>
head>
<body>
<script>
// 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);
// class
class Phone {
// 构造方法 名字不能修改
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
// 方法必须使用该语法,不能使用ES5的对象完整形式
call() {
console.log("我可以打电话!!");
}
}
let onePlus = new Phone("1 + ", 1999);
console.log(onePlus);
script>
body>
html>
eg:类的静态成员
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>静态成员title>
head>
<body>
<script>
// function Phone() {
// }
// Phone.name ='手机';
// Phone.change = function() {
// console.log("我可以改变世界");
// }
// Phone.prototype.size = '5.5inch';
// let nokia = new Phone();
// console.log(nokia.name); // undefined
// // nokia.change();
// console.log(nokia.size); // 5.5inch
class Phone {
static name = '手机';
static change() {
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia.name); // undefined
console.log(Phone.name); // 手机
script>
body>
html>
eg:ES5构造函数的继承
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象继承title>
head>
<body>
<script>
// ES5构造函数的继承
// 手机
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>
eg:ES6类继承和子类对父类方法的重写
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>类继承-2title>
head>
<body>
<script>
class Phone {
// 构造方法
constructor(brand, price) {
this.brand = bramd;
this.price = price;
}
// 父类的成员属性
call() {
console.log("我可以打电话!!");
}
}
class SmartPhone extends Phone {
// 构造方法
constructor(brand, price, color, size) {
super(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中的getter和setter设置
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>get 和 settitle>
head>
<body>
<script>
// get 和 set
class Phone {
get price() {
console.log("价格属性被读取了");
return "i love you"
}
set price(newVal) {
console.log('价格属性被修改了');
}
}
// 实例化对象
let s = new Phone();
// console.log(s.price);
s.price = 'free'
script>
body>
html>
ES6提供了二进制和八进制数值的新的写法,分别用前缀0b和0o表示。
Number.isFinite()用来检查一个数值是否为有限的
Number.isNaN()用来检查一个值是否为NaN
ES6将全局方法parseInt和parseFloat,移植到Number对象上面,使用不变。
用于去除一个数的小数部分,返回整数部分。
Number.isInteger()用来判断一个数值是否为整数
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数值扩展title>
head>
<body>
<script>
// 0. Number.EPSILON 是JavaScript表示的最小精度
// EPSILON 属性的值接近于2.220446049250310808472633361816E-16
console.log(0.1 + 0.2 === 0.3);
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('521123love'));
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 判断一个数到底是正数 负数 还是0
console.log(Math.sign(100)); // 1
console.log(Math.sign(0)); // 0
console.log(Math.sign(-2000)); // -1
script>
body>
html>
ES6新增了一些Object对象的方法
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象方法扩展title>
head>
<body>
<script>
// 1. Object.is 判断两个值是否完全相等
console.log(Object.is(200, 200)); // true
console.log(Object.is(NaN, NaN)); // true
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: 'yaya'
}
const cities = {
xiaoqu: ['北京', '上海', '深圳']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);
script>
body>
html>
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势有以下几点:
ES6之前的模块化规范有:
模块功能主要由两个命令构成:export和import。
// 分别暴露
export let school = 'yaya'
export function teach() {
console.log("我们可以教给你开发技能");
}
// 统一暴露
let school = 'yaya'
function findHappy() {
console.log('我可以帮助你得到快乐');
}
export { school, findHappy };
// 默认暴露
export default {
school: 'yaya',
change: function () {
console.log("我可以帮助你");
}
}
index.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES6模块化title>
head>
<body>
<script type="module">
// 引入m1.js模块内容 将暴露的数据存到m1中
import * as m1 from "./m1.js";
console.log(m1);
// 引入m2.jhs模块内容
import * as m2 from "./m2.js";
console.log(m2);
// 引入m3.js模块内容
import * as m3 from "./m3.js"
console.log(m3);
script>
body>
html>
ES6引入模块数据语法
index.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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 "./m1.js";
// console.log(m1);
// // 引入m2.jhs模块内容
// import * as m2 from "./m2.js";
// console.log(m2);
// // 引入m3.js模块内容
// import * as m3 from "./m3.js"
// console.log(m3);
// 2. 解构赋值形式
// import {school, teach} from './m1.js';
// import {school as sc, findHappy} from "./m2.js";
// import {default as m3} from "./m3.js";
// // console.log(school);
// // console.log(teach);
// // console.log(sc, findHappy);
// console.log(m3);
// 3. 简便形式 针对默认暴露
// import m3 from "./m3.js";
// console.log(m3);
script>
<script 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"
npm init --yes 初始化
npm i babel-cli babel-preset-env browserify -D
npx babel src/js -d dist/js --presets=babel-preset-env
npx browserify dist/js/app.js -o dist/bundle.js 打包



运行完之后,会多出一个文件夹:

bundle.js文件里面就是转化之后的ES5代码
打开浏览器,控制台输出跟之前一样

修改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.findHappy();
m3.default.change();
修改完文件之后,要重新进行打包:
npx babel src/js -d dist/js --presets=babel-preset-env
npx browserify dist/js/app.js -o dist/bundle.js 打包
打开浏览器,查看控制台:

通过jquery包对home.html的背景颜色进行修改
安装jquery包:
npm i jquery
然后重新打包:
npx babel src/js -d dist/js --presets=babel-preset-env
npx browserify dist/js/app.js -o dist/bundle.js
app.js
// 修改背景颜色为粉色
import $ from 'jquery'; // const $ = require("jquery");
$('body').css('background', 'pink');