ES6-ES11 学习笔记

let,常用于 for 循环

1. 变量不能重复声明;

2. 块级作用域 { };(其他作用域还有全局,函数,eval)

3. 不存在变量提升;(变量提升:在声明之前使用变量)

4. 不影响作用域链。

 

const,常量 

1. 一定要赋初始值;

2. 一般常量使用大写;

3. 块级作用域;

4. 常量的值不能修改;

5. 对于数组和对象的元素修改,不算做对常量的修改,不会报错。

 

模版字符串【``】,相当于 C# 的 @"" 和 $""。

 

对象简化,ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。

let name = '字符串';
let change = function () {
    console.log('字符串');
}
const school = {
    name,
    change,
    //声明一个函数
    improve () {
        console.log('字符串');
    }
}

对象简化
对象简化

 

解构赋值,允许按照一定模式从数组和对象中提取值,对变量进行赋值。

const zhao = {
    name: '赵本山',
    age: '不详',
    xiaopin: function () {
        console.log("我可以演小品");
    }
};
let { name, age, xiaopin } = zhao;
解构赋值

 

箭头函数,ES6 允许使用箭头 => 定义函数

//普通写法
let fn = function (n) {
    return n * n;
}
//箭头函数写法
let fn1 = (n) => {
    return n * n;
}
//当形参有且只有一个的时候
let fn2 = n => {
    return n * n;
}
//当代码体只有一条语句的时候
let fn3 = n => n * n;

//使用案例1
setTimeout(() => {
    console.log("字符串");
}, 2000);

//使用案例2
const arr = [1, 6, 8, 5, 11, 34];
const result = arr.filter(item => item % 2 === 0);
console.log(result.join(','));
箭头函数

1. this 是静态的。this 始终指向函数声明时所在作用域下的 this 的值;(扩充:JavaScript call() 方法)

2. 不能作为构造函数实例化对象;

3. 不能使用 arguments 变量;

4. 箭头函数适合与 this 无关的回调,如定时器、数组的方法回调;

 不适合与 this 有关的回调。如事件回调、对象的方法。

arguments:实参对象,解决 js 函数不可以重载的问题。ES6 用 rest 参数【...args】代替使用)

(数组过滤:JavaScript Array filter() 方法)

 

扩展运算符,【...】

//1. 可以将数组转换为参数序列
function add (x, y) {
    return x + y;
}
const array0 = [4, 6];
console.log(add(...array0));

//2.可以复制数组
const array1 = ['E', 'G', 'M'];
const array2 = [...array1];
console.log(array2);

//3.可以合并数组
const array3 = ['A', 'B'];
const array4 = ['C', 'D'];
// 方式一(原来的方式)
const array5 = array3.concat(array4);
console.log(array5);
// 方式二
const array6 = [...array3, ...array4];
console.log(array6);

//在ES6中只针对数组,ES9中扩展到了对象,rest参数同理
const skill1 = {
    q: '天音波'
}
const skill2 = {
    w: '金钟罩'
}
const skill3 = {
    e: '天雷破'
}
const skill4 = {
    r: '猛龙摆尾'
}
const mangseng = { ...skill1, ...skill2, ...skill3, ...skill4 };
console.log(mangseng)
扩展运算符

 

Symbol,JS语言的第七种数据类型,表示独一无二的值

1. Symbol 值是唯一的,用来解决命名冲突问题

2. Symbol 值不能进行运算

//Symbol.prototype.description:获取 Symbol 字符串描述(ES10功能)
let s = Symbol('尚硅谷');
console.log(s.description);

// 数据类型速记: u are so nb
// u undefined
// s string symbol
// o object
// n null number
// b boolean
Symbol

 

迭代器 Iterator 是一种接口,任何数据结构只要部署了 Iterator 接口,就可以完成遍历操作。

原生具备 Iterator 接口的类型:Array、Arguments、Set、Map、String、TypedArray、NodeList…

ES6 创造了一种新的遍历命令 for...of 循环,和 for in 的区别:一个获取键值,一个获取键名。

//声明一个对象
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); //输出xiaoming xiaoning xiaotian knight
}

Iterator
Iterator
类似链表:

a) 创建一个指针对象,指向当前数据结构的起始位置

b) 第一次调用对象的next方法,指针自动指向数据结构的第一个成员

c) 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员

