前言

本文大量参考了阮一峰老师的开源教程ECMAScript6入门和MDN,适合新手入门或者对ES6常用知识点进行全面回顾,目标是以较少的篇幅涵盖ES6及部分ES7在实践中的绝大多数使用场景。更全面、更深入的请进入上面的教程。如果您觉得有遗漏的常见知识点或者错误的地方,请评论指出!

新的变量声明方式let和const

是什么:

新的变量声明方式,提供变量的块级作用域,同时通过一些限制来更防止我们犯错误。也就是说是更好的声明变量的方式

怎么用

1)let/const与var的区别是提供了块级作用域以及变量创建时不会立即初始化

2)在同一个作用域内let/const禁止重复声明相同的变量

var a = 1
let a = 2 // SyntaxError

3)let声明的变量可重新赋值,const声明的变量不能重新赋值,即常量。

4)暂时性死区:在当前作用域,使用的变量已经存在,但是在代码执行到变量声明前禁止访问。

var tmp = 123

if (true) {
tmp = 'abc' // ReferenceError
let tmp
}

常见使用场景

1)因为能创建块级作用域,所以常见于if和for中

for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}

2)const在实践中常用来声明一个对象,之后可以再对这个对象的属性进行修改

const foo = {
name: 'bar'
} foo.name = 'baz' console.log(foo)

解构

是什么:

按照阮一峰大神的说法:ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。也就是说通过模式匹配来进行变量赋值。

怎么用:

1)数组基本用法

let [a, b, c] = [1, 2, 3]

a //1
b //2
c //3

2)对象基本用法

let { foo, bar } = { foo: "aaa", bar: "bbb" }
foo // "aaa"
bar // "bbb"

3)函数参数的解构赋值

如在vuex中action不使用解构如下:

actions: {
increment (context) {
context.commit('increment')
}
}

使用解构

actions: {
increment ({ commit }) {
commit('increment')
}
}

4)支持不完全解构

let [foo, bar] = [1, 2, 3]

5)如果解构不成功,变量的值就等于undefined,同时解构赋值允许指定默认值,默认值生效的条件是对象的属性值严格等于undefined。

常见使用场景

1)交换变量的值

[x, y] = [y, x]

2)提取JSON数据

let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
} let { id, status, data: number } = jsonData console.log(id, status, number) // 42, "OK", [867, 5309]

3)函数参数的默认值

jQuery.ajax = function (url, {
async = true,
beforeSend = function () {},
cache = true,
complete = function () {},
crossDomain = false,
global = true,
// ... more config
}) {
// ... do stuff
}

4)指定加载模块的什么功能

import { mapActions } from 'vuex'

箭头函数

干嘛的:

箭头函数可以用来替换函数表达式,不用写function,更加简化。也就是说是函数表达式的简化方式

怎么用:

1)注意箭头函数中的this指向外层的this

2)无法用call/apply/bind来改变this指向。

3)在ES6中,会默认采用严格模式,因此默认情况下this不是指向window对象,而是undefined。

<script type="text/javascript">
setTimeout(() => console.log(this), 1000) // undefined,不是window
</script>

4)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。

使用场景:

关键是你需要this指向什么

默认参数和rest参数

是什么:

默认参数就是设置参数默认值,rest参数(翻译为不具名参数,也叫做剩余参数)是将传入的未具名的参数作为一个数组集合

怎么用:

如下,默认参数给参数赋一个默认值,rest参数使用三个点(...)加数组集合名

function foo(arg1 = 1, ...restArg){
console.log(arg1, restArg)
} foo(undefined, 2, 3, 4) // 1, [2, 3, 4] foo(2, 3, 4) // 2, [3, 4]

扩展运算符

是什么:

同rest参数一样,也是三个点。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。因此常用于函数调用。

常见使用场景:

1)合并数组

let newArr = [...arr1, ...arr2, ...arr3]

2)与解构赋值结合

// ES5
a = list[0], rest = list.slice(1) // ES6
[a, ...rest] = list

3)将字符串转为数组

[...'test'] // [ "t", "e", "s", "t"]

对象扩展

语法变化

1)属性简写,当对象的一个属性名称与本地变量名相同的时候,可以省略冒号和值

var foo = 'bar'
var baz = {foo}
baz // {foo: "bar"}

2)属性名表达式,可以在以对象字面量方式定义对象是使用表达式作为属性名

// ES5只能这样
obj['a' + 'bc'] = 123 // ES6还能这样
let obj = {
['a' + 'bc']: 123
}

3)方法简写,省去:和function

const foo = {
bar () {
console.log('1')
}
}

