ES6知识总结

感兴趣的朋友可以去我的语雀平台进行查看更多的知识。
https://www.yuque.com/ambition-bcpii/muziteng

1. ES6&7&8

1.1 简介

  1. 什么是ECMA

ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电

信和计算机标准,1994 年后该组织改名为Ecma国际

  1. 什么是ECMAScript

ECMAScript是由Ecma国际通过ECMA-262标准化的脚本程序设计语言。

image-20220912130857203

  1. 什么是ECMA-262

Ecma国际制定了许多标准,而ECMA-262只是其中的一个,所有标准列表查看:http://www.ecma-international.org/publications/standards/Standard.htm

ECMA-262历史版本查看网址: http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm

  • ES5 是 ECMAScript 第5版,2009年发布
  • ES6 是 ECMAScript 第6版,2015年发布,也叫 ES2015
  • 从 ES6 开始,每年发布一个版本,版本号比年份最后一位大 1
  1. 谁在维护ECMA-262

TC39(Technical Committee 39)是推进ECMAScript 发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果、谷歌、微软、

因特尔等)。TC39 定期召开会议,会议由会员公司的代表与特邀专家出席。

  1. 为什么要学习ES6
  • ES6 的版本变动内容最多,具有里程碑意义
  • ES6 加入许多新的语法特性,编程实现更简单、高效
  • ES6 是前端发展趋势,就业必备技能
  1. ES6兼容性

可查看兼容性:http://kangax.github.io/compat-table/es6/

1.2 ECMASript 6 新特征

1.2.1 let关键字

let关键字用来声明变量,使用let声明的变量有几个特点

  • 不允许重复声明
  • 块级作用域
  • 不存在变量提升
  • 不影响作用域链
// 声明变量
let a;
let b, c, d;
let e = 100;
let f = 521, g = 'iloveyou', h = [];

// 1. 变量不能重复声明
let str = "你好";
// let str = "Hello";    // 错误

// 2. 块级作用域  全局,函数,eval
// if else while for 等都是块级作用域
// {
//     let girl = "Cindy";
// }
// console.log(girl) // girl is not defined

// 3. 不存在变量提升
// console.log(song);
// var song = '恋爱达人';  // 用var可以变量提升

// 用let不可以
// console.log(test)
// let test = "test";  // Cannot access 'test' before initialization

// 4. 不影响作用域链
{
    let school = "你好"

    function fn() {
        console.log(school);
    }

    fn();
}
1.2.2 const关键字

const 关键字用来声明常量,const 声明有以下特点

  • 声明必须赋初始值
  • 标识符一般为大写
  • 不允许重复声明
  • 值不允许修改
  • 块级作用域

注意:对象属性修改和数组元素变化不会出发 const 错误 应用场景:声明对象类型使用 const,非对象类型声明选择 let

const arr = ['UZI', "LetMe", "ClearLove7"]
arr.push("Mekio");
const obj = {
    name: "Teng",
    age: 20,
};
obj.age = 18;   // 不会报错
1.2.3 变量的解构赋值
/**
 * ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为 解构赋值
 */
// 数组的解构赋值
const arr = ['red', 'green', 'blue'];
let [r, g, b] = arr;
console.log(r, g, b);   // red green blue
// 对象的解构赋值
const obj = {
    name: "Teng",
    age: 20,
    sayHi() {
        console.log("Hi");
    },
    sayBye() {
        console.log("Bye");
    }
}
let {name, age, sayHi} = obj;
console.log(name, age)  // Teng 20
sayHi();    // Hi
let {sayBye} = obj;
sayBye(); // Bye

应用场景:频繁使用对象方法、数组元素,就可以使用解构赋值形式

1.2.4 模板字符串

