ES6小记(2)
ES6小计(2)
7. 函数的扩展
7.1 参数的默认值
函数定义时,可以直接用等于为参数设定默认值。传参全等于undefined
的时候,默认值有效。参数默认值与解构赋值同时使用时,参数默认值先有效,其次再进行解构赋值。
函数添加了length
属性,表示函数参数总个数-已设定默认值的参数个数。
function log(x, y = 'Y') { console.log(x, y) }
log('X') // XY
(function(a, b, c = 5) {}).length // 2
函数的变量初始化的作用域不属于函数内部,而在函数外层。
let x = 1
function f(y = x) {
let x = 2
console.log(y)
}
f() // 1
7.2 rest
参数
函数传参时,可以使用...变量名
的方式定义函数参数,变量名为一个传参组成的数组。rest
参数后不能再有参数。
function f(...arr) {
console.log(arr)
}
f(1, 2, 3) // [1, 2, 3]
7.3 ...
扩展运算符
类似于rest参数
的逆运算。将数组返还为多个项目参数。
console.log(...[1, 2, 3]) // 1 2 3
常有以下使用方法:
7.3.1 不定参数个数的传参。
let ag = ['name1', 1, 'name2', 2, 'name3', 3]
redis.client.hmset('key', ...ag, function(err, data) {}) // 简化传参的书写,此句等同于下句
redis.client.hmset('key', 'name1', 1, 'name2', 2, 'name3', 3, function(err, data) {})
7.3.2 数据合并
let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
arr1.push(...arr2) // arr1 = [1, 2, 3, 4, 5, 6]
arr1.concat(arr2)
[...arr1, ...arr2]
7.3.3 字符串转数组
[...'hello'] // ['h', 'e', 'l', 'l', 'o'] 可识别UTF-16,依据数组长度,可有效判断字符串长度
7.3.4 类数组对象转换为真数组
[].slice.call(arrLike)
Array.from(arrLike)
[...arrLike]
7.4 箭头函数
用箭头=>
定义的函数。
var f = v => v // 等同于如下:
var f = function(v) {
return v
}
var sum = (num1, num2) => { return num1 + num2 }
箭头函数仅仅是简化了函数定义的书写,并没有新增多少实际有用的功能。为了便于阅读,建议箭头函数的参数部分的()
不要省略。
箭头函数与普通函数的区别有以下四点:
- 箭头函数的
this
指向定义时所在对象,不是使用时所在对象;也可以说是箭头函数没有自己的this
对象,在其内使用this
其实是查找到外层的this
; - 不能使用
new
,不可当做构造函数; - 不能使用
arguments
对象,但可以使用rest参数;箭头函数没有自己的arguments
参数; - 不可使用
yield
命令。
7.5 尾调用优化与尾递归优化
函数尾调用时,不需要用到上层函数的环境时,使用尾调用就会不将上层环境保留在内存中,从而节省内存。尾递归同理。但是,只有开启严格模式,尾调用优化才会生效。
8. 对象的扩展
8.1 对象属性与方法名的简洁缩写
es6允许在对象中只写属性名,不写属性值。这时,属性值等于属性名所代表的变量。
let x = 1, y = 2
let obj = {x, y} // let obj = {x: 1, y: 2}
let objF = {
testFunc(x) {
return x
}
}
8.2 属性名可用表达式定义
用表达式作为属性名时,表达式要放在[]
内。属性名表达式与简洁表示法不能同时使用,否则会报错。
obj['a' + 'b'] = 123
obj = {
abc: 123,
['a' + 'b']: 321
}
var foo = 'bar'
var baz = { [foo] } // error
var baz = { [foo]: 'abc' } // {bar: 'abc'}
8.3 Object.is()
Object.is()
用来比较两个值是否严格相等,类似于===
,但有以下两点不同:
+0 === -0 // true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
8.4 Object.assign()
Object.assign(目标obj, 源obj1, 源obj2...)
,将源obj的可枚举属性复制到目标obj上,靠后的源obj属性会覆盖靠前的源obj的同名属性。继承的属性不会复制。该复制只是浅复制,只会复制当前层。
var target = {a: 1, b: 1}, source1 = {b: 2, c: 2}, source2 = {c: 3}
Object.assign(target, source1, source2)
target // {a: 1, b: 2, c: 3}
常用的应用有:克隆对象、合并多个对象、为属性指定默认值
8.5 属性的可枚举性
遍历对象属性时,注意使用的遍历方法与可遍历属性的关系。for...in
遍历时,会遍历继承属性,不会遍历不可枚举属性。Object.keys()
返回自身可枚举属性组成的数组。JSON.stringify()
只字符串化自身可枚举属性。Object.assign()
只复制自身可枚举属性。Reflect.enumerate()
返回for...in
会遍历的属性组成的数组。
故,循环遍历时,为了避免继承上的属性,建议用Object.keys()
获取属性名后再循环属性名数组进行遍历。
9. Symbol
Symbol
是一个新的原始数据类型,表示独一无二的值。成为第七种数据类型:undefined、null、boolean、string、number、object、symbol。Symbol
就是一个类似于不会重复的字符串。
9.1 Symbol
类型的创建
Symbol
类型不是对象,不能用new
方式创建。创建函数为Symbol(str)
,创建时,可以传入一个字符串参数,用来描述该Symbol
值。Symbol
值不能与其余类型值进行运算,但可以显示转换为字符串和布尔值。
let s1 = Symbol('s1')
let s2 = Symbol('s1')
let s3 = Symbol('s3')
s1 === s2 // false
console.log(s1) // Symbol(s1)
console.log(String(s1)) // Symbol(s1)
console.log(s1.toString()) // Symbol(s1)
console.log(Boolean(s1)) // true
9.2 Symbol
作为属性名
Symbol
作为属性名时,不能用.
运算符,只能用[]
变量传值。
let s1 = Symbol()
a[s1] = 123
var a = {}
a = {
[s1]: 123
}
Object.defineProperty(a, s1, {value: 123})
9.3 对象Symbol
属性的遍历
Symbol
作为属性名时,不会被for...in
、for...of
循环遍历到,也不会被Object.keys()
、Object.getOwnPropertyNames()
返回。可以通过Object.getOwnPropertySymbols()
通过数组返回。因此,可以为对象定义一些非私有,但只希望用于内部的方法。
9.4 Symbol.for()
和Symbol.keyFor()
当需要使用同一个Symbol
值时,除了通过变量传参以外,还可以通过Symbol.for()
获取。Symbol.for()
的机制是检索全局中是否有注册该描述的Symbol
值,若有,则返回该值;若没有,则注册后返回该值。Symbol.keyFor()
则是通过Symbol
值,获取注册描述。Symbol()
创建的Symbol
值不会进行注册。
Symbol.for('desc') === Symbol.for('desc') // true
Symbol('desc') === Symbol.for('desc') // false
let s1 = Symbol.for('desc')
let s2 = Symbol('desc')
Symbol.keyFor(s1) === 'desc' // true
Symbol.keyFor(s2) // undefined
es6内置的Symbol
值此处不讲,有需求可以查询相应资料。
TO BE CONTINUED!