ECMA6Script
1、ECMA6Script的介绍
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,它的目标是使得 JavaScript
语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
ES6带来的 箭头函数、模板字符串、let和const关键字、解构、默认参数值、模块系统
等大量的新特性
,使得JavaScript
代码更为简洁,功能更加强大,大大提升了JavaScript的开发体验。VUE3
中就大量使用了ES6
的语法。
2、let 和 var (主要) 差别
① let 不能重复声明,var 可以
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>let和var</title>
<script>
var b = 2;
var b = 3;//可以重复声明
let a = 1;
let a = 6;//报错:Identifier 'a' has already been declared
</script>
</head>
<body></body>
</html>
② let声明的变量只在它所在的代码块有效,var声明的变量全局范围内都有效
;
for循环中推荐使用 let
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>let和var</title>
<script>
{
let a = 1;
var b = 2;
}
console.log(b); // 2
console.log(a); // 报错: a is not defined 花括号外面无法访问
</script>
</head>
<body></body>
</html>
③ 不存在变量提升(先声明,再使用)
let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>let和var</title>
<script>
console.log(test); //可以 但是值为undefined
var test = "test";
console.log(test1); //报错:Cannot access 'test1' before initialization
let test1 = "test1";
</script>
</head>
<body></body>
</html>
④ 不会成为window的属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>let和var</title>
<script>
var a = 100;
console.log(window.a); //100
let bb = 200;
console.log(window.bb); //undefined
</script>
</head>
<body></body>
</html>
3、const
const 和 let 类似,只是 const 定义的变量不能修改,类似final
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>const</title>
<script>
//1.常量声明必须有初始化值
const v //报错:Missing initializer in const declaration(没有赋初始值)
//-------------------------------------------------------------------------------
//2.常量值不可以改动
let a = 1
a = 2 // 可以改变
const b = 2
b = 3 //报错:Assignment to constant variable(赋值给常量变量)
//-------------------------------------------------------------------------------
//3.声明场景语法,建议变量名大写区分
const PI = 3.1415926;
//-------------------------------------------------------------------------------
//4.和let一样,块儿作用域
{
const A = "summer";
console.log(A);
}
console.log(A); // 报错;A is not defined
//-------------------------------------------------------------------------------
//5.对应数组和对象元素修改,不算常量修改,修改值,不修改地址
const TEAM = ["刘德华", "张学友", "郭富城"];
TEAM.push("黎明"); //可以
TEAM = []; // 报错: Assignment to constant variable(赋值给常量变量) 不能指向新的数组(地址值不能改变)
console.log(TEAM);
</script>
</head>
<body></body>
</html>
4、模板字符串
模板字符串
(template string)是增强版
的字符串,用 反引号 ` 标识
- 字符串中可以出现换行符
- 可以使用
${xxx}
形式输出变量和拼接变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>const</title>
<script>
// 1.普通字符串拼接
let name = "中华";
let infoStr = name + "人民共和国";
console.log(infoStr);
//---------------------------------------------------------------
// 2.模板字符串拼接
let infoStr2 = `${name}小当家`;
console.log(infoStr2);
//---------------------------------------------------------------
// 3.多行普通字符串
let ulStr = "<ul>" +
"<li>JAVA</li>" +
"<li>html</li>" +
"<li>VUE</li>" +
"</ul>";
console.log(ulStr);
//---------------------------------------------------------------
// 4.多行模板字符串
let ulStr2 =
`<ul>
<li>JAVA</li>
<li>html</li>
<li>VUE</li>
</ul>`;
console.log(ulStr2);
</script>
</head>
<body></body>
</html>
执行结果:
5、es6的解构表达式
ES6 的解构赋值是一种方便的语法,可以快速将数组或对象
中的值拆分并赋值
给变量。解构赋值的语法
使用花括号 {}
表示对象
,方括号 []
表示数组
。
Ⅰ、数组解构赋值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>es6的解构表达式</title>
<script>
//可以通过数组解构将数组中的值赋值给变量
//新增变量名任意合法即可,本质是按照顺序进行初始化变量的值
let [aa, bbb, c] = [1, 2, 3];
console.log(aa); // 1
console.log(bbb); // 2
console.log(c); // 3
//该语句将数组 [1, 2, 3] 中的第一个值赋值给 aaa 变量,第二个值赋值给 bbbb 变量,第三个值赋值给 cc 变量。
//可以使用默认值为变量提供备选值,在数组中缺失对应位置的值时使用该默认值。例如:
let [aaa, bbbb, cc, d = 4] = [1, 2, 3];
console.log(d); // 4
</script>
</head>
<body></body>
</html>
Ⅱ、对象解构赋值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>es6的解构表达式</title>
<script>
// 可以通过对象解构将对象中的值赋值给变量,语法为:
let { a, b } = { a: 1, b: 2 };
//新增变量名必须和属性名相同,本质是初始化变量的值为对象中同名属性的值
//等价于 let a = 对象.a let b = 对象.b
console.log(a); // 1
console.log(b); // 2
//该语句将对象 {a: 1, b: 2} 中的 a 属性值赋值给 a 变量,b 属性值赋值给 b 变量。
//可以为标识符分配不同的变量名称,使用 : 操作符指定新的变量名。例如:
let { a: x, b: y } = { a: 66, b: 88 };
console.log(x); // 66
console.log(y); // 88
</script>
</head>
<body></body>
</html>
Ⅲ、函数参数解构赋值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>es6的解构表达式</title>
<script>
//解构赋值也可以用于函数参数。例如:
function add([x, y]) {
return x + y;
}
console.log(add([1, 2])) // 3
</script>
</head>
<body></body>
</html>
6、es6的箭头函数
ES6 允许使用“箭头
” 义函数。语法类似Java中的Lambda表达式
① 箭头函数声明
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>es6的箭头函数</title>
<script>
//函数声明:
//普通函数
let fun1 = function () { }
//箭头函数,此处不需要书写function关键字
let fun2 = () => { }
//单参数可以省略(),多参数无参数不可以!
let fun3 = x => { }
//只有一行方法体可以省略{};
let fun4 = x => console.log(x)
//当函数体只有一句返回值时,可以省略{}和 return 语句
let fun5 = x => x + 1
</script>
</head>
<body></body>
</html>
② 箭头函数this关键字
箭头函数没有自己的this,箭头函数中的this是外层上下文环境
中的this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>es6的箭头函数</title>
<script>
//箭头函数没有自己的this,箭头函数中的this是外层上下文环境中的this
console.log(this)
console.log("-----------------------------------------")
let user = {
age: 18,
showInfo: function () {
console.log(this)
console.log(this.age)
},
viewInfo: () => {//此this的外层是user对象,user对象上下文环境中的this就是Window对象,Window对象无age属性
console.log(this)
console.log(this.age)
}
}
user.showInfo();
console.log("-----------------------------------------")
user.viewInfo();
</script>
</head>
<body></body>
</html>
③ 箭头函数this牛刀小试
练习:点击图片,两秒后变换颜色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>es6的箭头函数this练习</title>
<style>
#xdd {
display: inline-block;
width: 200px;
height: 200px;
background-color: red;
}
#tmd {
display: inline-block;
width: 200px;
height: 200px;
background-color: lightblue;
}
</style>
</head>
<body>
<div id="xdd"><a style="font-size: 26px;">不使用箭头函数</a></div><br>
<div id="tmd"><a style="font-size: 26px;">使用箭头函数</a></div>
<script>
let xdd = document.getElementById("xdd");
let tmd = document.getElementById("tmd");
// 方案1
xdd.onclick = function () {
console.log(this) // <div id="xdd"><a style="font-size: 26px;">不使用箭头函数</a></div><br>
let _this = this;
//开启定时器
window.setTimeout(function () {
console.log(this) //Window对象
//点击后2秒变黄
_this.style.backgroundColor = 'yellow';
}, 2000);
}
// 方案2 使用箭头函数
tmd.onclick = function () {
console.log(this) // <div id="tmd"><a style="font-size: 26px;">使用箭头函数</a></div>
//开启定时器
window.setTimeout(() => {
//使用setTimeout() 方法所在环境时的this对象
console.log(this)// <div id="tmd"><a style="font-size: 26px;">使用箭头函数</a></div>
//变绿
this.style.backgroundColor = 'pink';
}, 2000);
}
</script>
</body>
</html>
演示结果:
ES6箭头函数中 this 关键字理解
④ rest和spread
rest
剩余的,解决剩余的参数接收
问题,因为箭头函数中无法使用arguments,rest 是一种解决方案。rest参数
在一个参数列表中的最后一个
,这也就无形之中要求一个参数列表中只能有一个rest参数
rest
剩余:是把...args
用在了参数列表
作为形参
使用的;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>es6的箭头函数rest</title>
<script>
//rest 剩余的,解决剩余的参数接收问题,因为箭头函数中无法使用arguments,rest 是一种解决方案
// rest参数在一个参数列表中的最后一个只,这也就无形之中要求一个参数列表中只能有一个rest参数
//let fun5 = (...args,...args2) =>{} // 这里报错
let fun3 = function (a, b, c, ...args) {
console.log(a, b, c)// 1 2 3
console.log(args) // (6) [4, 5, 6, 7, 8, 9]
}
let fun4 = (...args) => {
console.log(args) //(5) [12, 23, 34, 45, 56]
}
fun3(1, 2, 3, 4, 5, 6, 7, 8, 9)
fun4(12, 23, 34, 45, 56)
</script>
</head>
<body>
</body>
</html>
spread
展开:是把...args
放在方法调用
时作为实参
使用的;
1、方法调用使用
2、快速合并数组
3、快速合并对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>es6的箭头函数 spread</title>
<script>
//-------------------------1、方法调用使用
let arr = [1, 2, 3]
//let arrSpread = ...arr;// 这样不可以,...arr必须在调用方法时作为实参使用
let fun1 = (a, b, c) => {
console.log(a, b, c)
}
fun1(arr)//(3) [1, 2, 3] undefined undefined 会把arr整体赋值给a,b和c均为 undefined
fun1(...arr)//1 2 3
//-------------------------2、快速合并数组
let a = [1, 2, 3]
let b = [3, 4]
let c = [5, 6]
let d = [...a, ...b, ...c]
console.log(d)//(7) [1, 2, 3, 3, 4, 5, 6]
//-------------------------3、快速合并对象
let p1 = { name: "张三" }
let p2 = { age: 10 }
let p3 = { gender: "boy" }
let person = { ...p1, ...p2, ...p3 }
console.log(person)//{name: '张三', age: 10, gender: 'boy'}
</script>
</head>
<body>
</body>
</html>
7、es6的对象创建和拷贝
ES6中新增了对象创建的语法糖,支持了class extends constructor
等关键字,让ES6的语法和面向对象的语法更加接近
① 对象创建的语法糖
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>es6对象创建的语法糖</title>
<script>
class Person {
// 属性
#n;
age;
get name() {
return this.n;
}
set name(n) {
this.n = n;
}
// 实例方法
eat(food) {
console.log(this.age + "岁的" + this.n + "用筷子吃" + food)//10岁的小明用筷子吃火锅
}
// 静态方法
static sum(a, b) {
return a + b;
}
// 构造器
constructor(name, age) {
this.n = name;
this.age = age;
}
}
let person = new Person("张三", 10);
// 访问对象属性
// 调用对象方法
console.log(person.name)//张三
console.log(person.n)//张三
person.name = "小明"
console.log(person.age)//10
person.eat("火锅")
console.log(Person.sum(1, 2))//3
class Student extends Person {
grade;
score;
study() {
}
constructor(name, age) {
super(name, age);
}
}
let stu = new Student("学生小李", 18);//18岁的学生小李用筷子吃面条
stu.eat("面条")
</script>
</head>
<body>
</body>
</html>
② 对象的深拷贝和浅拷贝
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>对象的深拷贝和浅拷贝</title>
<script>
let arr = ['java', 'c', 'python']
let person = {
name: '张三',
language: arr
}
// 浅拷贝,person2和person指向相同的内存
let person2 = person;
person2.name = "小黑"
console.log(person.name)//小黑
console.log(person2.name)//小黑
console.log("==============================================")
let arr2 = ['java', 'c', 'python']
let person3 = {
name: '李四',
language: arr2
}
// 深拷贝,通过JSON和字符串的转换形成一个新的对象
let person4 = JSON.parse(JSON.stringify(person3))
person4.name = "小白"
console.log(person3.name)//李四
console.log(person4.name) //小白
</script>
</head>
<body>
</body>
</html>
8、es6的模块化处理
模块化是一种
组织
和管理
前端代码的方式,将代码拆分
成小的模块单元;提高代码可维护性、可复用性、可扩展性
- ES6模块化的
暴露
和导入方式
1. 分别导出
2. 统一导出
3. 默认导出
- ES6中
无论以何种方式导出
,导出的都是一个对象
,导出的内容都可以理解为是向这个对象中添加属性或者方法
① 分别导出
模块想对外导出,添加
export
关键字
Ⅰ、module.js 向外分别暴露成员
//1.分别暴露
// 模块想对外导出,添加export关键字即可!
// 导出一个变量
export const PI = 3.14;
const PI2 = 5.68;
// 导出一个函数
export function sum(a, b) {
return a + b;
}
// 导出一个类
export class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`);
}
}
Ⅱ、app.js 导入module.js中的成员
/*
*代表module.js中的所有成员
m1代表所有成员所属的对象
*/
import * as m1 from "./module.js";
// 使用暴露的属性
console.log(m1.PI); //3.14
console.log(m1.PI2); //undefined 【module.js中没有对外暴露PI2,所以无法使用】
// 调用暴露的方法
let result = m1.sum(10, 20);
console.log(result); //Hello, my name is 张三, I'm 10 years old.
// 使用暴露的Person类
let person = new m1.Person("张三", 10);
person.sayHello();
Ⅲ、index.html作为程序启动的入口 导入 app.js
导入JS文件 添加type=‘module’ 属性,否则不支持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><!-- 导入JS文件 添加type='module' 属性,否则不支持ES6的模块化 -->
<script src="./app.js" type="module" />
</head>
<body>
</body>
</html>
② 统一导出
Ⅰ、module.js 向外分别暴露成员
//2.统一暴露
// 模块想对外导出,export统一暴露想暴露的内容!
// 定义一个常量
const PI = 3.14;
// 定义一个函数
function sum(a, b) {
return a + b;
}
// 定义一个类
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`);
}
}
// 统一对外导出(暴露)
export { PI, sum, Person };
Ⅱ、app.js 导入module.js中的成员
/*
{}中导入要使用的来自于module.js中的成员
{}中导入的名称要和module.js中导出的一致,也可以在此处起别名
{}中如果定义了别名,那么在当前模块中就只能使用别名
{}中导入成员的顺序可以不是暴露的顺序
一个模块中可以同时有多个import
多个import可以导入多个不同的模块,也可以是同一个模块
*/
//import {PI ,Person ,sum } from './module.js'
//import {PI as pi,Person as People,sum as add} from './module.js'
import {
PI,
Person,
sum,
PI as pi,
Person as People,
sum as add,
} from "./module.js";
// 使用暴露的属性
console.log(PI); //3.14
console.log(pi); //3.14
// 调用暴露的方法
let result1 = sum(10, 20);
console.log(result1); //30
let result2 = add(10, 20);
console.log(result2); //30
// 使用暴露的Person类
let person1 = new Person("张三", 10);
person1.sayHello(); //Hello, my name is 张三, I'm 10 years old.
let person2 = new People("李四", 11);
person2.sayHello(); //Hello, my name is 李四, I'm 11 years old.
Ⅲ、index.html作为程序启动的入口 导入 app.js
导入JS文件 添加type=‘module’ 属性,否则不支持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><!-- 导入JS文件 添加type='module' 属性,否则不支持ES6的模块化 -->
<script src="./app.js" type="module" />
</head>
<body>
</body>
</html>
③ 默认导出 export default
Ⅰ、module.js 向外分别暴露成员
// 3默认和混合暴露
/*
默认暴露语法 export default sum
默认暴露相当于是在暴露的对象中增加了一个名字为default的属性
三种暴露方式可以在一个module中混合使用
*/
export const PI = 3.14
// 导出一个函数
function sum(a, b) {
return a + b;
}
// 导出一个类
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`);
}
}
// 导出默认
export default sum
// 统一导出
export {
Person
}
Ⅱ、app.js 导入module.js中的成员
/*
*代表module.js中的所有成员
m1代表所有成员所属的对象
*/
import * as m1 from "./module.js";
import { default as add } from "./module.js"; // 用的少
import add2 from "./module.js"; // 等效于 import {default as add2} from './module.js'
// 调用暴露的方法
let result = m1.default(10, 20);
console.log(result);//30
let result2 = add(10, 20);
console.log(result2);//30
let result3 = add2(10, 20);
console.log(result3);//30
// 引入其他方式暴露的内容
import { PI, Person } from "./module.js";
// 使用暴露的Person类
let person = new Person("张三", 10);
person.sayHello();//Hello, my name is 张三, I'm 10 years old.
// 使用暴露的属性
console.log(PI);//3.14
Ⅲ、index.html作为程序启动的入口 导入 app.js
导入JS文件 添加type=‘module’ 属性,否则不支持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>
<!-- 导入JS文件 添加type='module' 属性,否则不支持ES6的模块化 -->
<script src="./app.js" type="module" />
</head>
<body>
</body>
</html>