3670 字
18 分钟

ES6新特性

ES6,全称是 ECMAScript 6,也被称为 ECMAScript 2015,是 JavaScript 的一种标准,于 2015 年正式发布。ES6 是 JavaScript 新一代标准的缩写,引入了很多新的语法和特性,丰富了 JavaScript 的功能和表现力,提升了开发效率。

新特性#

1 let和const#

引入了块级作用域的变量声明方式,用于替代 var 关键字。

与var区别:不能重复声明,只会在作用域内生效,没有变量提升。

let a = 1 // 声明变量
const PI = 3.14 // 声明常量

2 箭头函数#

新的函数声明方式,可以更简洁地编写函数表达式。

// ES6 允许使用 => 定义函数
//声明函数
let fn = (a, b) => {
return a + b
}
//调用函数
console.log(fn(1, 2))

箭头函数中 this 是静态的, this 始终指向函数声明时所在作用域下的 this 的值

function getName() {
console.log(this.name)
}
let getName2 = () => {
console.log(this.name)
}
// 设置 window对象 的 name 属性
window.name = 'xxyyzz'
const school = {
name: 'qinghua',
}
getName() // this 指向 window 输出 xxyyzz
getName2() // this 指向 window 输出 xxyyzz
getName.call(school) // 结果是qinghua
getName2.call(school) // 结果还是 xxyyzz

不能作为构造实例化对象

let Person = (name, age) => {
this.name = name
this.age = age
}
let person = new Person('xxyyzz', 18)
console.log(person)
// 报错: Person is not a constructor

不能使用 arguments 变量

let fn1 = () => {
console.log(arguments)
}
fn1(1, 2, 3)
// 报错: arguments is not defined

简写

// 1. 只有一个参数省略括号
let add = n => {
return n + n
}
// 2. 只有一个return省略花括号
let pow = n => n * n
// 3. 返回对象简写
const fn = uname => ({uname: uname})

3 模板字符串#

用反引号(“)来创建多行字符串和插入变量。

// 1. 变量
const hello = 'hello'
const world = 'world'
console.log(`${hello} ${world}`) // hello world
// 2. 字符
let str2 = `<ul>
<li>1</li>
<li>2</li>
</ul>`
console.log(str2)
// 3. 表达式
let a = 3
let b = 4
let str3 = `${a + b}`
console.log(str3)

4 默认参数#

在函数声明时可以为参数设置默认值。

function add(a, b, c = 10) {
return a + b + c
}
let result = add(1, 2)
console.log(result) // 13
// 2. 可以与结构赋值结合
function connect({host = '127.0.0.1', username, password, port}) {
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host: 'localhost',
username: 'root',
password: 'root',
port: 3306,
})

5 解构赋值#

可以通过解构语法从数组或对象中提取值并赋给变量。

// 1. 数组
const F4 = ['xx', 'yy', 'zz', 'kk']
let [x, y, z, k] = F4
console.log(x) // xx
console.log(y) // yy
console.log(z) // zz
console.log(k) // kk
// 2. 对象
const zs = {
name: '张三',
age: 18,
sing: function () {
console.log('我会唱歌')
},
}
let {name, age, sing} = zs // 需要用大括号
console.log(name) // 张三
console.log(age) // 18
console.log(sing) // Function
sing() // 我会唱歌
// 3. 多维解构
const dog = {
name: 'Gallagher',
attr: {
age: 13,
birth: 'Pinocorni',
},
}
const {
name,
attr: {age, birth},
} = dog
console.log(name) // Gallagher
console.log(age) // 13
console.log(birth) // Pinocorni

6 类关键字class#

引入了 class 关键字,可以更方便地创建基于原型的面向对象编程。

ES5中:

// 手机
function Phone(brand, price) {
this.brand = brand
this.price = price
}
// 添加方法
Phone.prototype.call = function () {
console.log('正在呼叫...')
}
// 实例化对象
let honor = new Phone('荣耀', 2499)
console.log(honor)
honor.call()

ES6中:

class Phone {
// 构造方法
constructor(brand, price) {
// constructor 名字不能修改,是固定的
this.brand = brand
this.price = price
}
// 添加方法,(方法必须使用该语法)
call() {
console.log('华为手机正在呼叫...')
}
}
// 实例化对象
let honor = new Phone('华为', 2499)
console.log(honor)
honor.call()

静态成员

// 类的静态成员
class Phone {
static name = 'nojiya'
static change = function () {
console.log('我可以改变你们')
}
}
let phoneSHI = new Phone()
console.log(phoneSHI)
console.log(phoneSHI.name) // undefined
console.log(Phone.name) // nojiya
console.log(Phone.change)

