一、ES6 函数
(一)函数参数的扩展
1. 默认参数
function log(x, y = 'World') {
console.log(x, y)
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
复制代码
2. 剩余参数
function f(...values){
console.log(values.length)
}
f(1,2) //2
f(1,2,3,4) //4
复制代码
(二)箭头函数
1. 基本用法
//ES5
var f = function (a,b) {
return a+b
}
//ES6
var f = (a,b) => {
return a+b
}
复制代码
2. 注意点
- 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
- 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
- 不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
3. 不适合使用的场景
- 定义函数的方法,且该方法中包含 this
- 需要动态 this 的时候
二、ES6遍历器(迭代器)
(一)Iterator
遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
1. 遍历过程
- 通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置
- 随后通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象,对象包含了 value 和 done 两个属性, value 是当前属性的值, done 用于判断是否遍历结束
- 当 done 为 true 时则遍历结束
let arr = ['a', 'b', 'c']
let iter = arr[Symbol.iterator]()
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
复制代码
2. 可迭代的数据结构
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
(二)for...of
for...of 是 ES6 新引入的循环,用于替代 for..in 和 forEach() ,并且支持新的迭代协议。它可用于迭代常规的数据类型,如数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、Generator 对象以及字符串。
三、ES6 Class 类
(一)class类
class Point {
constructor(x, y) {
this.x = x
this.y = y
}
toString() {
return '(' + this.x + ', ' + this.y + ')'
}
}
复制代码
1. constructor
方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
2. 类的实例
生成类的实例的写法,与 ES5 完全一样,也是使用new命令。
class Point {
// ...
}
var point = new Point(2, 3)
复制代码
3. 取值函数(getter)和存值函数(setter)
在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
class Point {
constructor(x = 1) {
this.x = x
}
get xx() {
return this.x
}
set xx(val) {
this.x = val
}
}
const point = new Point()
point.xx = 99
console.log(point.x) //99
复制代码
4. 静态方法
如果在一个方法前,加上static关键字,就表示该方法不会被实例继承。
class Foo {
static classMethod() {
return 'hello'
}
}
Foo.classMethod() // 'hello'
var foo = new Foo()
foo.classMethod()
// TypeError: foo.classMethod is not a function
复制代码
父类的静态方法,可以被子类继承。
class Foo {
static classMethod() {
return 'hello'
}
}
class Bar extends Foo {
}
Bar.classMethod() // 'hello'
复制代码
5. 实例属性的新写法
实例属性除了定义在constructor()方法里面的this上面,也可以定义在类的最顶层。
class foo {
bar = 'hello'
baz = 'world'
constructor() {
// ...
}
}
复制代码
(二)extends继承
1. extends
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y) // 调用父类的constructor(x, y)
this.color = color
}
toString() {
return this.color + ' ' + super.toString() // 调用父类的toString()
}
}
复制代码
2. Object.getPrototypeOf()
Object.getPrototypeOf方法可以用来从子类上获取父类。
3. super 关键字
- super作为函数调用时,代表父类的构造函数。ES6要求,子类的构造函数必须执行一次super函数。
class A {}
class B extends A {
constructor() {
super()
}
}
复制代码
- super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
class A {
p() {
return 2
}
}
class B extends A {
constructor() {
super()
console.log(super.p()) // 2
}
}
let b = new B()
复制代码
-
原生构造函数的继承
ECMAScript 的原生构造函数大致有下面这些:
- Boolean()
- Number()
- String()
- Array()
- Date()
- Function()
- RegExp()
- Error()
- Object()
四、ES6 模块
(一)export 与 import
1. 基本用法
- 导出的函数声明与类声明必须要有名称(export default 命令另外考虑)。
- 不仅能导出声明还能导出引用(例如函数)。
- export 命令可以出现在模块的任何位置,但必需处于模块顶层。
- import 命令会提升到整个模块的头部,首先执行。
/*-----export [test.js]-----*/
let myName = "Tom"
let myAge = 20
let myfn = function(){
return "My name is" + myName + "! I'm '" + myAge + "years old."
}
let myClass = class myClass {
static a = "yeah!"
}
export { myName, myAge, myfn, myClass }
/*-----import [xxx.js]-----*/
import { myName, myAge, myfn, myClass } from "./test.js"
console.log(myfn())// My name is Tom! I'm 20 years old.
console.log(myAge)// 20
console.log(myName)// Tom
console.log(myClass.a )// yeah!
复制代码
2. as 的用法
export 命令导出的接口名称,须和模块内部的变量有一一对应关系。
导入的变量名,须和导出的接口名称相同,即顺序可以不一致。
/*-----export [test.js]-----*/
let myName = "Tom"
export { myName as exportName }
/*-----import [xxx.js]-----*/
import { exportName } from "./test.js"
console.log(exportName)// Tom
使用 as 重新定义导出的接口名称,隐藏模块内部的变量
/*-----export [test1.js]-----*/
let myName = "Tom"
export { myName }
/*-----export [test2.js]-----*/
let myName = "Jerry"
export { myName }
/*-----import [xxx.js]-----*/
import { myName as name1 } from "./test1.js"
import { myName as name2 } from "./test2.js"
console.log(name1)// Tom
console.log(name2)// Jerry
复制代码
(二)import 命令的特点
- 只读属性:不允许在加载模块的脚本里面,改写接口的引用指向,即可以改写 import 变量类型为对象的属性值,不能改写 import 变量类型为基本类型的值。
import {a} from "./xxx.js"
a = {} // error
import {a} from "./xxx.js"
a.foo = "hello" // a = { foo : 'hello' }
复制代码
- 单例模式:多次重复执行同一句 import 语句,那么只会执行一次,而不会执行多次。import 同一模块,声明不同接口引用,会声明对应变量,但只执行一次 import 。
import { a } "./xxx.js"
import { a } "./xxx.js"
// 相当于 import { a } "./xxx.js"
import { a } from "./xxx.js"
import { b } from "./xxx.js"
// 相当于 import { a, b } from "./xxx.js"
复制代码
- 静态执行特性:import 是静态执行,所以不能使用表达式和变量。
import { "f" + "oo" } from "methods"
// error
let module = "methods"
import { foo } from module
// error
if (true) {
import { foo } from "method1"
} else {
import { foo } from "method2"
}
// error
复制代码
(三)export default 命令
- 在一个文件或模块中,export、import 可以有多个,export default 仅有一个。
- export default 中的 default 是对应的导出接口变量。
- 通过 export 方式导出,在导入时要加{ },export default 则不需要。
- export default 向外暴露的成员,可以使用任意变量来接收。
var a = "My name is Tom!"
export default a
export default var c = "error"
// error,default 已经是对应的导出变量,不能跟着变量声明语句
import b from "./xxx.js" // 不需要加{}, 使用任意变量接收
复制代码
转载于:https://juejin.im/post/5cf7668b6fb9a07efe2daaf5