Object.is()

更好的判断方法,与===的不同有两点:一是+0不等于-0,二是NaN等于自身。

NaN === NaN // false
Object.is(NaN, NaN) // true

Object.assign()

1)Object.assign方法用于对象的合并,用法与jQuery和underscore的extend方法类似,而且同样会改变target。

Object.assign(target, source1, source2)

2)只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。

3)Object.assign方法实行的是浅拷贝,而不是深拷贝。

Object.setPrototypeOf

用来设置一个对象的prototype对象,返回参数对象本身

Object.setPrototypeOf(object, prototype)

Object.getPrototypeOf()

Object.getPrototypeOf方法可以用来从子类上获取父类。因此,可以使用这个方法判断,一个类是否继承了另一个类。参见下面类与继承章节

遍历

对象的每个属性都有一个描述对象(Descriptor),Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。这个描述对象有value、writable、enumerable、configurable四大属性。

ES5下面三个操作会忽略enumerable为false的属性。

  • for...in循环:只遍历对象自身的和继承的可枚举的属性
  • Object.keys():返回对象自身的所有可枚举的属性的键名
  • JSON.stringify():只串行化对象自身的可枚举的属性

ES6新增的操作Object.assign(),也会忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。

ES6一共有5种方法可以遍历对象的属性。

(1)for...in

for...in循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。

(2)Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。

(3)Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。

(4)Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性。

(5)Reflect.ownKeys(obj)

Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举。

以上的5种方法遍历对象的属性,都遵守同样的属性遍历的次序规则。

  • 首先遍历所有属性名为数值的属性,按照数字排序。
  • 其次遍历所有属性名为字符串的属性,按照生成时间排序。
  • 最后遍历所有属性名为Symbol值的属性,按照生成时间排序。

大多数时候,我们只关心对象自身的可枚举属性。所以,尽量不要用for...in循环,而用Object.keys()代替。

字符串扩展

以前判断一个字符串是否包含某个字符串只能通过indexOf的值是否大于-1来判断,现在新增了三种方法:

includes():表示是否包含该字符串。

startsWith():表示该字符串是否在头部。

endsWith():表示该字符串是否在尾部。

'hello world'.includes('hello') // true

模板字符串

干嘛的:

和handlebars那些模板引擎功能类似,有模板字符串可以不用拼接字符串了

怎么用:

用反引号``将整个字符串包裹起来,${}表示一个变量或者一个表达式,可以嵌套

const tmpl = addrs => `
<table>
${addrs.map(addr => `
<tr><td>${addr.first}</td></tr>
<tr><td>${addr.last}</td></tr>
`).join('')}
</table>
` const data = [
{ first: 'Jane', last: 'Bond' },
{ first: 'Lars', last: 'Croft' },
] console.log(tmpl(data))

标签模板

函数名后面紧接一个模板字符串。该函数将被调用来处理这个模板字符串。这被称为“标签模板”功能(tagged template)。当字符串模板有变量时,函数的第一个参数为被变量分开的字符串组成的数组,后面的参数依次为变量,这些变量的参数序列可以使用rest参数。

var a = 5
var b = 10 tag`Hello ${ a + b } world ${ a * b }`
// 等同于
tag(['Hello ', ' world ', ''], 15, 50)

数组扩展

Array.of()

Array.of方法用于将一组值,转换为数组。可以替代Array,且其行为非常统一,不像Array只有一个正整数参数n时,会生成n个空位构成的数组

Array.of(1) // [1]
Array.of(1, 2, 3) // [1, 2, 3]
Array(1) // [undefined * 1],其实不是undefined,是空位,如下可证明两者并不一样
0 in [undefined, undefined, undefined] // true
0 in [, , ,] // false
Array(1, 2, 3) // [1, 2, 3]

Array.from()

Array.from方法用于将两类对象转为真正的数组:类数组对象(array-like object)和可遍历(iterable)对象(包括ES6新增的数据结构Set和Map)。Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。

Array.from({'0': 'a', length: 1}) // ['a']

Array.from('hello') // ['h', 'e', 'l', 'l', 'o'],因为字符串有Iterator接口,可遍历

Array.from([1, 2, 3], (x) => x * x) // [1, 4, 9]

常见使用场景:

1)转换NodeList集合。常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象。但是后者使用rest参数更简便

// NodeList对象
let elementDivList = document.querySelectorAll('div')
Array.from(elementDivList).forEach(function (div) {
console.log(div)
})

2)数组去重。与下面要讲到的Set配合即可很简单地实现数值去重。