类继承

// ES6中使用class实现类继承
// 手机
class Phone {
constructor(brand, price) {
this.brand = brand
this.price = price
}
call() {
console.log('正在呼叫...')
}
}
// 智能手机
// extends关键字
class SmartPhone extends Phone {
constructor(brand, price, color, size) {
super(brand, price) //super 关键字用于调用父类的构造函数或方法。
this.color = color
this.size = size
}
photo() {
console.log('正在拍照...')
}
}
// 测试
let s = new SmartPhone('荣耀', 1399, '银色', '4.2inch')
console.log(s)
s.call()
s.photo()

class 中的 get 和 set

class Phone {
get price() {
console.log('price属性被读取了')
return 'iloveyou'
}
set price(newVal) {
console.log('price属性被修改了')
}
}
// 实例化对象
let s = new Phone()
console.log(s.price)
// 赋值
s.price = 'free'

7 Promise#

用于处理异步操作的新标准,避免回调地狱的问题。可以返回新的Promise链式调用。

// 创建Promise对象
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功')
})
})
// Promise.then
promise.then(value => {
console.log(value)
})
console.log(result)
// Promise.catch
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('出错啦!')
}, 1000)
})
promise2.catch(reason => {
console.warn(reason)
})

8 模块化#

引入了 import 和 export 关键字,提供了更好的模块化管理方式。

  1. 暴露:export
  2. 导入:import

9 扩展运算符...#

用三个点(…)可以将数组或对象展开成分散的值。

const boys = ['张三', '李四', '王五']
// 声明一个函数
function show() {
console.log(arguments)
}
show(...boys) // ['张三', '李四', '王五']
// 案例:合并数组
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr = [...arr1, ...arr2]
console.log(arr) // [1, 2, 3, 4, 5, 6]

10 简化对象声明#

可以直接写属性名,而无需写键和值。

let name = '张三'
let change = function () {
console.log('这是一个方法')
}
const sch = {
// 1. 定义对象的简写形式
// 2. 省略了属性值和冒号
name, // 旧版 name: name
change, // 旧版 change: change
// 3.方法前面省略了function关键字
improve() {
// 旧版improve: function() {
console.log('这是一个方法')
},
}
console.log(sch)

11 rest 参数#

rest参数获取剩余的所有参数,只能放在最后,返回一个参数数组

function date1(...args) {
console.log(args)
}
date1('2021-10-10', '2021-10-11', '2021-10-12') // 得到的是数组

12 生成器函数#

通过 function*yield 关键字实现的一种可暂停和恢复执行的函数。

写法的特殊地方就是需要加个 * 星号,靠左,靠右,中间都行

function* gen() {
console.log('hello generator')
}
let iterator = gen()
console.log(iterator)

yield可以看成是函数代码的分隔符,通过next方法来控制执行

function* gen() {
console.log('111')
yield '我是1' // yield为函数代码的分隔符
console.log('222')
yield '我是2'
console.log('333')
yield '我是3'
console.log('444')
}
let iterator = gen()
console.log(iterator)
iterator.next() // 111
iterator.next() // 222
iterator.next() // 333
iterator.next() // 444

生成器参考

function* gen(arg) {
console.log(arg)
let re1 = yield 111
console.log(re1)
let re2 = yield 222
console.log(re2)
let re3 = yield 333
console.log(re3)
}
// 执行获取迭代器对象
let iterator = gen('AAA')
console.log(iterator.next())
// next方法可以传入实参
console.log(iterator.next('BBB')) // 第二次调用传入的参数,将作为第一个yield语句的返回结果
console.log(iterator.next('CCC')) // 第三次调用传入的参数,将作为第二个yield语句的返回结果
console.log(iterator.next('DDD')) // 第四次调用传入的参数,将作为第三个yield语句的返回结果

解决地狱回调

// 地狱回调
setTimeout(() => {
console.log(111)
setTimeout(() => {
console.log(222)
setTimeout(() => {
console.log(333)
}, 3000)
}, 2000)
}, 1000)
// 解决后
function one() {
setTimeout(() => {
console.log(111)
iterator.next() // 执行下一个任务
}, 1000)
}
function two() {
setTimeout(() => {
console.log(222)
iterator.next()
}, 2000)
}
function three() {
setTimeout(() => {
console.log(333)
iterator.next()
}, 3000)
}
// 定义生成器函数
function* gen() {
yield one()
yield two()
yield three()
}
// 调用生成器函数
let iterator = gen()
iterator.next()

13 Map和Set#