d) 每调用next方法返回一个包含value和 done属性的对象
工作原理

 

生成器,一个特殊的函数,ES6 提供的一种异步编程(文件操作、网络操作、数据库操作等带来的回调地狱)的解决方案。

//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'));
理解
//回调地狱
// 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();
}
实例:解决回调地狱
//模拟获取 用户数据、订单数据、商品数据(没懂)
function getUsers () {
    setTimeout(() => {
        let data = '用户数据';
        //调用 next 方法,并且将数据传入
        iterator.next(data);
    }, 1000)
}
function getOrders () {
    setTimeout(() => {
        let data = '订单数据';
        iterator.next(data);
    }, 1000)
}
function getGoods () {
    setTimeout(() => {
        let data = '商品数据';
        iterator.next(data);
    }, 1000)
}
function* gen () {
    let users = yield getUsers();
    let orders = yield getOrders();
    let goods = yield getGoods();
}
//调用生成器函数
let iterator = gen();
iterator.next();
应用

 

Promise,ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。

//创建promise对象
const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        //resolve('用户数据'); //正确时返回
        reject('出错啦');   //错误时返回
    }, 1000)
})

//调用then方法
p.then(value => {
    console.log(value);
}, reason => {
    console.warn(reason);
})
Promise
//1. 引入fs模块
const fs = require('fs');

//2. 调用方法读取文件(原来的方式)
// fs.readFile('./为学.md', (err, data) => {
//     //如果失败,则抛出错误
//     if (err) throw err;
//     //如果没有出错,则输出内容
//     console.log(data.toString());
// })

//3. 使用Promise封装
const p = new Promise(function (resolve, reject) {
    fs.readFile("./为学.mda", (err, data => {
        //判断如果失败
        if (err) reject(err);
        //如果成功
        resolve(data);
    }))
})

p.then(function (value) {
    console.log(value.toString());
}, function (reason) {
    console.log(reason);
});
简单应用:Promise 封装读取文件( 需用到Node.js的API )
//1. 引入fs模块
const fs = require('fs');

//2. 调用方法读取文件(原来的方式)
// fs.readFile('./为学.md', (err, data1) => {
//     fs.readFile('./插秧诗.md', (err, data2) => {
//         fs.readFile('./观书有感.md', (err, data3) => {
//             let result = data1 + '\r\n' + data2 + '\r\n' + data3;
//             console.log(result);
//         })
//     })
// })

//3. 使用Promise实现
const p = new Promise(function (resolve, reject) {
    fs.readFile("./为学.mda", (err, data) => {
        resolve(data);
    })
})

p.then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./插秧诗.mda", (err, data) => {
            resolve([value, data]);
        });
    })
}).then(value => {
    return new Promise((resolve, reject) => {
        fs.readFile("./观书有感.mda", (err, data) => {
            //压入
            value.push(data);
            resolve(value);
        });
    })
}).then(value => {
    console.log(value.join('\r\n'));
});
继续应用:Promise 读取多个文件(链式调用) 

  +   实例:Promise 封装 Ajax 请求

 

Set 集合,ES6 提供的新的数据结构,类似于数组,但成员的值都是唯一的。

.size 获取元素个数;.add 添加新的元素;.delete 删除元素;.has 检查元素是否存在;.clear 清空;

let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
//1. 数组去重
let result = [...new Set(arr)];
console.log(result); //[1, 2, 3, 4, 5]

//2. 交集
let arr2 = [4, 5, 6, 5, 6];
let result2 = result.filter(item => { //老方法
    let s2 = new Set(arr2);
    if (s2.has(item)) {
        return true;
    } else {
        return false;
    }
});
console.log(result2); //[4, 5]
let result3 = result.filter(item => new Set(arr2).has(item)); //新方法
console.log(result3); //[4, 5]

//3. 并集
let union = [...new Set([...arr, ...arr2])];
console.log(union); //[1, 2, 3, 4, 5, 6]

//4. 差集
let diff = result.filter(item => !(new Set(arr2).has(item)));
console.log(diff); //[1, 2, 3]
Set

 

Map,ES6 提供的数据结构,类似于对象,键值对集合。

let m = new Map();
m.set('name', '小王'); //添加元素
m.set('doing', function () {
    console.log("去吃饭!");
});
//键不限于字符串,各种类型的值(包括对象)都可以当做键。
let exam = { subject: "数学", source: 98 }
m.set(exam, ['帽子', 'T恤', '裤子'])

