感兴趣的朋友可以去我的语雀平台进行查看更多的知识。
https://www.yuque.com/ambition-bcpii/muziteng
ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电
信和计算机标准,1994 年后该组织改名为Ecma国际
ECMAScript是由Ecma国际通过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
TC39(Technical Committee 39)是推进ECMAScript 发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果、谷歌、微软、
因特尔等)。TC39 定期召开会议,会议由会员公司的代表与特邀专家出席。
可查看兼容性:http://kangax.github.io/compat-table/es6/
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();
}
const 关键字用来声明常量,const 声明有以下特点
注意:对象属性修改和数组元素变化不会出发 const 错误 应用场景:声明对象类型使用 const,非对象类型声明选择 let
const arr = ['UZI', "LetMe", "ClearLove7"]
arr.push("Mekio");
const obj = {
name: "Teng",
age: 20,
};
obj.age = 18; // 不会报错
/**
* 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
应用场景:频繁使用对象方法、数组元素,就可以使用解构赋值形式
模板字符串(template string)是增强版的字符串,用反引号 ` 标识,特点
${xxx}
形式输出变量,近似 EL 表达式应用场景:当遇到字符串与变量拼接的情况使用模板字符串
let name = "Teng"
console.log(`hello, ${name}`);
let ul = `
- apple
- banana
- peach
`
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();
ES6 允许使用箭头=>定义函数
let fn = (param1, param2, …, paramN) => {
// 函数体
return expression;
}
注意
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);
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
})
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]
扩展运算符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}
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)
如果回调函数中返回的结果是非Promise
类型的属性,则then
方法返回的对象,其状态为成功fulfilled
,返回结果值取决于
then
方法所执行的是哪个函数(resolve
或reject
)
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)
如果回调函数中返回的结果是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);
如果回调函数中返回的结果是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);
链式调用
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 捕获异常,所以这句输出
ES6 提供了新的数据结构Set(集合),它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用扩展运算符 …
和 for…of 进行遍历。
属性和方法
// 数组去重
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]
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是 “键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作
键。Map 也实现了 iterator 接口,所以可以使用扩展运算符 … 和 for…of 进行遍历
Map 的属性和方法:(k 为键,v为值)
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()
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来
模块化的优势有以下几点
语法
模块功能主要由两个命令构成
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";
includes
方法用来检测数组中是否包含某个元素,返回布尔类型值
const arr = [1, 2, 3];
console.log(arr.includes(1)) // true
在 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));
async
和await
两种语法结合可以让异步代码像同步代码一样(看起来是同步的,实质上是异步的)
先从字面意思理解,async
意为异步,可以用于声明一个函数前,该函数是异步的。await
意为等待,即等待一个异步方法完成。
async
async
将function
变为成为async
函数
async
内部可以使用await
,也可以不使用,因此执行这个函数时,可以使用then
和catch
方法async
函数的返回值是一个Promise
对象Promise
对象的结果由async
函数执行的返回值决定async function funcName() {
//statements
}
return
返回值,则async
函数返回值为一个成功fulfilled
的Promise
对象,值为undefined
let a = async function() {}
let res = a()
console.log(res) // Promise{: undefined}
return
结果不是一个Promise
,则async
函数返回值为一个成功fulfilled
的Promise
对象,状态值为这个内部返回值let a = async function () {
return 'hello'
}
let res = a()
console.log(res) // Promise{: 'hello'}
async
函数返回值为一个失败reject
的Promise
对象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
的值
综合async
和await
而言
await
必须写在async
函数中await
右侧的表达式一般为promise
对象await
返回的是promise
成功的值await
的promise
失败了就会抛出异常,需要使用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(); // '失败'