新的数据结构,提供了更方便的数据存储和操作方式。

Map 键值对集合#

let myMap = new Map()
// 添加键值对(元素)
myMap.set('name', '张三')
myMap.set('age', 18)
let key = {
school: 'university',
}
myMap.set(key, ['清华大学', '北京大学'])
console.log(myMap)
// 获取Map中的元素个数
console.log(myMap.size)
// 删除元素
myMap.delete('age')
console.log(myMap)
// 获取元素
console.log(myMap.get('name'))
console.log(myMap.get(key))
// 判断Map中是否存在某个元素
console.log(myMap.has('name'))
console.log(myMap.has('age'))
// 遍历Map
for (let v of myMap) {
console.log(v)
}
// 清空Map
myMap.clear()
console.log(myMap)

Set 不重复集合#

let mySet = new Set()
console.log(mySet)
console.log(typeof mySet)
let mySet2 = new Set(['好事', '坏事', '大事', '好事']) // 自动去重
console.log(mySet2)
// 元素个数
console.log(mySet2.size)
// 添加元素
mySet2.add('小事')
console.log(mySet2)
// 删除元素
mySet2.delete('坏事')
console.log(mySet2)
// 检测是否有该元素
console.log(mySet2.has('大事')) // 返回结果是boolean类型
// 清空set
mySet2.clear()
console.log(mySet2)
// 遍历Set: 集合实现了iterator接口,所以可以使用for...of进行遍历
for (let item of mySet2) {
console.log(item)
}

14 Symbol#

ES6(ECMAScript 2015)引入了一种新的原始数据类型 Symbol。Symbol 是一种独一无二且不可变的数据类型,每个通过 Symbol 函数创建的 Symbol 值都是唯一的,即使符号名相同也不会相等。Symbol 主要用于对象属性的标识符,可以作为对象的属性名,用来解决属性名冲突的问题。

下面是 Symbol 的一些特点和用法:

  1. 独一无二性:每个 Symbol 值都是唯一的,不会与其他的 Symbol 值相等。这使得 Symbol 可以用作对象的属性名,保证属性的唯一性。

  2. 不可改变性:Symbol 是不可变的,一旦创建就不能修改其值。

  3. Symbol 作为对象属性名:使用 Symbol 作为对象的属性名,可以确保属性不会被意外覆盖。可以通过 Symbol() 方法创建一个 Symbol 值,然后作为属性名定义在对象中。

  4. 内置 Symbol 值:ES6 提供了一些预定义好的 Symbol 值,如 Symbol.iteratorSymbol.toStringTag 等,用于标识特定行为,可以在对象上使用这些 Symbol 值进行定制。

  5. Symbol.for() 和 Symbol.keyFor():ES6 还提供了两个与全局 Symbol 相关的静态方法 Symbol.for() 和 Symbol.keyFor()。Symbol.for() 方法接收一个字符串作为参数,如果存在相同字符串的 Symbol 值则返回,否则新建一个;Symbol.keyFor() 方法则是返回与 Symbol 关联的键。

// 1. 创建Symbol
let s = Symbol()
console.log(s, typeof s) // Symbol() 'symbol'
// 2. 每一个都是独一无二的
let s2 = Symbol('张三')
let s3 = Symbol('张三')
console.log(s2, s3)
console.log(s2 === s3) // false
// 3. Symbol.for 创建可以得出相同值
let s4 = Symbol.for('李四')
let s5 = Symbol.for('李四')
console.log(s4, s5)
console.log(s4 === s5) // true
// 4. 作为对象属性
let info = {
name: '张三',
[Symbol('age')]: 20,
[Symbol('say')]: function () {
console.log('我要说话了!')
},
}

15 迭代器#

ES6 引入了迭代器(Iterator)的概念,迭代器是一种能够让我们遍历数据结构的方法。通过迭代器,我们可以按照特定顺序逐个访问数据结构中的元素,而不必关心数据结构的具体实现细节。

下面是关于 ES6 迭代器的一些重要信息和特点:

  1. 迭代器协议:ES6 迭代器是基于迭代器协议(Iterator Protocol)实现的,在一个对象上部署了 Symbol.iterator 方法,该对象就被视为可迭代对象(iterable),可以通过迭代器进行遍历。

  2. 迭代器对象:迭代器对象必须具有一个 next() 方法,每次调用 next() 方法后都会返回一个包含 value 和 done 两个属性的对象,value 表示下一个元素的值,done 表示是否遍历结束。

  3. 可迭代对象:实现了迭代器协议的对象被称为可迭代对象,例如数组、字符串、Map、Set 和自定义对象等,它们可以通过 for…of 循环、展开运算符(…)、解构赋值等方式进行遍历。

  4. Symbol.iterator 方法:可迭代对象都会具有一个 Symbol.iterator 方法,调用该方法会返回一个迭代器对象,从而实现迭代访问。

  5. for…of 循环:ES6 引入的 for…of 循环可以遍历可迭代对象,自动调用迭代器的 next() 方法,简化了遍历操作。

  6. 内置数据结构:ES6 的内置数据结构如数组、Map、Set 等都实现了迭代器协议,因此可以直接使用 for…of 循环来遍历这些数据结构。