console.log("size:" + m.size); //size
console.log(m.get('name')); //获取
console.log(m.get(exam));
m.delete('doing'); //删除
for (let v of m) {
    console.log(v)
}
m.clear(); //清空
Map

 

Class 类,通过 class 关键字,可以定义类。

其实就是一个语法糖,让对象原型的写法更加清晰、更像面向对象编程的语法而已。

function Phone (brand, price) {
    this.brand = brand
    this.price = price
}
//添加方法
Phone.prototype.call = function () {
    console.log("我可以打电话!")
}
//通过构造函数实例化对象
let NOKIA = new Phone('诺基亚', 999)
NOKIA.call()
console.log(NOKIA)

// ES5 构造函数继承↓
function SmartPhone (brand, price, color, size) {
    Phone.call(this, brand, price)
    this.color = color
    this.size = size
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone
SmartPhone.prototype.construtor = SmartPhone
//声明子类的方法
SmartPhone.prototype.photo = function () {
    console.log("我可以拍照!")
}
let Realme = new SmartPhone('真我', 2499, '黑色', '5.5inch')
Realme.call()
Realme.photo()
console.log(Realme)
ES5 通过构造函数实现“类和继承”
class Phone {
    constructor(brand, price) {
        this.brand = brand
        this.price = price
    }
    call () {
        console.log("我可以打电话!")
    }
}
let Jinli = new Phone("金立", 288)
Jinli.call()
console.log(Jinli)
//类继承
class SmartPhone extends Phone {
    constructor(brand, price, color, size) {
        super(brand, price)
        this.color = color
        this.size = size
    }
    //重写
    call () {
        console.log("我可以视频电话!")
    }
    photo () {
        console.log("我可以拍照!")
    }
}
let Xiaomi = new SmartPhone("小米", 1999, "银色", '6.0inch')
Xiaomi.call()
Xiaomi.photo()
console.log(Xiaomi)
ES6 类和继承的实现
class Phone {
    get price () {
        console.log("价格属性被读取了")
        return 999
    }
    set price (newVal) {
        console.log(`价格属性被修改了,值为${newVal}`)
    }
}

let s = new Phone();
console.log(s.price) //输出:价格属性被读取了   999
s.price = 288 //输出:价格属性被修改了,值为288
get 和 set

   +  静态成员: 

 

ES6 的数值扩展

// Number.EPSILON 是JavaScript表示的最小精度
function equal (a, b) {
    if (Math.abs(a - b) < Number.EPSILON) { //Math.abs求差值的绝对值
        return true
    } else {
        return true
    }
}
console.log(0.1 + 0.2 === 0.3)
console.log(equal(0.1 + 0.2, 0.3))
// Number.isFinite 检测是否为有限数
console.log(Number.isFinite(100))
console.log(Number.isFinite(100 / 0))
console.log(Number.isFinite(Infinity))
// Number.isNaN 检测是否为NaN
console.log(Number.isNaN(123))
// Number.parseInt 字符串转整数
console.log(Number.parseInt('521love'))
console.log(Number.parseFloat('3.14派'))
// Number.isInteger 判断是否为整数
console.log(Number.isInteger(5))
console.log(Number.isInteger(2.5))
// Math.trunc 将小数部分抹掉
console.log(Math.trunc(3.5))
// Math.sign 判断是正数、负数还是零
console.log(Math.sign(100))
console.log(Math.sign(0))
console.log(Math.sign(-100))
数值扩展

 

ES6 的对象方法扩展:  

//判断两个值是否完全相等 
console.log(Object.is(120, 120))

let obj1 = { name: "zhangsan" }
let obj2 = { age: 18 }
//对象合并
console.log(Object.assign(obj1, obj2))

// Object.setPrototypeOf 设置原型对象
// Object.getPrototypeOf 获取原型对象
对象方法扩展

 

ES10 的字符串方法扩展

str.trimStart()、str.trimEnd()

 

模块化,将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

ES6 之前的模块化规范:CommonJS:NodeJS、Browserify;AMD:requireJS;CMD:seaJS。

优点:防止命名冲突、代码复用、高维护性。

模块化功能主要由两个命令组成:

  export 命令用于规定模块的对外接口

  import 命令用于输入其他模块提供的功能

//1. 通用的导入方式
// import * as m1 from "./m1.js"
// import * as m2 from "./m2.js"
// import * as m3 from "./m3.js"
//2. 解构赋值形式
// import { name, say } from "./m1.js"
// import { name as n, say } from "./m2.js"
// import { default as m3 } from "./m3.js"
//3. 简便形式   针对默认暴露
import m3 from "./m3.js"
console.log(m3)

// m1.js
// export let name = '肖红'
// export function say () {
//     console.log('hello~')
// }

// m2,js 统一暴露
// let name = '肖红'
// function say () {
//     console.log('hello~')
// }
// export { name, say }

// m3.js 默认暴露
export default {
    name: '肖红',
    say: function () {
        console.log('hello~')
    }
}
export import

或者使用入口文件形式:

//demo.html
<script src="./index.js" type="module"></script>

//index.js 入口文件
//模块引入
import * as m1 from './m1.js'
import * as m2 from './m2.js'
import * as m3 from './m3.js'
入口文件写法

考虑兼容性,使用 Babel

 

npm 包管理器

import $ from 'jquery' //const $ = require('jquery')
//修改背景颜色为粉色
$('body').css('background', 'pink')
结合 JQuery 包使用

 

async 函数和 await 表达式,可以让异步代码像同步代码一样

//1. async函数的返回值为promise对象
//2. promise对象的结果由async函数执行的返回值决定
async function fn () {
    return new Promise((resolve, reject) => {
        // resolve('成功的数据')
        reject('失败的错误')
    })
}
const result = fn()
result.then(value => {
    console.log(value)
}, reason => {
    console.warn(reason)
})
async 函数
//1. await必须写在async函数中
//2. await右侧的表达式一般为promise对象
//3. await返回的是promise成功的值
const p = new Promise((resolve, reject) => {
    reject('失败的错误')
})
async function main () {
    try {
        let result = await p;
        console.log(result)
    } catch (e) {
        console.log(e)
    }
}
main()
await 函数
const fs = require("fs");
function readWeiXue () {
    return new Promise((resolve, reject) => {
        fs.readFile("./为学.md", (err, data) => {
            if (err) reject(err);
            resolve(data);
        })
    })
}
function readChaYangShi () {
    return new Promise((resolve, reject) => {
        fs.readFile("./插秧诗.md", (err, data) => {
            if (err) reject(err);
            resolve(data);
        })
    })
}
function readGuanShu () {
    return new Promise((resolve, reject) => {
        fs.readFile("./观书.md", (err, data) => {
            if (err) reject(err);
            resolve(data);
        })
    })
}
async function main () {
    let weixue = await readWeiXue();
    let chayang = await readChaYangShi();
    let guanshu = await readGuanShu();
}
main();
结合 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/api/getTime").then(value => {
//     console.log(value)
// }, reason => {
//     console.warn(reason)
// })

//async 与 await 测试   axios
async function main () {
    //发送 AJAX 请求
    let result = await sendAjax("https://api.apiopen.top/api/getTime");
    console.log(result)
    // //再次测试
    let tianqi = await sendAjax("https://www.tianqiapi.com/api")
    console.log(tianqi)
}
main();
再结合 Ajax

 

私有属性, #

class Person {
    //公有属性
    name;
    //私有属性
    #age;
    constructor(name, age) {
        this.name = name;
        this.#age = age;
    }
    say () {
        console.log(`我叫${this.name},今年${this.#age}`)
    }
}
const p = new Person("肖红", 18);
console.log(p.name); //输出 肖红
console.log(p.age); //报错
p.say(); //输出 我叫肖红,今年18
私有属性

 

可选链操作符,?.

和 C# 的 ?. 相同,检查是否为 NULL

 

动态import

//静态导入,浪费资源
// import * as m1 from "./hello.js"

//点击按钮时,动态导入
const btn = document.getElementById('btn')
btn.onclick = function () {
    import('./hello.js').then(module => {
        module.hello();
    })
}

//hello.js
function hello () {
    alert('Hello')
}
动态导入

 

绝对全局对象,globalThis,相当于window

 

学习来源:https://www.bilibili.com/video/BV1uK411H7on?p=11&spm_id_from=pageDriver ,ES6之后仅挑重点记

posted @ 2021-12-20 22:06  kueizheng  阅读(35)  评论(0编辑  收藏  举报