变量的解构赋值
1. 数组的解构赋值
const [, b] = [1, 2, 3, 4]
console.log(b) // 2
const [a] = [[1, 2], 3]
console.log(a) // [1, 2]
const [foo = true] = []
console.log(foo) // true
const [c, d = 'world'] = ['hello']
console.log(c, d) // hello world
const [e = 'world'] = [undefined]
console.log(e) // world
const [f = 'world'] = [null]
console.log(f) // null
2. 对象的解构赋值
const { sex, age } = { name: '张三', sex: '男' }
console.log(sex) // 男
console.log(age) // undefined
const { foo: baz } = { foo: 'aaa', baz: 'bbb' }
console.log(baz) // aaa
console.log(foo) // error: foo is not defined
const { x: z = 3 } = {}
console.log(x, z) // undefined 3
const { x: w = 3 } = { x: 5 }
console.log(x, w) // undefined 5
const { m = 3 } = { m: undefined }
console.log(m) // undefined
const { n = 3 } = { n: null }
console.log(n) // null
const obj = {
p: [
'hello',
{ y: 'world' },
]
}
const { p: [x, { y }] } = obj
console.log(x, y) // hello world
3. 字符串解构赋值
const [a, b, c, d, e] = 'hello'
console.log(a) // h
console.log(b) // e
console.log(c) // l
console.log(d) // l
console.log(e) // o
const { lenth: len } = 'hello'
console.log(len) // 5
4. 用途
交换变量的值:
let x = 3
let y = 5;
[x, y] = [y, x]
console.log(x, y) // 5 3
扩展运算符和rest运算符
1. 解决数组赋值只是堆栈引用的问题
const arr1 = ['www', 'baidu', 'com']
const arr2 = [...arr1]
arr2.push('hh')
console.log(arr1) // ["www", "baidu", "com"]
console.log(arr2) // ["www", "baidu", "com", "hh"]
2. 求数组最大的值
// ES5
const a = Math.max.apply(null, [44, 2, 77]) // 第一个参数:null,第二个参数:数组
console.log(a) // 77
// ES6
const b = Math.max(...[44, 2, 77])
console.log(b) // 77
3. 将一个数组添加到另一个数组尾部
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
// ES5
Array.prototype.push.apply(arr1, arr2)
console.log(arr1) // [1, 2, 3, 4, 5, 6]
// ES6
arr1.push(...[arr2])
console.log(arr1) // [1, 2, 3, 4, 5, 6]
4. 合并数组
const arr1 = [1, 2]
const arr2 = [3]
const arr3 = [5, 6]
// ES5
const arr4 = arr1.concat(arr2, arr3)
console.log(arr4) // [1, 2, 3, 5, 6]
// ES6
const arr5 = [...arr1, ...arr2, ...arr3]
console.log(arr5) // [1, 2, 3, 5, 6]
5. 扩展运算符与解构赋值(rest)结合
const arr1 = [1, 2, 3, 4, 5]
// ES5
const a = arr1[0]
const rest = arr1.slice(1)
console.log(a) // 1
console.log(rest) // [2, 3, 4, 5]
// ES6
const [first, ...list] = arr1
console.log(first) // 1
console.log(list) // [2, 3, 4, 5]
扩展运算符用于数组,只能用于最后一个参数,否则报错
const [...first, list] = arr1 // error
字符串新增方法
- String.fromCharCode(0x2bbbbb) 用于Unicode码返回对应的字符
- Str. codePointAt(ind) 能够正确处理4个字节储存的字符,返回一个字符的码点。
- Includes() 一个字符串是否包含在另一个字符串中,返回Boolean
- startsWith() 参数字符串是否包含在另一个字符串头部,返回Boolean
- endsWith() 参数字符串是否包含着另一个字符串尾部,返回Boolean
- repeat(num) 返回一个新字符串,表示将原字符串重复n次,如果是小数,会被向下取整,如果是小于-1的负数则报错,如果是0至-1之间的小数等同于0,返回空字符串,NaN等同于0,字符串先转为数字
var str = 'na'
console.log(str.repeat(2)) // nana
console.log(str.repeat(-0.3)) // ''
console.log(str.repeat(NaN)) // ''
console.log(str.repeat('he')) // ''
console.log(str.repeat('3')) // nanana
console.log(str.repeat(-1)) // RangeError: Invalid count value
- padStart() 长度补全功能,头部补全
- padEnd() 长度补全功能,尾部补全
padStart 、padEnd接收两个参数,参数一:补全的最大参数,参二:用来补全的字符串
console.log('x'.padStart(5, 'ab')) // ababx
console.log('x'.padEnd(4, 'ab')) // xaba
如果原字符串长度等于或大于补全的字符串长度,则补全不生效,返回原字符串
console.log('xxx'.padStart(2, 'ab')) // xxx
console.log('xxx'.padEnd(2, 'ab')) // xxx
如果原字符串+补全字符串的长度超过最大长度,则截去超出的补全字符串
console.log('xxx'.padStart(6, 'abcdefg')) // abcxxx
如果省略第二个参数,则用空字符串补全
console.log('xxx'.padStart(6)) // ' xxx'
- 消除字符串空格trim/ trimStart/ trimEnd
' abc '.trim() // 'abc'
' abc '.trimStart() // 'abc '
' abc '.trimEnd() // ' abc'
- replace 替换字符,只能替换第一个字符
'aabbcc'.replace('b', '_') // aa_bcc
要替换所有的字符,不得不使用正则表达式g修饰符
'aabbcc'.replace(/b/g, '_') // aa__cc
replaceAll () 可以一次性替换所有匹配字符串
'aabbcc'.replaceAll('b', '-') // aa--cc
- 数值扩展
1) Number.isNaN(NaN) 判断值是否为 NaN
2) parseInt 、parseFloat
ES6的目的是为了逐步减少全局方法,是语言逐步模块化
// ES5
console.log(parseInt(12.34)) // 12
console.log(parseFloat(12.34)) // 12.34
// ES6
console.log(Number.parseInt(13.32)) // 12
console.log(Number.parseFloat(13.32)) // 12.32
3)Number.isInteger()用来判断一个数值是否为整数
4)Math.trunc() 用来去除一个小数的小数部分,只返回整数部分
console.log(Math.trunc(3.3)) // 3
console.log(Math.trunc(3.8)) // 3
console.log(Math.trunc(true)) // 1
console.log(Math.trunc(false)) // 0
console.log(Math.trunc(NaN)) // NaN
console.log(Math.trunc('ab')) // NaN
console.log(Math.trunc()) // NaN
console.log(Math.trunc(undefined)) // NaN
5)Math.sign() 判断数值是正数、负数、还是0
正数:返回+1
负数:返回-1
参数0:返回0
参数-0:返回-0
如果参数是非数值,会自动转为数值,如果不能转成数值,则返回NaN
console.log(Math.sign(9)) // +1
console.log(Math.sign(-3)) // -1
console.log(Math.sign(0)) // 0
console.log(Math.sign(-0)) // -0
console.log(Math.sign(true)) // 1
console.log(Math.sign(false)) // 0
console.log(Math.sign(NaN)) // NaN
console.log(Math.sign(undefined)) // NaN
6)Math.cbrt() 用于计算一个数的立方根
console.log(Math.cbrt(8)) // 2
对象新增方法
1. Object.is() 比较两个值是否完全相等
Object.is()与=== 基本相等,不同之处只有两处:1. +0 不等于-0;2. NaN等于自身
2. Object.assign() 用于对象合并
var obj1 = { a: 11 }
var obj2 = { b: 22 }
var obj3 = { c: 33 }
Object.assign(obj1, obj2, obj3)
console.log(obj1) // {a: 11, b: 22, c: 33}
如果只有一个参数,会直接返回改参数
console.log(Object.assign(obj1) === obj1) // true
浅拷贝
var obj4 = { a: { b: 1 }}
var obj5 = Object.assign({}, obj4)
obj5.a.b = 22
console.log(obj5) // {a: {b: 22}}
console.log(obj4) // {a: {b: 22}}
var arr1 = [1, 2, 3, 4]
var arr2 = [5, 6]
Object.assign(arr1, arr2)
console.log(arr1) // [5, 6, 3, 4]
3. Object.keys() 返回数组,成员是参数对象的关键字
var obj1 = { a: 11, b: 22 }
Object.keys(obj1) // ["a", "b"]
4. Object.values() 返回数组,成员是参数对象的键值
var obj1 = { a: 11, b: 22 }
Object.values(obj1) // [11, 22]
5. Object.entries() 返回一个数组,成员是参数对象的键值对
var obj1 = { a: 11, b: 22 }
Object.entries(obj1) // [['a', 11], ['b', 22]]
6. Object.fromEntries() 是 Object.entries() 的逆方法,是将键值对数组转为对象
var arr = [['a', 11], ['b', 22]]
Object.fromEntries(arr) // {a: 11, b: 22}
7. 运算符扩展
指数运算符(**)
console.log(3 ** 2) // 9
Set 和 Map 方法
1. Set数据结构不会添加重复的值
var s = new Set()
var arr = [2, 3, 5, 4, 5, 2, 2]
arr.forEach(i => s.add(i))
console.log(s) // {2, 3, 5, 4}
Set函数可以接收一个数组
var s = new Set([2, 3, 5, 4, 5, 2, 2])
console.log(s) // {2, 3, 5, 4}
console.log(s.size) // 4
数组去重
var s = [...new Set([2, 3, 5, 4, 5, 2, 2])]
console.log(s) // [2, 3, 5, 4]
字符串去重
console.log([...new Set('aabbcc')].join('')) // abc
2. Set的实例方法
-
size Set实例成员的总数
-
add() 添加值,返回Set结构本身
-
delete(value) 删除某个值,返回Set结构本身
-
has(value) 返回一个布尔值,判断该值是否为Set成员
-
clear() 清除数据,没有返回值
-
遍历方法:
-
keys()键名遍历、values() 键值遍历,Set结构没有键名,所以keys()和values() 返回值一样
-
entries() 、forEach()
var s = new Set([2, 3, 5, 4, 5, 2, 2]) s.forEach((key, value) => console.log(key + ':' + value))
-
3. Map() 数据结构类似于对象,它的‘键’不局限于字符串
var s = new Map([['a', 1], ['b', 2]])
console.log(s) // {"a" => 1, "b" => 2}
var map = new Map()
map.set(1, 'aaa').set(2, 'bbb')
console.log(map) // {1 => "aaa", 2 => "bbb"}
console.log(map.get(1)) // aaa
方法:set()、get()、delete()、
has() 某个键是否在 Map()结构中
Map()转数组
var map = new Map()
map.set(1, 'aaa').set(2, 'bbb')
console.log([...map]) // [[1, "aaa"], [2, "bbb"]]
数组转Map
var s = new Map([['a', 1], ['b', 2]])
console.log(s) // {"a" => 1, "b" => 2}
4. Promise
Promise是异步编程的一种解决方案,简单的说就是一个容器,里面保存着未来才会结束的事情。
Promise有两个特点:
- 对象的状态不受外界影响。Promise是一个异步状态,有三种pending(进行中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果可以决定是哪种状态,任何其它操作都不能改变这个状态。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。状态有两种改变:1)pendingfulfilled;2)pendingrejected
Promise基本用法:
const promise = new Promise(function(resolve, reject) {
if ( /* 异步操作成功 */) {
resolve(value)
} else {
reject(error)
}
})
Promise接收一个函数作为参数,该函数接收两个参数:resolve和reject;resolve是Promise的状态从‘未完成’变成‘已成功’;reject是Promise的状态从“未完成”变成“已失败”
promise实例生成后,可以使用then方法分别指定resolved和rejected状态的回调函数
promise.then(function(val) {
// success
}, function(error) {
// failure
})
Promise新创建后会立即执行
const promise = new Promise(function(resolve, reject) {
console.log('Promise')
resolve()
})
promise.then(() => {
console.log('resolved')
})
console.log('Hi!')
// Promise
// Hi!
// resolved
上例代码中Promise创建后会立即执行,所以先输出Promise,then方法指定的回调函数,将在当前脚本所有同步任务执行完成后才会执行,所以resolved!最后执行。
1)Promise.all()
方法用于将多个Promise实例,包装成一个新的Promise实例。
ponst p = Promise.all([p1, p2, p3])
p的状态有P1、 p2、 p3
决定,P1、 p2、 p3
都是resolved
,则p
是resolved
;
P1、 p2、 p3
有一个是rejected
,则p
是rejected
runAsync1() {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('异步任务1执行')
resolve('数据1')
}, 1000)
})
return p
},
runAsync2() {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('异步任务2执行')
resolve('数据2')
}, 2000)
})
return p
},
runAsync3() {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('异步任务3执行')
resolve('数据3')
}, 2000)
})
return p
},
Promise.all([this.runAsync1(), this.runAsync2(), this.runAsync3()])
.then(function(results) {
console.log(results)
})
// 异步任务1执行
// 异步任务2执行
// 异步任务3执行
// ["数据1", "数据2", "数据3"]
2)Promise.race() 只有一个
Promise.race([this.runAsync1(), this.runAsync2(), this.runAsync3()])
.then(function(results) {
console.log(results)
})
// 异步任务1执行
// 数据1
// 异步任务2执行
// 异步任务3执行
P1, p2, p3
只要有一个resolved
,p
就是resolved
;p1,p2,p3
都为rejected
,则p
是rejected
3)Promise.any()
只要参数实例有一个变成fulfilled
,包装实例就会变成fulfilled
,如果所有实例参数都变成rejected
,包装实例就会变成rejected
;
Promise.any([this.runAsync1(), this.runAsync2(), this.runAsync3()])
.then(function(results) {
console.log(results)
})
// 异步任务1执行
// 数据1
// 异步任务2执行
// 异步任务3执行
Promise.any()
和Promise.race()
很像,只有一点不同:就是Promise.any()
不会因为某个Promise
状态变成rejected
而结束,必须等到所有状态都变成rejected
才会结束。
5. for…of循环
可以循环数组、Set 和 Map结构、某些类似数组的对象。
for…in
循环数组,循环的是索引值
for…of
循环数组,循环的是属性值
var arr = ['a', 'b', 'c']
for (const a of arr) {
console.log(a) // a b c
}
for (const b in arr) {
console.log(b) // 0 1 2
}
for…of
循环Map和Set结构
var s = new Set([11, 22, 33])
for (const a of s) {
console.log(a) // 11 22 33
}
var m = new Map().set('a', 11).set('b', 22)
for (const b of m) {
console.log(b) // ["a", 11] ["b", 22]
}
6. this的指向
var name = '小王' // eslint-disable-line
var age = 17 // eslint-disable-line
var obj = {
name: '小张',
objAge: this.age,
Fun: function() {
console.log(this.name) // 小张
console.log(this.age) // undefined
}
}
console.log(obj.objAge) // undefined
obj.Fun()
使用bind()、call()、apply()
改变this指向
var name = '小王' // eslint-disable-line
var age = 17 // eslint-disable-line
var obj = {
name: '小张',
objAge: this.age,
Fun: function() {
console.log(this.name + '的年龄' + this.age)
}
}
var db = {
name: '小黄',
age: 25,
}
obj.Fun.bind(db)() // 小黄的年龄25
obj.Fun.call(db) // 小黄的年龄25
obj.Fun.apply(db) // 小黄的年龄25
bind()、call()、apply()
带参数改变this指向
var name = '小王' // eslint-disable-line
var age = 17 // eslint-disable-line
var obj = {
name: '小张',
objAge: this.age,
Fun: function(fm, t) {
console.log(this.name + '的年龄' + this.age + '来自' + fm + '去往' + t)
}
}
var db = {
name: '小黄',
age: 25,
}
obj.Fun.bind(db, '成都', '上海')() // 小黄的年龄25来自成都去往上海
obj.Fun.call(db, '成都', '上海') // 小黄的年龄25来自成都去往上海
obj.Fun.apply(db, ['成都', '上海']) // 小黄的年龄25来自成都去往上海
bind()、call()、apply()
的区别:
- bind()不能立即执行,必须需要调用才会执行
- bind()、call()、apply()的第一个参数都是this指向的对象;
- bind()、call() 的参数是直接放在()里的,第二第三第n个参数都用逗号隔开;apply()的参数必须放到数组里面[ ];
7. export命令和import命令
export命令用于规定模块对外接口,import命令用于输入其它模块提供的功能
xxx.js
const formJson = {}
const addForm = []
export { formJson, addForm }
引入
import { formJson, addForm } from './formBuild'
export default命令