var arr = [1, 3, 5, 5, 8, 3, 2]
var uniqueArr = Array.from(new Set(arr))
console.log(uniqueArr) // [1, 3, 5, 8, 2]

数组实例的copyWithin方法

Array.prototype.copyWithin(target, start = 0, end = this.length)

它接受三个参数。

  • target(必需):从该位置开始替换数据。
  • start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。
  • end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
	[1, 2, 3, 4, 5].copyWithin(0,2) // [3, 4, 5, 4, 5]
/* 从索引2开始读取数据,到数组尾部停止,即读到(3, 4, 5),然后从索引0开始替换数据 */

数组实例的find和findIndex方法

找到第一个符合条件的item(项)或index(索引),前者相当于underscore中的first方法,后者则和underscore中的同名方法一致。另外,这两个方法都可以借助Object.is发现NaN,弥补了数组的IndexOf方法的不足。

[1, 2, 3, 4].find(x => x > 2) // 3
[1, 2, 3, 4].findIndex(x => x > 2) // 2
[NaN].findIndex(x => Object.is(NaN, x)) // 0

数组实例的fill方法

Array.prototype.fill(fillItem, start = 0, end = this.length)

[1, 3, 6, 11, 4].fill(10,2) // [1, 3, 10, 10, 10]

数组实例的includes方法

与字符串的includes方法类似。该方法属于ES7,但Babel转码器已经支持。

[1, 2, 3].includes(3, 3) // false
[1, 2, 3].includes(3, -1) // true
[NaN].includes(NaN) // true

Set和Map

ES6中增加了两个新的数据结构:Set和Map。Set是不包含重复值的列表,而Map则是键与相对应的值的集合。

Set

是什么:

Set是不包含重复值的有序列表。

怎么用:

1)Set构造函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。

const set = new Set([1, 2, 3, 4, 4])
console.log(set)

2)四个操作方法(add()、delete()、has()、clear())和一个属性(size),使用方法根据名字和下面例子就知道了

const s = new Set()
s.add(1).add(2).add(2) // 注意2被add了两次 s.size // 2 s.has(1) // true
s.has(2) // true
s.has(3) // false s.delete(2)
s.has(2) // false s.add(3)
s.size // 2 s.clear()
s.size // 0

3)三个遍历器生成函数(keys()、values()、entries())和一个遍历方法(forEach())

keys方法、values方法、entries方法返回的都是遍历器对象(详见Iterator)。都这可以使用遍历器对象的方法for...of进行遍历。由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。forEach方法与ES5数组的forEach类似。

let set = new Set(['red', 'green', 'blue'])

for (let item of set.keys()) {
console.log(item)
}
// red
// green
// blue for (let item of set.values()) {
console.log(item)
}
// red
// green
// blue for (let item of set.entries()) {
console.log(item)
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"] set.forEach((value, key) => console.log(value, key))

4)Set转化为数组,有两种方法:...扩展运算符和Array.from()

这两者可互换,因此前面提到的使用Array.from()来数组去重也可以这样做:[...new Set(arr)]

// 方法一
let set = new Set([1, 2, 3])
set = new Set([...set].map(val => val * 2))
// set的值是2, 4, 6 // 方法二
let set = new Set([1, 2, 3])
set = new Set(Array.from(set, val => val * 2))
// set的值是2, 4, 6

Map

是什么:

一种由键值对集合构成的数据结构,类似于对象,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

const m = new Map();
const o = {p: 'Hello World'}; m.set(o, 'content')
m.get(o) // "content"

怎么用:

1)Set构造函数可以接收任何一个具有Iterator接口的数据结构作为参数

const set = new Set([
['foo', 1],
['bar', 2]
])
const m1 = new Map(set)
m1.get('foo') // 1

2)5个操作方法(set(key, value)、get(key)、has(key)、delete(key)、clear())和一个属性(size)

3)遍历生成函数和遍历方法和Set类似,Map结构的默认遍历器接口(Symbol.iterator属性),就是entries方法。

map[Symbol.iterator] === map.entries // true

4)Map转为数组,使用...扩展运算符

WeakSet和WeakMap

WeakSet、WeakMap分别和Set、Map类似,不过存储的是对象的弱引用方式,这样在内存管理上更加容易优化。