模板字符串(template string)是增强版的字符串,用反引号 ` 标识,特点

  • 字符串中可以出现换行符
  • 可以使用 ${xxx} 形式输出变量,近似 EL 表达式

应用场景:当遇到字符串与变量拼接的情况使用模板字符串

let name = "Teng"
console.log(`hello, ${name}`);

let ul = `<ul>
                <li>apple</li>
                <li>banana</li>
                <li>peach</li>
               </ul>`
1.2.5 简化对象写法

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

应用场景:对象简写形式简化了代码,所以以后用简写就对了

{
    let name = "Teng";
    let age = 20;
    let sayHi = function () {
        console.log("Hi")
    }
    }

// 创建对象 因属性、方法的 k v 同名,可以简化
const obj = {
    name: "Teng",
    age: 20,
    sayHi() {
        console.log("Hi")
    }
};
let {name, age, sayHi} = obj;
console.log(name, age);
sayHi();
1.2.6 箭头函数

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

let fn = (param1, param2,, paramN) => {
    // 函数体
    return expression;
}

注意

  • 如果形参只有一个,小括号可以省略
  • 如果函数体只有一条语句,花括号可以省略,函数的返回值为该条语句的执行结果,如果是 return 语句,return 必须省略
  • 箭头函数 this 是静态的,始终指向声明时所在作用域下 this 的值
  • 箭头函数不能作为构造函数实例化
  • 不能使用 arguments
let fn1 = function () {
}
let fn2 = (a, b) => {
    return a + b;
}
// 调用函数
// console.log(fn2(1, 2))

// 1. this是静态的 this始终指向函数声明时所在作用域下的this的值
const obj = {
    a: 10,
    getA() {
        let fn3 = () => {
            console.log(this);  // obj 这个对象
            console.log(this.a);    // 10
        }
        fn3();
    }
}
obj.getA()

function getName() {
    console.log(this.name);
}

let getName2 = () => {
    console.log(this.name);
}
// 设置window对象的name属性
window.name = "Teng"
const school = {
    name: "MuZi"
}
// 直接调用
//getName()   // Teng
//getName2()  // Teng

// call方法调用
//getName.call(school);   // MuZi
//getName2.call(school);  // Teng


// 2. 不能作为构造函数实例化对象
// let Person = (name, age) => {
//     this.name = name;
//     this.age = age;
// }
// let me = new Person("Teng", 20);
// console.log(me) // Person is not a constructor

// 3. 不能使用arguments变量
// let f = () => {
//     console.log(arguments); // arguments is not defined
// }
// f(1, 2, 3);
1.2.7 函数参数默认值设定

ES6 允许给函数参数设置默认值,当调用函数时不给实参,则使用参数默认值

具有默认值的形参,一般要靠后。

let add = (x, y, z=3) => x + y + z;
console.log(add(1,2));	// 6

可与解构赋值结合

function connect({host = '127.0.0.1', username, password, port}) {
    console.log(host)
    console.log(username)
    console.log(password)
    console.log(port)
}

connect({
    // host: "www.baidu.com",
    username: "root",
    password: "root",
    port: 3306
})
1.2.8 rest 参数

ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments,作用与 arguments 类似,将接收的参数序列转换为一个数组对象

(arguments 是伪数组)

语法格式:fn(a, b, ...args),写在参数列表最后面

应用场景:rest 参数非常适合不定个数参数函数的场景

let fn = (a, b, ...args) => {
    console.log(a);
    console.log(b);
    console.log(args);
}
fn(1, 2, 3, 4, 5);
// 1
// 2
// (3) [3,4,5]
1.2.9 spread 扩展运算符

扩展运算符spread也是三个点...,它好比 rest 参数的逆运算,将一个数组、伪数组转为用逗号分隔的参数序列,对数组进行解包,扩

展运算符也可以将对象解包 ,可用在调用函数时,传递的实参,将一个数组转换为参数序列(与rest参数的区别,一个用在形参,一个实

参)

展开数组

function fn(a, b, c) {
    console.log(arguments)
    console.log(a + b + c)
}
let arr = ['red', 'green', 'blue'];
fn(...arr);
// Arguments(3) {'0': 'red', '1': 'green', '2': 'blue'}
// redgreenblue

案例:数组合并

let A = [1, 2, 3];
let B = [4, 5, 6];
let C = [...A, ...B];
console.log(C); // [1,2,3,4,5,6]

案例:对象合并

let obj1 = {
    a: 123
}
let obj2 = {
    b: 456
}
let obj3 = {
    c: 789
}
let obj = {...obj1, ...obj2, ...obj3};
console.log(obj)    // {a:123,b:456,c:789}
1.2.10 Promise

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

一个Promise必然处于以下几种状态之一

  • 待定pending:初始状态,既没有被兑现,也没有被拒绝
  • 已兑现fulfilled:意味着操作成功完成
  • 已拒绝rejected:意味着操作失败

Promise的使用

  • Promise构造函数new Promise((resolve, reject) => {})
  • Promise.prototype.then()方法
  • Promise.prototype.catch()方法
let p = new Promise((resolve, reject) => {
    // 使用setTimeout模拟请求数据库
    setTimeout(() => {
        let isRight = true; // 这个异步请求数据库数据操作是否正确返回数据
        if (isRight) {
            let data = '数据库中的数据'
            resolve(data);  // 设置 Promise 对象的状态为操作成功
        } else {
            let err = '数据读取失败';
            reject(err);    // 设置 Promise 对象的状态未操作失败
        }
    }, 2000)
})
p.then(function (value) {
    console.log(value)
}, function (reason) {
    console.error(reason);
})

Promise封装读取文件

// 使用node.js 的 fs 读取文件模块
const fs = require('fs');

const p = new Promise((resolve, reject) => {
    fs.readFile('./aaa.txt', (err, data) => {
        if (err) reject(err);
        resolve(data);
    })
})
p.then((value) => {
    console.log(value.toString())
}, reason => {
    console.log("读取失败")
})

Promise 封装 Ajax 请求

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((value) => {
    console.log(value)
}, (reason) => {
    console.log(reason)
})

Promise.prototype.then 方法

Promise.prototype.then方法返回的结果依然是Promise对象,对象状态由回调函数的执行结果决定

具体情况如下

  • then方法未写返回值,则then方法返回的对象的状态值为成功fulfilled,返回结果值为undefined
const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        // resolve('用户数据')
        reject("出错了")
    }, 1000);
})
// 未设定返回值
const res = p.then((value) => {
    console.log(value);
}, (reason) => {
    console.log(reason)
})
// 打印then方法的返回值
console.log(res)

image-20220920085609311

  • 如果回调函数中返回的结果是非Promise类型的属性,则then方法返回的对象,其状态为成功fulfilled,返回结果值取决于

    then方法所执行的是哪个函数(resolvereject

const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        // resolve('用户数据')
        reject("出错了")
    }, 1000);
})
// 返回的非Promise对象
const res = p.then((value) => {
    console.log(value)
    return "成功了"
}, (reason) => {
    console.warn(reason)
    return "出错了"
})
// 打印then方法的返回值
console.log(res)

image-20220920085857306

  • 如果回调函数中返回的结果是Promise类型return new Promise(),则then方法返回的Promise对象状态与该返回结果的状态相

    同,返回值也相同

const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('用户数据')
        // reject('出错了');
    }, 1000);
})
const res = p.then((value) => {
    console.log(value);
    // 返回 Promise 对象
    return new Promise((resolve, reject) => {
        resolve('(1)成功了!!!');
        // reject('(1)出错了!!!')
    })
}, (reason) => {
    console.warn(reason);
    return new Promise((resolve, reject) => {
        // resolve('(2)成功了!!!');
        reject('(2)出错了!!!')
    })
})
// 打印 then 方法的返回值
console.log(res);

image-20220920085951875

  • 如果回调函数中返回的结果是throw语句抛出异常,则then方法的对象的状态值为rejected,返回结果值为throw抛出的字面量

    或者Error对象

const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('用户数据');
    }, 1000);
});
const res = p.then((value) => {
    console.log(value);
    return new Promise((resolve, reject) => {
        throw new Error('错误了!!');
    })
});
// 打印结果
console.log(res);

image-20220920090026465

链式调用

Promise.prototype.then方法返回的结果还是Promise对象,这意味着我们可以继续在该结果上使用then方法,也就是链式调用。

const p = new Promise(resolve=>{}, reject=>{});
p.then(value=>{}, reason=>{})
.then(value=>{}, reason=>{})
.then(value=>{}, reason=>{})
...

Promise.prototype.catch

catch()方法返回一个Promise,并且处理拒绝的情况,它的行为与调用Promise.prototype.then(undefined, onRejected)相同

obj.catch(onRejected);
等同于
obj.then(undefined, onRejected);

语法

p.catch(onRejected);

p.catch(function(reason) {
   // 拒绝
});

举例

var p1 = new Promise(function (resolve, reject) {
    resolve('Success');
});

p1.then(function (value) {
    console.log(value); // "Success!"
    throw 'oh, no!';
}).catch(function (e) {
    console.log(e); // "oh, no!"
}).then(function () {
    console.log('有 catch 捕获异常,所以这句输出');
}, function () {
    console.log('没有 catch 捕获异常,这句将不会输出');
});

// 结果
Success
oh, no!
有 catch 捕获异常,所以这句输出
1.2.11 Set

ES6 提供了新的数据结构Set(集合),它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用扩展运算符 …

和 for…of 进行遍历。

属性和方法

  • st.size:返回集合个数
  • st.add(item):往集合中添加一个新元素 item,返回当前集合
  • st.delete(item):删除集合中的元素,返回 boolean 值
  • st.has(item):检测集合中是否包含某个元素,返回 boolean 值
  • st.clear():清空集合
  • 集合转为数组:[…st]
  • 合并两个集合:[…st1, …st2]
// 数组去重
let arr1 = [1, 2, 2, 3, 3, 3, 4, , 1, 2];
let res1 = [...new Set(arr1)]
console.log(res1) // [1,2,3,4]
// 数组求交集
let arr2_1 = [1, 2, 2, 3, 4, 5];
let arr2_2 = [3, 6, 6, 7, 1, 4]
let res2 = arr2_1.filter(arr => new Set(arr2_2).has(arr));
console.log(res2) // [1,3,4]
// 数组求并集
let arr3_1 = [1, 2, 2, 3, 4, 5];
let arr3_2 = [3, 6, 6, 7, 1, 4];
let res3 = [...new Set([...arr3_1, ...arr3_2])];
console.log(res3)   // [1,2,3,4,5,6,7]
// 求差集
let arr4_1 = [1, 2, 2, 3, 4, 5];
let arr4_2 = [3, 6, 6, 7, 1, 4];
let res4 = [...new Set(arr4_1)].filter(v => !(new Set(arr4_2).has(v)));
console.log(res4)   // [2,5]
1.2.12 Map

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是 “键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作

键。Map 也实现了 iterator 接口,所以可以使用扩展运算符 … 和 for…of 进行遍历

Map 的属性和方法:(k 为键,v为值)

  • size:返回 Map 的元素(键值对)个数
  • set(k, v):增加一个键值对,返回当前 Map
  • get(k):返回键值对的键值
  • has():检测 Map 中是否包含某个元素
  • clear():清空集合,返回 undefined
let map = new Map();

map.set('name', 'Teng');
map.set('change', function () {
    console.log("Change");
})
let key = {
    school: "CQJTU"
}
map.set(key, ['深圳', '重庆']);
console.log(map.size)
map.delete('name')
console.log(map.get('change'))
console.log(map.get(key))
for (const element of map) {
    console.log(element)
}
map.clear()
1.2.13 模块化

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

模块化的优势有以下几点

  • 防止命名冲突
  • 代码复用
  • 高维护性

语法

模块功能主要由两个命令构成

  • export命令用于规定模块的对外接口
  • import命令用于输入其他模块提供的功能

模块导出数据语法

// 1. 分别暴露
export let school = 'CQJTU';

export function teach() {
    console.log("哈哈哈哈哈哈哈");
}

// 2. 统一暴露
let school = 'CQJTU';
function findJob() {
    console.log("你好");
}

export {school, findJob};

// 3. 默认暴露
export default {
    school: 'CQJTU',
    change() {
        console.log("Change");
    }
}

模块导入数据语法

// 1. 通用导入方式
import * as m1 from './js/m1.js';
import * as m2 from './js/m2.js';
import * as m3 from './js/m3.js';

m3.default.change()

// 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";

1.3 ECMASript 7 新特性

1.3.1 Array.prototype.includes

includes 方法用来检测数组中是否包含某个元素,返回布尔类型值

const arr = [1, 2, 3];
console.log(arr.includes(1)) // true
1.3.2 指数运算符

在 ES7 中引入指数运算符 **,用来实现幂运算,功能与 Math.pow(a, b) 结果相同

// includes   indexOf也可以判断
const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];

//判断
console.log(mingzhu.includes('西游记'));    // true
console.log(mingzhu.includes('金瓶梅'));

// **
console.log(2 ** 10);	// 1024
console.log(Math.pow(2, 10));

1.4 ECMAScript 8 新特性

1.4.1 async 和 await

asyncawait两种语法结合可以让异步代码像同步代码一样(看起来是同步的,实质上是异步的)

先从字面意思理解,async意为异步,可以用于声明一个函数前,该函数是异步的。await意为等待,即等待一个异步方法完成。

async

asyncfunction变为成为async函数

  • async内部可以使用await,也可以不使用,因此执行这个函数时,可以使用thencatch方法
  • async函数的返回值是一个Promise对象
  • Promise对象的结果由async函数执行的返回值决定
async function funcName() {
    //statements 
}
  • 函数体不return 返回值,则async函数返回值为一个成功fulfilledPromise对象,值为undefined
let a = async function() {}
let res = a()
console.log(res) // Promise{<fullfilled>: undefined}
  • return结果不是一个Promise,则async函数返回值为一个成功fulfilledPromise对象,状态值为这个内部返回值
let a = async function () {
  return 'hello'
}
let res = a()
console.log(res) // Promise{<fullfilled>: 'hello'}
  • 内部抛出错误,则async函数返回值为一个失败rejectPromise对象
let a = async function foo() {
  throw new Error('出错了')
}
a().catch(reason => {
  console.log(reason)
})
  • 若函数内部返回值是一个Promise对象,则async函数返回值的状态取决于这个Promise对象是resolve还是reject
let a = async function () {
  return new Promise((resolve, reject) => {
    resolve("成功")
  })
}
a().then(value => {
  console.log(value)
})

await

await相当于一个运算符,右边接一个值。一般为一个Promise对象,也可以是一个非Promise类型。

  • 当右接一个非promise类型,await表达式返回的值就是这个值;当右接一个promise对象,则await表达式会阻塞后面的代码,

    等待当前promise对象resolve 的值

综合asyncawait而言

  • await必须写在async函数中
  • await右侧的表达式一般为promise对象
  • await返回的是promise成功的值
  • awaitpromise失败了就会抛出异常,需要使用try-catch捕获处理
  • Promise使用链式调用解决了传统方式回调地狱的问题,而async-await又进一步优化了代码的可读性
// 创建 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();	// '失败'
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ambition0823

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值