迭代器工作原理:

  1. 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。

  2. 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。

  3. 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。

  4. 不断调用指针对象的next方法,直到它指向数据结构的结束位置。

  5. 每一次调用next方法都会返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。

// 1. for...of
const arr = [1, 2, 3, 4, 5]
for (let element of arr) {
console.log(element)
// 输出:1 2 3 4 5
}
// 2. 迭代器
const arr = [1, 2, 3, 4, 5]
let iterator = arr[Symbol.iterator]()
console.log(iterator.next()) // { value: 1, done: false }
console.log(iterator.next()) // { value: 2, done: false }
console.log(iterator.next()) // { value: 3, done: false }
console.log(iterator.next()) // { value: 4, done: false }
console.log(iterator.next()) // { value: 5, done: false }
console.log(iterator.next()) // { value: undefined, done: true }
// 3. 自定义迭代器
// 声明一个对象
const banji = {
name: '终极一班',
stus: ['xiaoming', 'xiaoning', 'xiaotian', 'knight'],
[Symbol.iterator]() {
// 索引变量
let index = 0
return {
next: () => {
if (index < this.stus.length) {
// 构建一个yield返回值
const result = {value: this.stus[index], done: false}
// 下标自增
index++
return result
}
// 返回结束标志
return {value: undefined, done: true}
},
}
},
}
for (let v of banji) {
console.log(v)
}

16 数值扩展#

  1. Number.EPSILON 是JavaScript表示的最小精度, EPSILON 属性的值接近于 2.2204460492503131e-16
  2. 引入进制
  3. Number.isFinite()
  4. Number.isNaN()
  5. Number.parserInt()、Number.parseFloat(),将字符串转为整数(浮点数)
  6. Number.isInteger(),判断一个数是否为整数
  7. Math.trunc(),将数字的小数部分抹掉
  8. Math.sign(),判断一个数是正数、负数、还是零,返回:1,-1
// 1. EPSILON 属性的值接近于 2.2204460492503131e-16
function equal(a, b) {
if (Math.abs(a - b) < Number.EPSILON) {
return true
} else {
return false
}
}
console.log(0.1 + 0.2) // 0.30000000000004
console.log(0.1 + 0.2 === 0.3) // false
console.log(equal(0.1 + 0.2, 0.3)) // true
// 2. 二进制、八进制、十进制、十六进制
let b = 0b10
let o = 0o10
let d = 10
let x = 0x10
console.log(b, o, d, x) // 2 8 10 16
// 3. 判断极大数
function isFinite(num) {
return Number.isFinite(num)
}
console.log(isFinite(5)) // true
console.log(isFinite(5.0)) // true
console.log(isFinite(5.1)) // true
console.log(isFinite(Infinity)) // false
// 4. 判断NaN
function isNaN(num) {
return Number.isNaN(num)
}
console.log(isNaN(5)) // false
console.log(isNaN(NaN)) // true

17 对象方法扩展#

  1. Object.is 对象是否完全相等
  2. Object.assign 对象的合并
  3. Object.setPrototypeOf 设置原型对象
  4. Object.getPrototypeOf 获取原型对象

转化#

并不是所有的浏览器都能向chrome一样都能识别ES6新特性,所以需要进行转换

Terminal window
# 安装工具: babel-cli babel-preset-env browserify
npm i babel-cli babel-preset-env browserify -D
npx babel src/js -d dist/js --presets=babel-preset-env
npx browserify dist/js/app.js -o dist/bundle.js

参考#

ES6 新特性(0基础,精简版,学ES6看这篇就够了!!!)

ES6(ECMAScript 2015)

赞助支持

如果这篇文章对你有帮助,欢迎赞助支持!

赞助
ES6新特性
https://march7th.online/posts/0009-es6新特性/
作者
Yiguo
发布于
2024-06-04
许可协议
CC BY-NC-SA 4.0
最后更新于 2024-06-05,距今已过 561 天

部分内容可能已过时

目录