1. 解构赋值
// 数组
let arr = ['apple', 'pear', 'bananar', 'sour'];
let [a, b, c, d] = arr;
console.log(a, b, c, d); // apple pear bananar sour
// 对象
let obj = {
uname: 'Tom',
age: 18,
play: function() {
console.log('like ping-pong');
}
}
let {uname, age, play} = obj;
console.log(uname, age, play)
play(); // like ping-pong
2. 函数参数的默认值
// 默认放最后,否则可能导致出错
function fn(a, b, c=10) {
return a + b + c;
}
let res = fn(1, 2);
console.log(res); // 13
3. rest参数
// 以前获取函数实参,伪数组
function fn1() {
console.log(arguments);
// Arguments(3) ['Tom', 'Jerry', 'Lily', callee: ƒ, Symbol(Symbol.iterator): ƒ]
}
fn1('Tom', 'Jerry', 'Lily');
// rest获取实参,真数组
function fn2(...args) {
console.log(args); // ['cat', 'mouse', 'people']
}
fn2('cat', 'mouse', 'people');
4. 扩展用算符(…)
// 1、数组合并
let arr1 = [1, 2, 3, 4];
let arr2 = ['a', 'b'];
let newarr1 = arr1.concat(arr2);
let newarr2 = [...arr1, ...arr2];
console.log(newarr1, '-----', newarr2);
// 2、浅拷贝
let arr3 = ['sily', 3, 'haha'];
// let arr4 = arr3;不可取,当一个值发生改变,原数组和拷贝数组都发生改变
let newarr3 = [...arr3];
console.log(newarr3);
// 3、转为参数序列
function add(x, y) {
return x + y;
}
let num = [10, 30];
let addRes = add(...num); // 40
// 4、与解构赋值结合,生成数组
let [num1, ...rest] = [1, 2, 3, 4, 5];
console.log(num1);// 1
console.log(rest);// [2, 3, 4, 5]
// 5、将字符串变为数组
let haha = [...'Hello']
console.log(haha); // ['H', 'e', 'l', 'l', 'o']
// 6、将伪数组转为真数组
function fun() {
const args = [...arguments];
// const args = Array.prototype.slice.call(arguments); 也可以转化(ES5)
console.log(args); // ['a', 'b', 'c']
}
fun('a', 'b', 'c');
// 对象的扩展运算符
// 将对象中可枚举的属性进行浅拷贝
let oneobj = {
sex: 'boy',
age: 10,
play() {
console.log('happy');
}
}
let shallow = {...oneobj}; // 等价与 Object.assign({}, oneobj)
shallow.play(); // happy
shallow.sex = 'girl';
console.log(shallow.sex, '===', oneobj.sex); // girl === boy
5. Symbol基本数据类型
// 创建一个独一无二的值,不能参与运算
let s1 = Symbol();
let s2 = Symbol('Tom');
let s3 = Symbol('Tom');
console.log(s2 == s3);// false
// Symbol.for 创建
let s4 = Symbol.for('Jerry');
let s5 = Symbol.for('Jerry');
console.log(s4 == s5);// true
// 创建对象属性
// 第一种
let origin = {
name: 'haha',
down: '下',
up: '上',
}
let methods = {
down: Symbol(),
up: Symbol(),
}
origin[methods.down] = function() {
console.log('this is down');
}
origin[methods.up] = function() {
console.log('this is up');
}
// 第二种
let bar = {
age: 19,
[Symbol('play')]: function() {
console.log('hahahah')
}
}
console.log(bar)
6. iterator迭代器
-
内置迭代器的有
-
Array
-
Arguments
-
Set
-
Map
-
String
-
TypedArray
-
NodeList
-
-
工作原理
-
创建一个指针对象,指向当前数据结构的起始位置
-
第一次调用对象的next方法,指针自动指向数据结构的第一个成员
-
不断调用next方法,指针一直向后移动知道最后一个成员
-
每次调用next方法会返回一个包含value和done属性的对象,其中value为遍历对象的值,done为知否遍历完成;当遍历结束后{value:undefined,done:true}
- 需要自定义遍历数据时,可用迭代器
// Symbol.iterator const arr = ['one', 'two', 'three']; let iterator = arr[Symbol.iterator](); console.log(iterator.next()); // {value: 'one', done: false}
-
-
自定义遍历数据
var xiyou = { author: '吴承恩', member: [ '孙悟空', '唐僧', '猪八戒', '沙和尚' ], [Symbol.iterator]() { let i = 0; return { next: () => { if (i < this.member.length) { let res = { value: this.member[i], done: false } i++ return res; } else { return { value: undefined, done: true }; } } } } } for (let v of xiyou) { console.log(v); // 孙悟空 唐僧 猪八戒 沙和尚 }
7. 生成器
function one() {
setTimeout(() => {
console.log('AAA');
aterator.next()
}, 1000);
}
function two() {
setTimeout(() => {
console.log('BBB');
aterator.next()
}, 2000);
}
function three() {
setTimeout(() => {
console.log('CCC');
aterator.next()
}, 3000);
}
function* gen() {
yield one();
yield two();
yield three();
}
// 调用gen()
let aterator = gen();
aterator.next(); // 调用第一个函数 AAA
// aterator.next(); // 调用第二个函数 BBB
// aterator.next(); // 调用第三个函数 CCC
// 需求: 依次获取 用户数据 订单数据 产品数据
function userDate() {
setTimeout(() => {
let user = "用户数据";
result.next(user)
}, 1000);
}
function orderDate() {
setTimeout(() => {
let order = "订单数据";
result.next(order)
}, 1000);
}
function goodsDate() {
setTimeout(() => {
let goods = "产品数据";
result.next(goods)
}, 1000);
}
function *totalRequire() {
let getuser = yield userDate();
console.log(getuser );// (隔一秒) 用户数据
let getorder = yield orderDate();
console.log(getorder);// (隔一秒) 订单数据
let getgoods = yield goodsDate();
console.log(getgoods);// (隔一秒) 产品数据
}
let result = totalRequire();
result.next();
8. Promise
-
Promise的状态:(实例对象中的一个属性【PromiseState】)
-
pending:未决定的(初始默认)
-
resolved / fullfilled:成功
-
rejected:失败
-
-
Promise状态改变:
-
pending变为resolved
-
pending变为rejected
-
一个promise对象只能改变一次,无论成功失败都有一个结果数据
-
-
Promise对象的值:(实例对象中的一个属性【PromiseResult】,异步保存对象【成功/失败】的结果)
-
resolve
-
reject
-
(1)利用Promise读取多个文件, 解决回调地狱
const fs = require('fs');
let p = new Promise((resolve, reject) => {
fs.readFile('./files/cat.txt', (err, data) => {
if (err) reject(err);
resolve(data)
})
})
p.then((value) => {
// console.log(value.toString());
return new Promise((resolve, reject) => {
fs.readFile('./files/dog.txt', (err, data) => {
if (err) reject(err);
resolve([value, data]);
})
})
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile('./files/people.txt', (err, data) => {
if (err) throw err
value.push(data)
resolve(value)
})
})
}).then(value => {
console.log(value.join('\n\r'));
})
(2)Promise封装ajax操作
<body>
<div>
<h1>封装ajax操作</h1>
<button class="btn">获取</button>
</div>
<script>
const btn = document.querySelector('.btn');
btn.onclick = function() {
const p = new Promise((resolve, reject) => {
// 创建对象
const xhr = new XMLHttpRequest();
// 初始化
xhr.open('GET', 'https://api.apiopen.top/getJoke');
// 发送
xhr.send();
// 处理响应结果
xhr.onreadystatechange = function() {
if(xhr.readyState = 4) {
// 判断响应状态码
if(xhr.status >= 200 && xhr.status < 300) {
// 输出响应体
resolve(xhr.response);
} else {
// 输出响应状态码
reject(xhr.status);
}
}
}
})
p.then((val) => {
console.log(val);
}, (err) => {
console.warn(err);
})
}
</script>
</body>
function sendAJAX(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.responseType = 'json';// 返回响应体的格式
xhr.open('GET', url);
xhr.send();
xhr.onreadystatechange = function() {
if(xhr.readyState = 4) {
if(xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
}else {
reject(xhr.status);
}
}
}
})
}
// 使用
sendAJAX('https://api.apiopen.top/getJoke').then(val => {
console.log(val)
}).catch(err => {
console.log(err)
})
(3)Promise封装fs读取文件
const fs = require('fs');
// 封装函数
function toReadFiles(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, (err, data) => {
if (err) reject(err)
resolve(data)
})
})
}
// 执行
toReadFiles('./files/cat.txt').then(val => {
console.log(val.toString());
}, err => {
console.log(err);
})
(4)fs读取文件借助内置方法util
// 借助内置方法util.promisify()
const util = require('util');
const fs = require('fs');
let myReadFile = util.promisify(fs.readFile);
myReadFile('./files/dog.txt').then(val => {
console.log(val.toString());
}).catch(err => {
console.log(err);
})
(5)Promise的API
-
Promise.resolve(参数)
-
参数为非Promise类型的对象,返回的结果为成功的promise对象
-
参数为Promise对象,则参数的结果决定了resolve的结果
let p1 = Promise.resolve(520) console.log(p1); let p2 = Promise.resolve(new Promise((resolve, reject) => { // resolve('ok') reject('err') })) // console.log(p2); p2.catch(err => { console.log(err); })
-
-
Promise.reject(参数):无论传入什么参数,状态是失败的状态,结果是传入的值
-
Promise.all (由promise组成的数组):所有的promise对象全部成功,才返回成功,且值为所有promise结果组成的数据;如果有失败,值为失败的那个值
let p1 = new Promise((resolve, reject) => { resolve('ok'); }) let p2 = Promise.resolve('成功'); let p3 = Promise.resolve('hahahah'); let resultFinal = Promise.all([p1, p2, p3]) console.log(resultFinal);
let p1 = new Promise((resolve, reject) => { resolve('ok'); }) let p2 = Promise.reject('Error'); let p3 = Promise.resolve('hahahah'); let resultFinal = Promise.all([p1, p2, p3]) console.log(resultFinal);
-
Promise.race(由promise组成的数组):哪个先执行,哪个为最终结果
(6)关键问题
-
① Promise对象状态改变的方式
let p = new Promise((resolve, reject) => { // 1. //resolve('oj'); // 2. //reject('err'); // 3. 抛出错误 //throw "error" })
-
② Promise对象指定多个成功或失败的回调(then/catch),当promise改变状态时,都会调用
-
③ 改变promise状态和指定回调函数谁先谁后?
-
都有可能,当new Promise(function)里封装的是同步任务,先改状态再回调;当是异步任务,先回调再改状态
-
得到数据:①先指定回调,当状态发生改变,回调函数就会调用,得到数据;②先改变状态,当指定回调时,回调函数调用得到数据。
-
-
④ promise.then() 返回新的promise结果状态由then() 指定的回调函数执行结果决定
-
如果抛出异常(throw error),新promise变为rejected
-
如果返回非promise的任意值,新promise为resolved
-
如果返回promise,它的结果为新promise的结果
-
-
⑤ promise如果串联多个操作任务?
-
通过then的链式调用
-
-
⑥ promise异常传透?
-
通过then链式调用时,可以在最后指定失败的回调(catch)
-
前面任何操作出异常,都会传到最后失败的回调中处理
-
-
⑦ 中断promise链?
-
回调函数中返回一个pendding状态的promise对象
let p = new Promise((resolve, reject) => { resolve('ok'); }) p.then(val => { console.log('111') return new Promise(() => {}) }).then(val => { console.log('222') })
-
9. async函数
-
async函数的返回值是promise对象
-
promise对象的结果由async函数执行的返回值决定(同then的)
-
await表达式
-
await右侧的表达式一般为promise对象,也可以是其他值
-
表达式如果是promise对象,await返回的是promise成功的值
-
表达式时其他值,直接将此值作为await的返回值
-
// 获取多个文件的数据
const fs = require('fs');
const util = require('util');
const myReadFile = util.promisify(fs.readFile);
async function getFilesData() {
try {
const file1 = await myReadFile('./files/cat.txt');
const file2 = await myReadFile('./files/dog.txt');
const file3 = await myReadFile('./files/people.txt');
console.log(file1 + file2 + file3);
} catch (error) {
console.log(error);
}
}
getFilesData()
10. Set
// 声明一个set
let s = new Set();
let s2 = new Set(['good', 'nice', 'prefect', 'great']);
console.log(s2.size);// 4
// 添加
s2.add('wonderfull');
console.log(s2);
// 删除
s2.delete('nice')
// 是否存在
console.log(s2.has('nice'));// false
// 清空
// s2.clear()
console.log(s2);
for(const v of s2) {
console.log(v);
}
-
① 数组去重
let arr1 = [1, 2, 3, 4, 5, 5, 5, 4, 3, 2]; console.log(new Set(arr1)); // Set(5) { 1, 2, 3, 4, 5 } let res1 = [...new Set(arr1)]; console.log(res1);// [ 1, 2, 3, 4, 5 ]
-
② 交集
let arr1 = [1, 2, 3, 4, 5, 5, 5, 4, 3, 2]; let arr2 = [3, 3, 4, 4, 6]; let res2 = [...new Set(arr1)].filter(item => new Set(arr2).has(item)); console.log(res2);// [ 3, 4 ]
-
③ 并集
let arr1 = [1, 2, 3, 4, 5, 5, 5, 4, 3, 2]; let arr2 = [3, 3, 4, 4, 6]; let res3 = [...new Set([...arr1, ...arr2])] console.log(res3); // [ 1, 2, 3, 4, 5, 6 ]
-
④ 差集
let arr1 = [1, 2, 3, 4, 5, 5, 5, 4, 3, 2]; let arr2 = [3, 3, 4, 4, 6]; let res4 = [...new Set(arr1)].filter(item => !(new Set(arr2).has(item))); console.log(res4); // [ 1, 2, 5 ]
11. Map
let map = new Map();
// 1. 设置, key和value, 类型为任意
map.set('name', 'Tom');
map.set(2, function(){
console.log('haha');
})
map.set({xixi: '嘻嘻'}, true);
// 2. 个数
console.log(map.size); // 3
// 3. 查找
console.log(map.get(2));
// 4. 删除
map.delete('name');
// 5. 是否存在
console.log(map.has('name'));// false
console.log(map);
// 6. 清空
map.clear();
12. Class
-
class关键字
class Cat {
// 构造函数
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHi() {
console.log('miao~');
}
}
const cat = new Cat('Tom', 2);
console.log(cat.name, cat.age); //Tom 2
cat.sayHi(); //miao~
-
static静态属性,实例无法使用
function Phone() {
}
Phone.name = 'Huawei';
Phone.price = 4999;
Phone.prototype.call = function() {
console.log('can all somebody');
}
const huawei = new Phone();
console.log(huawei.name, huawei.price); // undefined undefined
huawei.call();// can all somebody
class Phone2 {
name = "Xiaomi";
price = 2999;
// static 静态属性
static color = "black";
}
const xiaomi = new Phone2()
console.log(xiaomi.name, xiaomi.price); // Xiaomi 2999
console.log(xiaomi.color); // undefined
-
继承
// ES5原型继承
function Phone3(brand, price) {
this.brand = brand;
this.price = price;
this.call = function() {
console.log('打电话');
}
}
function SmartPhone(brand, price, color, size) {
Phone3.call(this, brand, price);
this.color = color;
this.size = size;
}
SmartPhone.prototype = new Phone3;
SmartPhone.prototype.constructor = SmartPhone;
SmartPhone.prototype.chat = function() {
console.log('聊微信');
}
SmartPhone.prototype.movie = function() {
console.log('看电影');
}
const smartphone = new SmartPhone('iPhone', 5999, 'white', '5.5inch');
console.log(smartphone.brand, smartphone.price, smartphone.color, smartphone.size); // iPhone 5999 white 5.5inch
smartphone.call(); // 打电话
smartphone.chat(); // 聊微信
smartphone.movie(); // 看电影
// class类继承
class Father {
constructor(house, money) {
this.house = house;
this.money = money;
}
play() {
console.log('打牌');
}
}
class Son extends Father{
constructor(house, money, cat , car) {
super(house, money);
this.cat = cat;
this.car = car;
}
learn() {
console.log('study hard');
}
play() {
console.log('打球');
}
}
const son = new Son(1, '100RMB', 'Tom', 'BMW');
console.log(son); // Son { house: 1, money: '100RMB', cat: 'Tom', car: 'BMW' }
son.play(); // 打牌 重新改写后为 打球
son.learn(); // study hard
-
get和set
class Dog {
constructor(name) {
this._name = name;
}
// 获取属性
get name() {
console.log('拿到了属性值');
return this._name;
}
// 设置属性
set name(newVal) {
console.log('设置了属性值');
this._name = newVal;
}
}
const dog = new Dog('Dark');
console.log(dog.name); // Dark
dog.name = 'heihei'
console.log(dog.name); // heihei
13. 模块化
-
好处:
-
防止命名冲突
-
代码复用
-
高维护性
-
-
ES6之前的模块化规范:
-
CommonJS => NodeJS、Browserify
-
AMD => requireJS
-
CMD => seaJS
-
-
ES6模块化语法
-
export
-
import
// 暴露方式: (文件m1.js) // 1、分别暴露 export let school = "Ming"; export function goto() { console.log('go to Ming School'); } // export {school, goto} 2、统一暴露 // 3、默认暴露 /* export default { xxx }*/ // 引入方式:(文件m1.js暴露的东西) // 1、通用的导入放肆 import * as m1 from './m1.js' // 2、解构赋值的方式 import {school, goto} from './m1.js' // 3、简便形式 只针对默认暴露 import m1 from './m1.js'
-