ES6核心内容精讲--快速实践ES6(一)的更多相关文章

  1. ES6核心内容精讲--快速实践ES6(二)

    Iterator和for...of 是什么: Iterator(遍历器)是专门用来控制如何遍历的对象,具有特殊的接口. 怎么用: Iterator(遍历器)对象带有next方法,每一次调用next方法 ...

  2. ES6核心内容精讲--快速实践ES6(三)

    Promise 是什么 Promise是异步编程的一种解决方案.Promise对象表示了异步操作的最终状态(完成或失败)和返回的结果. 其实我们在jQuery的ajax中已经见识了部分Promise的 ...

  3. ES6核心内容讲解

    ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015. 也就是说,ES6就是ES2015. ...

  4. ES6/ES2015核心内容

    ECMAScript定义了: JS语言语法 – 语法解析规则.关键字.语句.声明.运算符等. 类型 – 布尔型.数字.字符串.对象等. 原型和继承 内建对象和函数的标准库 – JSON.Math.数组 ...

  5. 30分钟掌握ES6/ES2015核心内容

    30分钟掌握ES6/ES2015核心内容   ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript ...

  6. ES6核心特性

    摘要:聊JS离不开ES6啊! 原文:ES6核心特性 作者:ljianshu 前言 ES6 虽提供了许多新特性,但我们实际工作中用到频率较高并不多,根据二八法则,我们应该用百分之八十的精力和时间,好好专 ...

  7. 30分钟掌握ES6/ES2015核心内容(下)

    在 30分钟掌握ES6/ES2015核心内容(上)我们讲解了es6最常用的一些语法:let, const, class, extends, super, arrow functions, templa ...

  8. linux驱动开发重点关注内容--摘自《嵌入式Linux驱动模板精讲与项目实践》

    本文摘自本人拙著 <嵌入式Linux驱动模板精讲与项目实践> 初步看起来Linux设备驱动开发涉及内容非常多,而须要实现驱动的设备千差万别.事实上做一段时间驱动之后回首看来主要就是下面几点 ...

  9. TypeScript完全解读(26课时)_7.ES6精讲 - 类Class基础

    ES6精讲 - 类Class基础 es5中创建构造函数和实例 原来在es5中的写法 定义好Point后,在原型对象上定义getPostion的方法 实例自身是没有这个方法的,我们调用的时候会去创建他的 ...

随机推荐

  1. Android Studio查找功能(搜索功能)及快捷键

    版权声明:本文为博主原创文章,未经博主允许不得转载. 1.在当前窗口查找文本[Ctrl+F] F3                  向下查找关键字出现位置 Shift+F3        向上一个关 ...

  2. my first blogs(我的处女博)

    末夏的夕阳送走一批批下班的人,些许的轻风给一天烦躁的心带来一丝丝的清凉.我倒是挺喜欢在这种天气,提前下了公交车然后漫步回家.这样我能多点时间回顾一天的事情,俗话说是思考人生. 不知不觉毕业两年多了,在 ...

  3. Hibernate(四)之对象状态及一级缓存

    一.Hibernate中的对象状态 1.1.瞬时态(临时态) 没有与Hibernate产生关联 与数据库中的记录没有产生关联(有关联就是与数据库中表的id相对应) 获得:一般都只直接创建(new) 瞬 ...

  4. 使用express创建新应用的骨架

    通过应用生成器工具 express 可以快速创建一个应用的骨架. 通过如下命令安装: $ npm install express-generator -g -h 选项可以列出所有可用的命令行选项: $ ...

  5. 1136: 零起点学算法43——多组测试数据输出I

    1136: 零起点学算法43--多组测试数据输出I Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lldSubmitted: ...

  6. 【G】开源的分布式部署解决方案文档 - 部署Console & 控制负载均衡 & 跳转持续集成控制台

    G.系列导航 [G]开源的分布式部署解决方案 - 导航 设置项目部署流程 项目类型:选择Console,这个跟功能无关,只是做项目分类,后面会有后续功能 宿主:选择Console 部署方式:选择原始, ...

  7. Android系统--输入系统(六)模拟输入驱动程序

    Android系统--输入系统(六)模拟输入驱动程序 1. 回顾输入子系统 简单字符设备驱动:应用程序通过调用驱动所实现的函数使能硬件. 输入子系统:由于有多个应用程序使用输入子系统,故肯定使用的是早 ...

  8. view测量

    一.测规格是由测量模式mode和测量大小size组成的,size好说,那测量模式mode代表什么含义呢.由上面的代码可知,测量模式有三类:    UNSPECIFIED    父控件不对你有任何限制, ...

  9. java 解析xml文档---通过XmlPullParser解析方式

    package com.zx; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayLi ...

  10. 不须组件的NPOI插件 excel读取

    前提: 需要DLL  1.引用 using NPOI.SS.UserModel; using NPOI.XSSF.UserModel;//用于2007版本 using NPOI.HSSF.UserMo ...