ECMAScript
ECMAScrit 简介
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 历史
-
ECMA
(European Computer Manufacturers Association
)中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信第 1 版 1997年 制定了语言的基本语法 第 2 版 1998年 较小改动 第 3 版 1999年 引入正则、异常处理、格式化输出等。IE 开始支持 第 4 版 2007年 过于激进、未发布 第 5 版 2009年 严格模式、 JSON
、扩展对象、数组、原型、字符串、日期方法第 6 版 2015年 模块化、面向对象语法、 Promise
、箭头函数、let
、const
、数组解构赋值等等第 7 版 2016年 幂运算符、数组扩展 第 8 版 2017年 Async/await
、字符串扩展第 9 版 2018年 对象解构赋值、正则扩展 第 10 版 2019年 扩展对象、数组方法 ES.next
动态指向下一个版本 -
注:从
ES6
开始,每年发布一个版本,版本号比年份最后一位大 1
为什么要学习ES6
ES6
的版本变动内容最多,具有里程碑意义ES6
加入许多新的语法特性,编程实现更简单、高效ES6
是前端发展趋势,就业必备技能
let
关键字
-
let
关键字用来声明变量,使用let
声明的变量有几个特点:-
不允许重复声明
<!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>Document</title> </head> <body></body> <script> // 不允许重复声明 let a = 10; // let a = "abc"; // 报错 console.log(a); // 10 </script> </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>Document</title> </head> <body></body> <script> // 块儿级作用域 for if // var 是没有块级作用域的 for (var i = 0; i < 10; i++) {} console.log(i); // 10 if (true) { var f = "abc"; } console.log(f); // abc // let 是有块级作用域的 for (let index = 0; index < 10; index++) {} // console.log(index); // 报错 index is not defined if (true) { let n = false; } // console.log(n); // 报错 n is not defined </script> </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>Document</title> </head> <body></body> <script> // var 的变量提升 console.log(a); //undefined var a = 10; // let 不存在变量提升 // console.log(n); // 报错 Cannot access 'n' before initialization let n = false; </script> </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>Document</title> </head> <body></body> <script> // var 不影响作用域链 function fn() { var a = 10; function fn1() { var b = 10; console.log(a + b); // 20 } function fn2() { var c = 20; // console.log(a + b + c); // 报错 b is not defined } fn1(); fn2(); } // fn(); // let 也不影响作用域链 function foo() { let a = 10; function fn1() { let b = 10; console.log(a + b); // 20 } function fn2() { let c = 20; // console.log(a + b + c); // 报错 b is not defined } fn1(); fn2(); } foo(); </script> </html>
-
-
应用场景:以后声明变量使用
let
就对了
const
关键字
-
const
关键字用来声明常量,const
声明有以下特点-
声明必须赋初始值
<!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>Document</title> </head> <body></body> <script> // const a; // 报错 Missing initializer in const declaration const a = 10; console.log(a); // 10 </script> </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>Document</title> </head> <body></body> <script> const a = false; // const a = 10; // 报错 Identifier 'a' has already been declared console.log(a); // false </script> </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>Document</title> </head> <body></body> <script> const a = false; // a = 10; // 报错 Assignment to constant variable. console.log(a); </script> </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>Document</title> </head> <body></body> <script> for (let i = 0; i < 10; i++) { const a = 20; var b = 10; // var 定义的变量在for循环中是没有块级作用域的 } // console.log(a); // 报错 a is not defined console.log(b); // 10 if (true) { const foo = false; } console.log(foo); // 报错 foo is not defined // const 在 for 和 if 都是具有块级作用域的 </script> </html>
-
-
注意: 对象属性修改和数组元素变化不会触发
const
错误
<!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>Document</title>
</head>
<body></body>
<script>
// 对象属性改变不会触发 const 错误
const obj = {
name: "张三",
age: 10,
sayHi: function () {
console.log(this.name + ":hi");
},
};
obj.name = "王五";
obj.sayHi(); // 王五:hi
obj.weight = "50";
console.log(obj); // 也不会报错
// 数组元素改变也不会触发 const 错误
const arr = [];
arr.push(10, 20, 30);
console.log(arr); // [10, 20, 30]
</script>
</html>
- 应用场景:声明对象类型使用
const
,非对象类型声明选择let
变量的解构赋值
-
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>Document</title> </head> <body></body> <script> const arr = ["张学友", "刘德华", "黎明", "郭富城"]; // 数组的解构赋值 => 根据数组的下标有顺序的进行赋值 let [zhang, liu, li, guo] = arr; console.log(zhang, liu, li, guo); // 张学友 刘德华 黎明 郭富城 </script> </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>Document</title> </head> <body></body> <script> // 对象的解构赋值 const lin = { name: "林志颖", tags: ["车手", "歌手", "小旋风", "演员"], sayHi: function () { console.log("唱歌"); }, }; // 对象的解构赋值是将对象中的各个属性取出来 变量名称必须与属性名称一致 const { name, tags, sayHi } = lin; console.log(name, tags, sayHi); // 林志颖 console.log(tags); // ['车手', '歌手', '小旋风', '演员'] console.log(sayHi); // ƒ () {console.log("唱歌");} sayHi(); // 唱歌 </script> </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>Document</title> </head> <body></body> <script> let wangfei = { name: "王菲", age: 18, songs: ["红豆", "流年", "暧昧", "传奇"], history: [{ name: "窦唯" }, { name: "李亚鹏" }, { name: "谢霆锋" }], }; const { name, age, // 数组的解构 => string,string,string,string songs: [one, two, three, four], // 数组的解构 => obj,obj,obj,obj history: [first, second, third], } = wangfei; console.log(name); // 王菲 console.log(age); // 18 console.log(one); // 红豆 console.log(first); // {name: '窦唯'} </script> </html>
-
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
模板字符串
-
模板字符串(
template string
)是增强版的字符串,用反引号(`)标识,特点:- 字符串中可以出现换行符
- 可以使用
${xxx}
形式输出变量
<!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>Document</title> </head> <body> <ul></ul> </body> <script> const books = ["JavaScript", "Vue", "React", "Es6"]; let str = ""; for (let i = 0; i < books.length; i++) { str += ` <li>${books[i]}</li> `; } // 获取 DOM 对象 document.querySelector("ul").innerHTML = str; </script> </html>
-
注意:当遇到字符串与变量拼接的情况使用模板字符串
简化对象写法
-
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>Document</title> </head> <body></body> <script> let name = "张三"; let age = 20; const sayHi = function () { console.log("hi"); }; // 原始写法 let obj = { // key:value 的写法 name: name, age: age, sayHi: sayHi, }; console.log(obj); // {name: '张三', age: 20, sayHi: ƒ} // 简化写法 let newObj = { // 当key与value一致时,就可以只写一个就可以了 name, age, sayHi, }; console.log(newObj); // {name: '张三', age: 20, sayHi: ƒ} const person = { sayHi: function () { console.log(11); }, }; // 对象中的方法后 :function 是可以省略的 const newPerson = { sayHi() { console.log(11); }, }; </script> </html>
-
注意:对象简写形式简化了代码,所以以后用简写就对了
箭头函数
-
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>Document</title> </head> <body></body> <script> // => 代替 function() const oldFn = function () { console.log("oldFn"); // oldFn }; oldFn(); const fn = () => { console.log("fn"); // fn }; fn(); </script> </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>Document</title> </head> <body></body> <script> // 箭头函数没有参数的情况 const a = () => { console.log("没有参数的箭头函数"); }; a(); // 箭头函数只有一个参数的情况(参数的括号可以省略) const b = (a) => { console.log("只有一个参数的箭头函数"); }; b(); // 箭头函数的参数有多个时,不可以省略 const c = (a, b) => { console.log(a, b); // 10 20 }; c(10, 20); </script> </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>Document</title> </head> <body></body> <script> // 代码函数只有一行,方法体的大括号可以省略 const fo = () => console.log("代码函数只有一行,方法体的大括号可以省略"); fo(); // 代码行数只有一行,有返回值的情况,方法体的大括号和 return 可以省略的 const sum = (a, b) => a + b; console.log(sum(10, 20)); </script> </html>
-
箭头函数
this
指向声明时所在作用域下this
的值<!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>Document</title> </head> <body></body> <script> const obj = { name: "张三", age: 20, sayHi() { // this const _this = this; setTimeout(function () { // 计时器里面的 this 永远指向于 window console.log(`你好,${_this.name}`); }, 2000); }, }; obj.sayHi(); const obj2 = { name: "李四", age: 18, sayHi() { setTimeout(() => { // 箭头函数没有 this 指向,指向最近的 this // 这里受箭头函数的影响 this 指向 obj2 console.log(`你好,${this.name}`); }, 2000); }, }; obj2.sayHi(); </script> </html>
-
箭头函数不能作为构造函数实例化
-
不能使用
arguments
<!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>Document</title> </head> <body></body> <script> const fo = function () { console.log(arguments); }; fo(1, 2, 3, 4); const foo = () => { // console.log(arguments); // 报错 arguments is not defined }; foo(1, 2, 3); </script> </html>
-
-
注意:箭头函数不会更改
this
指向,用来指定回调函数会非常合适
rest
参数
-
ES6
引入rest
参数,用于获取函数的实参,用来代替arguments
<!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>Document</title> </head> <body></body> <script> const bar = function () { console.log(arguments instanceof Array); // false }; bar(10, 20, 30, 40, 50, 60); // 箭头函数 rest 参数 // 使用 ... 将剩余没有接收的参数放在数组中 const foo = (...args) => { console.log(args instanceof Array); // true }; foo(10, 20, 30, 40, 50, 60); const fn = (a, b, ...args) => { console.log(a, b, args); }; fn(10, 20, 30, 40, 50, 60); </script> </html>
-
注意:
rest
参数非常适合不定个数参数函数的场景
spread
扩展运算符
-
扩展运算符(
spread
)也是三个点(...
)。它好比rest
参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包<!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>Document</title> </head> <body></body> <script> // 展开数组 let tfboys = ["德玛西亚之力", "德玛西亚之翼", "德玛西亚皇子"]; function fn() { console.log(arguments); } fn(...tfboys); // 展开对象 let skillOne = { q: "致命打击" }; let skillTwo = { w: "勇气" }; let skillThree = { e: "审判" }; let skillFour = { r: "德玛西亚正义" }; const gailun = { ...skillOne, ...skillTwo, ...skillThree, ...skillFour }; console.log(gailun); // 数组的合并 const a = [1, 2, 3, 4]; const b = [5, 6, 7, 8]; const c = a.concat(b); console.log(c); // [1, 2, 3, 4, 5, 6, 7, 8] const d = a.push(...b); console.log(d); // 8 // 对象的合并 const p1 = { name: "李四", age: 18, }; const p2 = { ...p1, age: 30 }; // 在合并对象的时候 重复的属性会以最后一个出现的为准 console.log(p2); </script> </html>
迭代器
-
遍历器(
Iterator
)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。 -
ES6
创造了一种新的遍历命令for...of
循环,Iterator
接口主要供for...of
消费 -
原生具备
iterator
接口的数据(可用for of
遍历)Array
Arguments
Set
Map
String
NodeList
(DOM
节点)
-
工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的
next
方法,指针自动指向数据结构的第一个成员 - 接下来不断调用
next
方法,指针一直往后移动,直到指向最后一个成员 - 每调用
next
方法返回一个包含value
和done
属性的对象 - 注: 需要自定义遍历数据的时候,要想到迭代器
<!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>Document</title> </head> <body> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> <div>7</div> <div>8</div> <div>9</div> <div>10</div> </body> <script> // const divs = document.querySelectorAll("div"); // 获取到的 HTMLCollection 集合,没有办法 forEach const divs = document.getElementsByTagName("div"); // divs.forEach((item) => { // console.log(item); // 报错 divs.forEach is not a function // }); for (const item of divs) { console.log(item); // 这个是可以遍历的 } const objArr = [ { name: "Vuejs", price: 18, }, { name: "React", price: 10, }, { name: "Angular", price: 28, }, ]; for (const item of objArr) { console.log(item); } </script> </html>
Promise
-
Promise
是ES6
引入的异步编程的新解决方案 -
语法上
Promise
是一个构造函数, 用来封装异步操作并可以获取其成功或失败的结果。<!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>Document</title> </head> <body></body> <script> // 创建Promise的对象 // 在创建Promise对象的时候,需要传入一个回调函数, // 这个回调函数会产生两个参数 // 这两个参数是两个函数 resolve() 表示成功 reject() 失败 const p = new Promise(function (resolve, reject) { setTimeout(() => { let a = 10; if (a == 10) { // 表示成功 resolve(++a); } else { // 表示失败 a = 20; reject(a); } }, 2000); }); const p2 = new Promise((resolve, reject) => { // then表示成功 // cath表示失败 p.then((a) => { console.log(a); // 11 if (a == 11) { resolve(++a); } else { reject(a); } }).catch((error) => { console.log(error); }); }); // p2.then(a=>{ // console.log(a); // }) // p2.catch(error => { // console.log(error); // }) </script> </html>
-
Promise
构造函数:Promise (excutor) {}
-
Promise.prototype.then
方法 -
Promise.prototype.catch
方法 -
Promise.prototype.all
Promise
封装Ajax
<!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>Document</title>
</head>
<body></body>
<script>
let xhr;
// 创建XMLHttpRequest对象
if (XmlHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject("Microsoft.XML");
}
// 监听状态
xhr.onreadystatechange = () => {
// post 201
// get 200
if ((xhr.readyState == 4) & (xhr.status == 200) || xhr.status == 201) {
// 处理操作
}
};
// 开启连接
xhr.open("get", "xxxx", true);
xhr.send();
</script>
</html>
function $http(params) {
const { method, url, body, header } = params;
return new Promise((resolve, reject) => {
let xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
const { code, data } = JSON.parse(xhr.responseText);
resolve(data);
}
};
xhr.open(method, url);
try {
for (const key in header) {
xhr.setRequestHeader(key, header[key]);
}
} catch (error) {
console.log(error);
}
xhr.send(JSON.stringify(body));
});
}
Set
-
ES6
提供了新的数据结构Set
(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator
接口,所以可以使用『扩展运算符』
和『for…of…』
进行遍历,集合的属性和方法:<!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>Document</title> </head> <body></body> <script src="./http.js"></script> <script> let s1 = new Set(); console.log(s1); // 成员的值都是唯一的 所以可以做数组的去重 let s2 = new Set([22, 2, 22, 34, 34, 22, 5]); // 得到一个去重的对象 console.log(s2); // {22, 2, 34, 5} let newArr = [...s2]; console.log(newArr); // [22, 2, 34, 5] </script> </html>
-
size
返回集合的元素个数 -
add
增加一个新元素,返回当前集合 -
delete
删除元素,返回boolean
值 -
has
检测集合中是否包含某个元素,返回boolean
值 -
clear
清空集合,返回undefined
<!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>Document</title> </head> <body></body> <script src="./http.js"></script> <script> // size 返回集合的元素个数 let s2 = new Set([10, 20, 20, 30, 40, 30]); console.log("size:" + s2.size); // size:4 // add 增加一个新元素,返回当前集合 console.log(s2.add(5)); // {10, 20, 30, 40, 5} // delete 删除元素,返回 boolean 值 // .delete(某一个元素) console.log(s2.delete(20)); // true console.log(s2); // {10, 30, 40, 5} // has 检测集合中是否包含某个元素,返回 boolean 值 console.log(s2.has(10)); // true for (const iterator of s2) { console.log(iterator); } // clear 清空集合,返回 undefined console.log(s2.clear()); // undefined </script> </html>
-
Map
-
ES6
提供了Map
数据结构。它类似于对象,也是键值对的集合。但是“键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map
也实现了iterator
接口,所以可以使用『扩展运算符』
和『for…of…』
进行遍历。Map
的属性和方法:size
返回Map
的元素个数set
增加一个新元素,返回当前Map
get
返回键名对象的键值has
检测Map
中是否包含某个元素,返回boolean
值clear
清空集合,返回undefined
<!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>Document</title> </head> <body></body> <script src="./http.js"></script> <script> const map = new Map([ ["name", "网星软件"], ["slogon", "不断提高行业标准"], ]); console.log(map); // {'name' => '网星软件', 'slogon' => '不断提高行业标准'} // size 返回 Map 的元素个数 console.log(map.size); // 2 // set 增加一个新元素,返回当前 Map console.log(map.set("old", 13)); // get 返回键名对象的键值 console.log(map.get("old")); // 13 // has 检测 Map 中是否包含某个元素,返回 boolean 值 console.log(map.has("name")); // true for (const item of map) { console.log(item); } // clear 清空集合,返回 undefined console.log(map.clear()); // undefined </script> </html>
class
类
-
ES6
提供了更接近传统语言的写法,引入了Class
(类)这个概念,作为对象的模板。通过class
关键字,可以定义类。基本上,ES6
的class
可以看作只是一个语法糖,它的绝大部分功能,ES5
都可以做到,新的class
写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。知识点class
声明类constructor
定义构造函数初始化
<!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>Document</title> </head> <body></body> <script src="./http.js"></script> <script> // 创建类 class Person { // 静态属性 可以直接被类名调用 static type = "human"; /** * 构造函数(构造方法) 不能写出箭头函数 * 做初始化的 */ constructor(name, age) { this.name = name; this.age = age; } /** * 普通函数 * 关于对象的行为操作 */ // sayHi() { // console.log(`${this.name}:hi`); // } sayHi = () => { console.log(`${this.name}:hi`); }; /** * 静态方法 被 static 修饰 * 频繁使用的一些方法 */ static talk() { console.log("讲话"); } } const person = new Person("张三", 18); console.log(person); person.sayHi(); // 静态方法可以直接被类名调用 无需创建对象 Person.talk(); console.log(Person.type); // human </script> </html>
extends
继承父类super
调用父级构造方法static
定义静态方法和属性- 父类方法可以重写
<!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>Document</title> </head> <body></body> <script src="./http.js"></script> <script> // 定义 Person 类 class Person { constructor(name, age) { this.name = name; this.age = age; } sayHi = () => { console.log(`${this.name}:hi`); }; static talk() { console.log("讲话"); } } // 定义 Student 类,并继承 Person,只能继承一个 class Student extends Person { constructor(name, age, score) { // 交给父类 super(name, age); // 自己的参数 this.score = score; } // 子类可以重写父类中的方法 sayHi = () => { console.log("hello"); }; static talk() { console.log("spack"); } } const stu = new Student("张三", 18, 66); console.log(stu); stu.sayHi(); Student.talk(); </script> </html>
没有模块化产生的问题
-
结构目录
-
代码展示
-
bar.js
var a = true;
-
foo.js
var a = false;
-
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>Document</title> </head> <body></body> <script src="./bar.js"></script> <script src="./foo.js"></script> <script> if (a) { // 没有内容打印 前面的var a把后面的var a给覆盖了,导致最后执行了foo.js里面的var a = false // 但是当你把 俩个文件引入的顺序换一下就会打印出来 // 当你把这俩个文件看成俩个不同的人写的项目,这样就会造成项目之间的互相影响 也会使后期的代码不好维护 console.log("a == true"); } </script> </html>
-
-
早期解决的办法:(闭包)
-
bar.js
var bar = (function () { // 返回一个对象 这样我们就可以使用 对象.属性 的方式获取 return { a: true, }; })();
-
foo.js
var foo = (function () { // 返回一个对象 这样我们就可以使用 对象.属性 的方式获取 return { a: false, }; })();
-
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>Document</title> </head> <body></body> <script src="./bar.js"></script> <script src="./foo.js"></script> <script> if (bar.a) { console.log("a == true"); // a == true } </script> </html>
-
这样虽然可以解决问题,但是当你一直在
bar.js
和foo.js
的return
里面写代码,会发现非常臃肿。所以让我们看看下面ES6
中的模块化。
-
模块化
- 模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
- 模块化的优势有以下几点:
- 防止命名冲突
- 代码复用
- 高维护性
2.18.2.
模块化规范产品ES6
之前的模块化规范有:CommonJS=> NodeJS、Browserify
AMD => requireJS
CMD => seaJS
ES6 模块化语法
-
模块功能主要由两个命令构成:
export
和import
。 -
export
命令用于规定模块的对外接口export
导出 将需要给别人使用的变量或者方法暴露出去
-
import
命令用于输入其他模块提供的功能import
导入 将别人导出的变量和方法引入使用
-
导出导入的方式(输出打印需要开启一个服务)
-
目录结构
-
单独导出
-
foo.js
export const a = 10;
-
main,js
// 程序的入口(主文件) // 导入方式一 import * as foo from "./foo.js"; console.log(foo.a); // 10
// 程序的入口(主文件) // 导入方式二 import { a } from "./foo.js"; console.log(a); // 10
-
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>Document</title> </head> <body></body> <script src="./main.js" type="module"></script> </html>
-
-
统一导出
-
bar,js
const name = "张三"; const sum = function (a, b) { return a + b; }; // 导出 export { name, sum };
-
foo.js
const a = 10; const sum = (a, b) => console.log(a + b); // 30 export { a, sum };
-
main.js
// 程序的入口(主文件) import * as bar from "./bar.js"; import * as foo from "./foo.js"; console.log(bar.name); // 张三 console.log(bar.sum(10, 30)); // 40 console.log(foo.a); // 10 foo.sum(10, 20);
-
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>Document</title> </head> <body></body> <script src="./main.js" type="module"></script> </html>
-
-
默认导出(一个)
-
bar,js
export default 10;
-
foo,js
// 这里 a 前面不能加 const // 这里默认导出只能有一个 不可以写多个默认导出 export default () => 10 + 20;
-
main,js
// 程序的入口(主文件) import bar from "./bar.js"; import foo from "./foo.js"; console.log(bar); // 10 console.log(foo()); // 30
-
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>Document</title> </head> <body></body> <script src="./main.js" type="module"></script> </html>
-
-
默认导出(多个)
-
foo.js
const a = 10; const sum = () => 10 + 20; export default { a, sum };
-
main,js
// 程序的入口(主文件) import foo from "./foo.js"; console.log(foo.a); // 10 console.log(foo.sum()); // 30
-
index,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>Document</title> </head> <body></body> <script src="./main.js" type="module"></script> </html>
-
-
ES10
新增的模块化
-
目录结构
-
代码展示
-
data.js
export const formatDate = () => new Date();
-
math.js
export const radom = () => Math.random();
-
index.js
// 统一导出 // * 表示所有 export * from "./data.js"; export * from "./math.js";
-
main.js
import { formatDate, radom } from "./index.js"; console.log(formatDate()); console.log(radom());
-
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>Document</title> </head> <body> <script src="./main.js" type="module"></script> </body> </html>
-
async
和 await
async
和await
两种语法结合可以让异步代码像同步代码一样async
函数的返回值为promise
对象promise
对象的结果由async
函数执行的返回值决定await
必须写在async
函数中await
右侧的表达式一般为promise
对象await
返回的是promise
成功的值await
的promise
失败了, 就会抛出异常, 需要通过try...catch
捕获处理
Rest/Spread 属性
-
Rest
参数与spread
扩展运算符在ES6
中已经引入,不过ES6
中只针对于数组, 在ES9
中为对象提供了像数组一样的rest
参数和扩展运算符<!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>Document</title> </head> <body></body> <script> function connect({ host, port, ...user }) { console.log(host, port); // 127.0.0.1 8080 console.log(user); // {username: 'admin', password: '123456', type: 'master'} } connect({ username: "admin", password: "123456", host: "127.0.0.1", port: 8080, type: "master", }); </script> </html>