ES6+ (上)
一、ECMAScript简介
1.1 什么是ECMA
- ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994 年后该组织改名为 Ecma 国际。
1.2 什么是 ECMAScript
-
ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言
-
Ecma 国际制定了许多标准,而 ECMA-262 只是其中的一个,所有标准列表查看
http://www.ecma-international.org/publications/standards/Standard.htm
1.3 ECMA-262历史
-
ECMA-262(ECMAScript)历史版本查看网址:
http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm
- 注:从 ES6开始,每年发布一个版本,版本号以年份命名。ES2016(ES7)、ES2017(ES8)、ES2018(ES9)、ES2019(ES10)、ES2020(ES11)
1.4 谁在维护ECMA-262
- TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39 定期召开会议,会议由会员公司的代表与特邀专家出席
1.5 为什么要学习ES6
- ES6 的版本变动内容最多,具有里程碑意义;
- ES6 加入许多新的语法特性,编程实现更简单、高效;
- ES6 是前端发展趋势,就业必备技能;
1.6 ES6 兼容性
- 查看网址:http://kangax.github.io/compat-table/es6
二、let
let 关键字用来声明变量
2.1 let 特点
-
块级作用域
-
在ES5中,只有全局作用域和函数作用域。这会导致函数作用域覆盖了全局作用域;亦或者循环中的变量泄露为全局变量
-
在ES6中,新增了块级作用域,使用let声明的变量只在当前{}内可以访问,。{}包括if(){}、for(){} 、while(){}、{}等
// 函数作用域覆盖了全局作用域 var num = 100; function test(){ console.log(num) if(true){ var num = 20; } } test(); // 循环中的变量泄露为全局变量 for(var i=1;i<=10;i++){ console.log(i) } console.log(i);
-
-
不允许重复声明
-
不存在变量提升
-
不影响作用域链
let num = 100; function test(){ console.log(num) } test();
2.2 let与var的区别
- var声明的是函数作用域或全局作用域,let声明的是块级作用域
- var声明的变量有变量提升,let声明的变量没有
- var可以重新声明变量,let不可以重新声明
- var声明的全局变量是window对象的属性,let声明的变量不是
三、const
- const 关键字用来声明常量
3.1 const特点
-
声明的同时必须赋值
const IP = '127.0.0.1';
-
不允许重复声明
-
块级作用域
-
值不允许修改
-
值为对象或数组时可以修改,因为它们属于地址引用数据类型,数据变化了,但是引用的地址并没有变化
// 定义常量 const COLORS = ['red','green','blue']; // 改变数组的值 COLORS.push('pink'); // 输出常量 console.log(COLORS);
-
3.1 应用场景
- 声明对象类型使用const,非对象类型声明选择let
四、 解构赋值
ES6 允许按照一定模式从数组和对象中提取值,赋值给变量,这被称为解构赋值
4.1 数组解构
-
单行解构
let [name, age, gender] = ['Mr.Gao', 100, '男'];
-
默认值
let [name, age, gender='男'] = ['Mr.Gao',100]
-
不定个数
let [name,age,...others] = ['Mr.Gao',100,'男','郑州'] console.log(others); // [ '男','郑州' ]
-
逗号占位
let [,,gender,city] = ['Mr.Gao',100,'男','郑州'] console.log(gender,city); // '男','郑州'
-
多维数组
let [name, [age, gender]] = ['Mr.Lee', [100, '男']];
2.2 对象解构
-
对象的解构方式和数组大同小异
let obj = { id: 1, info:{ name: 'Mr.Gao', age: 100, gender: '男', }, sing: function(){ console.log('唱歌') } } // 解构指定 let {info} = obj; console.log(info); // 多级解构 let {info:{name}} = obj; console.log(name) // 解构全部 let {id,info:{name,age,gender},sing} = obj; sing(); // 解构时变量改名 let {info:{name: myname, age: myage} } = obj; console.log(myname,myage);
demo: 交换两个变量的值
let a = 100;
let b = 200;
[a,b] = [b,a];
console.log(a,b);
五、 模板字符串
-
模板字符串(template string)是增强版的字符串,用反引号(`)标识
-
特点如下:
-
字符串中可以识别空格、换行、单引、双引
-
可以使用 ${} 形式输出变量以及使用函数、运算符
function abc() { return 100; } let num = 200; console.log (`两数之和为:"${num + abc() }"` )
-
六、简化对象写法
-
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁
let username = 'Andy'; let age = 18; function study(){ console.log("努力学习"); } // 简写对象 let student = { username, age, study } // 调用属性和方法 console.log( student.username ); console.log( student.study() );
-
ES6 允许在对象中声明方法时可以省去function
// es5 let obj = { say: function(){ console.log("说话方法") } } // es6简写 let obj = { say(){ console.log("说话方法") } }
七、 箭头函数
箭头函数相当于匿名函数,并且简化了匿名函数的写法
7.1 基本用法
-
函数无参数
let test = function (){ console.log("hello") } // 箭头函数写法 let test = () => { console.log("hello") }
-
函数只有一个参数
let test = function (x){ console.log(x) } // 箭头函数写法 let test = x => { console.log(x) }
-
函数有多个参数
let test = function (x,y){ console.log(x + y) } // 箭头函数写法 let test = (x,y) => { console.log(x+y) }
-
函数体只有一条语句
let test = function (x,y){ return x + y; } // 箭头函数会默认将这一条语句的值当作返回值 let test = (x,y) => x + y;
7.2 注意的问题
-
当函数体中只有return语句时,使用箭头函数比较方便,但当返回值为对象时,需要在对象外加上( ),否则对象中的{}会产生岐义
var test = (x,y) => ({ num1:x, num2:y }) console.log( test(100,200) );
-
箭头函数不能用作为构造函数通过new实例化
-
箭头函数没有prototype原型属性
-
箭头函数不能使用arguments ,可以使用…rest
-
箭头函数.call()不会改变this的指向,但是也能成功调用箭头函数
-
普通函数中的this指向将函数作为方法调用的对象, 箭头函数中的this指向上层普通函数所属对象
-
其实质是因为箭头函数没有自己的this,用的是上层普通函数的this
var num = 10; var obj = { num: 20, fun1: function(){ console.log(this.num) ; var fun11 = () => { console.log(this.num); } fun11(); }, fun2: () => { console.log(this.num); var fun22 = () => { console.log(this.num); } fun22(); }, obj2: { num:30, fun3: function(){ console.log(this.num); }, fun4: () => { console.log(this.num); }, } } obj.fun1(); // ? obj.fun2(); // ? obj.obj2.fun3(); // ? obj.obj2.fun4(); // ?
-
八、rest 参数
-
ES6 引入 rest 参数,用来代替 arguments 接收函数实参
-
rest参数非常适合函数实参个数不确定的场景
function sum(x,y,...args){ // 当实参的个数不确定时,可以通过...形参名称来接收实参 console.log(args) var sum = x + y; for(var i=0;i<args.length;i++){ sum += args[i]; } return sum; }
九 、spread 扩展运算符
-
扩展运算符(spread)也是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包
-
展开数组
/** * 展开数组 */ let tfboy = ['易烊千玺','王源','王俊凯']; console.log(tfboy); // [ '易烊千玺', '王源', '王俊凯' ] console.log(...tfboy); // 易烊千玺 王源 王俊凯 /** *函数传参 */ function sum(x,y,...args){ // 当实参的个数不确定时,可以通过...形参名称来接收实参 console.log(args) var sum = x + y; for(var i=0;i<args.length;i++){ sum += args[i]; } return sum; } console.log(sum(...[10,20,30,40,50])) // ...此时为扩展运算符 相当于sum(10,20,30,40,50)
-
合并数组
let tfboy = [ '易烊千玺', '王源', '王俊凯' ]; let kings = ['沈腾','贾玲']; let tfboyKings = [...tfboy,...kings]; console.log(tfboyKings)
十、Symbol
-
ES6 引入了一种新的原始数据类型 Symbol(符号),表示独一无二的值。是一种类似于id
- Symbol是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型
- Undefined、Null、Boolean、Number、String、Object、Symbol(ES6)、BigInt(ES10)
- Symbol是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型
-
Symbol 特点:
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用Reflect.ownKeys 来获取对象的所有键名
-
创建:
// 创建 Symbol let s1 = Symbol(); console.log(s1); console.log(typeof s1) // 创建Symbol时添加标识 let s2 = Symbol('hello'); let s3 = Symbol('hello'); console.log(s2 === s3); // 使用 Symbol for 创建 let s4 = Symbol.for('hello'); let s5 = Symbol.for('hello'); console.log(s4 === s5); // 不能与其它数据进行任何的运算、比较、拼接 console.log( s1 + 100 )
-
作用:
// 向对象中扩展属性和方法时可以避免命名冲突 let game = { name: '王者荣耀', level: '青铜', kill(){ console.log('You are die!!!'); } } // 扩展属性和方法时避免命名冲突 let name = Symbol('newname'); let kill = Symbol('3kill'); game[name] = '王者'; game[kill] = function(){ console.log('kill! kill! kill!'); } // 调用属性和方法 console.log(game); console.log(game[name]); game[kill]();
十一、Set
-
ES6提供了新的数据结构Set(集合)。
-
Set类似于数组,但成员的值要求是唯一的,不能重复
-
属性
- size 返回集合中元素的个数
-
方法
- add() 增加一个新元素,返回当前集合
- delete() 删除元素,返回布尔值
- clear() 清空集合,没有返回值
- has() 检测集合中是否包含某个元素,返回布尔值
-
操作
// 创建 let colorSet = new Set(['red','green','blue','red']); // 添加 colorSet.add('pink'); // 删除 colorSet.delete('pink'); console.log(colorSet);
-
应用
-
去除数组中的重复成员
let colorArr = ['red','green','blue','red']; colorArr = [...new Set(colorArr)]; console.log(colorArr)
-
去除字符串中的重复字符
let str = 'ababbc' console.log( [...new Set(str)].join('') )
-
求交集
let arr1 = [10,20,30,40,50,60]; let arr2 = [30,40,50,60,70,80]; let result = [...new Set(arr1)].filter(item => new Set(arr2).has(item)) console.log(result);
-
求并集
let arr1 = [10,20,30,40,50,60]; let arr2 = [30,40,50,60,70,80]; let result = [... new Set( [...arr1,...arr2]) ] ; console.log(result);
-
求差集
let arr1 = [10,20,30,40,50,60]; let arr2 = [30,40,50,60,70,80]; let result1 = [...new Set(arr1)].filter(item => !new Set(arr2).has(item)) console.log(result1); let result2 = [...new Set(arr2)].filter(item => !new Set(arr1).has(item)) console.log(result2);
-
十二、Map
-
ES6 提供了 Map 数据结构。
-
它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
-
属性
- size 返回Map集合中元素的个数
-
方法
- set() 增加一个新元素,返回当前Map集合
- get() 根据键名返回键值
- delete() 根据键名删除元素
- clear() 清空Map集合,没有返回值
- has() 检测Map集合中是否包含某个元素,返回布尔值
-
操作
// 创建一个空Map let studentMap = new Map(); // 添加元素 studentMap.set('name','小明'); studentMap.set('age',20); studentMap.set('score',60); // 获取元素的值 console.log(studentMap); console.log(studentMap.get('score'));
-
可以通过构造函数传递参数的方式进行初始化集合
let studentMap = new Map([ ['name','小花'], ['age',18], ['score',100] ]); console.log(studentMap);
当作键。
-
属性
- size 返回Map集合中元素的个数
-
方法
- set() 增加一个新元素,返回当前Map集合
- get() 根据键名返回键值
- delete() 根据键名删除元素
- clear() 清空Map集合,没有返回值
- has() 检测Map集合中是否包含某个元素,返回布尔值
-
操作
// 创建一个空Map let studentMap = new Map(); // 添加元素 studentMap.set('name','小明'); studentMap.set('age',20); studentMap.set('score',60); // 获取元素的值 console.log(studentMap); console.log(studentMap.get('score'));
-
可以通过构造函数传递参数的方式进行初始化集合
let studentMap = new Map([ ['name','小花'], ['age',18], ['score',100] ]); console.log(studentMap);