ES全称叫做:EcmaScript,是脚本语言的规范,而平时经常编写的 JavaScript 是 EcmaScript 的一种实现,所以 ES 新特性其实就是指的是 JavaScript 的新特性。
一 介绍
ECMA 是欧洲计算机制造商协会,这个组织是评估,开发,认可电信和计算机标准,1994年之后,该组织改名为:ECMA 国际
ECMAScript:是由 ECMA 国际通过 ECMA-262 标准化的脚本程序设计语言
ECMA-262:ecma制定了许多标准,262 是其中的一种。
TC39 是推进ECMAScript 发展的委员会,其会员都是公司(其中主要是浏览器厂商:苹果,谷歌,微软,因特尔等)TC39 定期召开会议,会议由会员公司的代表和特邀专家出席。
ES6 的版本变动内容最多,具有里程碑的意义,还加入很多新的语法特性,编程实现更加简单,高效。
二 ES6
2.1、let声明变量
1、不能重复声明变量
2、块级作用域
{// 这里声明的 man 在外部不能被使用let man = 'tom'}console.log(man)
3、不存在变量提升,即不能在变量声明前使用
4、不影响作用域链,即函数块可以使用外部 let 声明的变量
2.2、const声明常量
1、常量必须初始化,即声明就需要赋值
2、常量名一般大写
3、常量的值不能修改
4、也是块级作用域
5、对数组,对象里面的元素做修改,不算是对常量的修改
2.3、变量的解构赋值
ES6 允许按照一定模式从数组和对象当中提取值,对变量进行赋值,这就是被称为解构赋值
1、数组的解构
const arr = ["a", "b", "c", "d"]let [a, b, c, d] = arrconsole.log(a, b, c, d)
2、对象的解构
const obj = {'name': 'kll','age': 18,'address': 'gz'}let {name, age, address} = objconsole.log(name, age, address)
2.4、模板字符串
ES6 引入了新的声明字符串的语法
1、声明变量
let str = `halo, i am a boy, i very happy, and so do you, how are you`console.log(str)
2、可以直接使用换行符号
let a = `---------\n==========`console.log(a)
3、变量拼接
let c = `${str}hhhh`console.log(c)
2.5、对象的简化写法
允许在大括号中,直接写变量和函数,作为对象的属性和方法,更加简洁
且变量名的引号可以省略!
let a = {name: 'lz',age: 18,say() {console.log('halo')}}console.log(a)a.say()
2.6、箭头函数
允许使用【箭头】 => 来定义函数
// 正常声明函数let fn1 = function (a, b) {console.log(a, b)}fn1('aaaa', 'bbbb')// es6声明函数let fn2 = (a, b) => {console.log(a, b)}fn2('vvvvv','dsdsds')
1、this是静态的,this 始终指向外部函数声明时所在作用域下的 this 的值
// 正常声明函数let fn1 = function () {console.log(this)}// es6声明函数let fn2 = () => {console.log(this)}let a = {a: 'a',b: 'b'}fn1.call(a) // 此时打印的 this 是 afn2.call(a) // 箭头函数打印的 this 还是 window 对象
2、不能作为构造函数实例化
3、不能使用 arguments 变量
let fn2 = () => {// console.log(arguments) // 不允许在内部使用这个变量}
4、箭头函数的简写
- 省略小括号,当形参有且只有一个的时候
- 省略花括号,当代码体有且只有一条语句的时候 ```javascript // 省略小括号,当形参有且只有一个的时候 let fn3 = n => { console.log(n) } fn3(3)
// 省略花括号,当代码体有且只有一条语句的时候 let fn4 = n => console.log(n) fn4(4)
<a name="w2zTc"></a>## 2.7、函数参数赋值默认值允许在函数调用时,如果没有参数传过来,就使用默认值,一般设置默认值的参数都放在后面```javascriptlet fn3 = (a = 100, b = 'l') => {console.log(a, b)}
和解构赋值结合使用
形参定义时对象的属性使用等号赋值默认值,使用函数时,参数值为对象
let fn4 = ({name, age, address = 'gz'}) => {console.log(name, age, address)}fn4({name: 'lz', age: 18})
2.8、rest参数
引入 rest 参数,用于获取函数的实参,用来代替 arguments ,类似于Java的接收可变长参数的方式
arguments 存储的是所有的参数,而 args 存储的后面剩余的所有参数
let fn5 = function (a) {console.log(a, arguments)}let fn6 = function (a, ...args) {console.log(a, args)}fn5(1, 2, 3, 4, 5) // 打印的 arguments = [1,2,3,4,5]fn6(1, 2, 3, 4, 5) // 打印的 args = [2,3,4,5]
2.9、扩展运算符
【…】扩展运算符可以将【数组】转换为逗号分隔的【参数序列】
const arr = [1, 2, 3, 4]let fn1 = function (a, b, c, d) {console.log(a, b, c, d)}// 这就是将数组的元素分割开传参数到函数fn1当中fn1(...arr)
1、数组的合并
const a = [1, 2, 3, 4]const b = [5, 6, 7, 8]const c = [...a, ...b]console.log(c)
2、数组的克隆
const d = [...c]
2.10、symbol
ES6 引入了一种新的原始数据类型:symbol,表示独一无二的值。是 JavaScript 语言的第 7 种数据类型,是一种类似于字符串的数据类型。
特点:
- 值是唯一的,用来解决命名冲突问题
- 值不能和其他数据类型进行运算
定义的对象属性不能使用 for…in 循环遍历,但是可以使用 Reflect.ownKeys 来获取对象的所有键名
let a = Symbol()let b = Symbol('b')let e = Symbol('b')let c = Symbol.for('c')let d = Symbol.for('c')console.log(c === d) // trueconsole.log(b === e) // false
JavaScript 中 7 中数据类型的记忆:you are so niubility
u:undefined
s:String,Symbol
o:Oject
n:null,number
b:boolean
- 为对象中添加属性和方法 ```javascript let obj = {
}
- Symbol内置值<a name="lllxs"></a>## 2.11、迭代器迭代器是一种接口,为各种不同的数据结构提供统一的访问机制,任何的数据结构只要部署在 Iterator 接口,就可以完成遍历操作。1. ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费1. 原生具备 Iterator 接口的数据(可用于 for of 遍历)1. Array1. Arguments1. Set1. Map1. String1. TypedArray1. NodeList3. 工作原理:1. 创建一个指针对象,指向当前的数据结构的起始位置1. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员1. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员1. 每次调用 next 方法返回一个包含 value 和 done 属性的对象```javascript// 遍历数组元素const arr = [1, 2, 3, 4, 5]for (let number of arr) {console.log(number)}let fn1 = function () {for (const argument of arguments) {console.log(argument)}}fn1(1,2,3,4)
2.12、生成器
生成器其实就是一个特殊的函数
function* gen() {console.log("----------")}// gen执行会返回一个迭代器对象,用于迭代执行该函数let iterator = gen() // 这样函数的方法还不能立即执行,还需要执行 next 方法iterator.next()
yield:相当于函数的代码分隔符
function* gen2() {console.log(1111)yield 'aaa'console.log(2222)yield 'bbb'console.log(3333)}let it2 = gen2()for (const never of it2) {// 这里其实就是执行了 yield 分割的第一个片段console.log(never) // 这个 never 就是 yield 后面的值}// 打印结果是:1111 aaa 2222 bbb 3333 按照顺序打印
2.13、promise
promise 是 ES6 引入的异步编程的新解决方案,语法上 promise 是一个构造函数,用来封装异步操作并可以获取其成功或者失败的结果
- 构造函数:Promise(excutore) {}
- Promise.prototype.then 方法
- Promise.prototype.catch 方法 ```javascript // 实例化,参数是一个函数 const p = new Promise(function (resole, reject) { let data = “成功” let err = ‘error’ // resole(data) // 调用这个方法表示请求成功 reject(err) // 调用这个方法表示失败 })
// 执行 then 方法,传入两个函数,如果成功执行第一个函数,失败执行第二个函数 p.then(function (res) { // 成功 console.log(res) }, function (err) { // 失败 console.log(err) })
- 封装 Ajax 的操作```javascript// 改造const p2 = new Promise(function (resolve, reject) {// 接口地址:https://api.apiopen.top/getJoke// 创建对象let 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)}}}})p2.then(function (res) {console.log(res)}, function (err) {console.log(err)})
promise 的 catch 方法。这个就是上面处理回调的第二种方式。
// 使用 catch 方法来捕捉失败的处理new Promise(function (resolve, reject) {reject('error form reject')}).then(function (res) {console.log(res)}).catch(function (err) {console.log(err)})
2.14、Set
ES6 提供了全新的数据结构 Set,类似于数组,但是成员的值都是唯一的,即无重复元素,和Java语言的 Set 结构差不多。集合实现了 Iterator 接口,所以可以使用 for…of 来进行遍历,集合的属性和方法
- size:属性,返回集合的元素个数
- add:方法,增加一个新的元素,返回当前集合
- delete:方法,删除元素,返回 boolean 值
- has:方法,检测集合中是否包含了某个元素,返回 boolean 值 ```javascript // 声明实例 let set = new Set() // 打印 set 的元素个数 console.log(set.size)
let set2 = new Set([1, 2, 3]) console.log(set2.size)
// 增加一个元素 set2.add(4) console.log(set2)
// 删除一个元素,参数是被删除元素的值 set2.delete(1) console.log(set2)
// 检测是否包含某个元素 console.log(set2.has(2))
// 清空元素 set2.clear() console.log(set2)
结合数组的相关操作```javascriptlet arr = [1, 2, 3, 4, 2, 3]// 1 数组去重let set = [...new Set(arr)]console.log(set)// 交集let arr2 = [4, 3, 5, 6, 4, 5]let set2 = new Set(arr2)let arr3 = set.filter(item => {return set2.has(item);})console.log(arr3)// 并集let arr4 = [...new Set([...arr, ...arr2])]console.log(arr4)// 差集let a = [...new Set(arr)].filter(item => !new Set(arr2).has(item))console.log(a)
2.15、Map
ES6 的 Map 数据结构类似于 Java 的 Map,也是键值对组合,键的范围不限于字符串,各种类型的值都可以作为键,Map实现了 Iterator 接口,所以可以使用 for…of 进行遍历。
- size:属性,返回元素个数
- Map:增加一个新元素,返回当前的Map
- get:返回键名对象的键值
- has:检测 Map 中是否包含了某个元素,返回 boolean 值
- clear:清空集合,返回 undefined ```javascript // 声明 Map let map = new Map()
// 添加元素 map.set(‘name’, ‘lz’) map.set(‘age’, 18)
// 遍历 for (const item of map) { console.log(item[0],item[1]) // item是一个数组,第一个元素是key,第二个元素是value }
<a name="s6zlS"></a>## 2.16、class类这里的class,是作为对象的模板,也类似于Java的类。通过 class 关键字,可以定义类,基本上,这里的 class 可以看作是一个语法糖,绝大部分功能,ES5 都可以做到,新的 class 写法,也只是让对象的原型的写法更加清晰,更加像面向对象编程的语法而已。```javascriptclass Phone {// 构造方法,名字不能修改constructor(a, b) {this.brand = athis.price = b}// 方法必须使用这个语法,不能使用 ES5 的对象完整形式say() {console.log('can call anybody')}}let xiaomi = new Phone('xiaomi', 1888)console.log(xiaomi)
- 静态成员
声明在类中的静态成员是不能用实例调用的,只能使用类名来调用,因为这个静态成员是声明在构造函数上的,并不是在原型上的
class Person {// 静态属性,属于这个类的,即构造函数的,只能使用类名调用static name = '人类'// 静态方法static fun() {console.log('fun')}}let xiaoMing = new Person()console.log(Person.name)
2.17、模块化
模块化指的是将一个大的程序文件,拆分成很多小的文件,然后将小文件组合起来。
模块功能主要由两个命令构成,export,import
- export命令用于规定模块的对外接口
- import命令用于输入其他模块提供的功能
1、暴露数据的方式
// 分别暴露export let name = 'lz'export function fun() {console.log('i am a function in xxx.js')}
let name = 'kk'function fun1() {console.log('hdsjhj')}// 统一暴露export {name, fun1}
// 默认暴露export default {name: 'kkkk',fun2() {console.log('halo')}}
<script type="module">import * as x from './js/xxx.js'import * as y from './js/yyy.js'import * as z from './js/zzz.js'console.log(x.name)y.fun1()z.default.fun2() // 需要加上 default</script>
2、引入数据的方式
<script type="module">// 1、这种引入数据的形式是通用的形式import * as x from './js/xxx.js'import * as y from './js/yyy.js'import * as z from './js/zzz.js'console.log(x.name)y.fun1()z.default.fun2()// 2、解构赋值的形式import {name, fun} from './js/xxx.js'import {name as name2, fun1} from './js/yyy.js' // 可以给导入的变量起别名import {default as zz} from './js/zzz.js' // 导入默认暴露的数据console.log(name)console.log(name2)console.log(zz.name)// 3、简便形式,只实用于默认暴露的数据import zzz from './js/zzz.js'zzz.fun2()</script>
2.18、Object.assgin
对象赋值,赋值对象间相同属性名的值
<script>let searchParams = {"category1Id": "", // 一级分类Id"category2Id": "", // 二级分类Id"category3Id": "", // 三级分类Id"categoryName": "", // 分类名称"keyword": "", // 关键字"order": "1:desc", // 排序"pageNo": 1, // 页码"pageSize": 10, // 每页数量"props": ["1:1700-2799:价格", "2:6.65-6.74英寸:屏幕尺寸"], // 商品属性的数组"trademark": "4:小米" // 品牌}let a = {"category1Id": 10}let b = {"categoryName": "手机", "keyword": "小米"}// 将后面的对象属性复制到第一个对象当中Object.assign(searchParams, a, b)console.log(searchParams)</script>
