7. 函数参数默认值
ES6 允许给函数参数赋值初始值
7.1 形参初始值
// 具有默认值的参数, 一般位置要靠后 let f1 = function( a, b, c=10 ) { console.log(a+b+c) } // 没有给有默认值的参数传值时,参数的值为默认值 f1(1,2,3) f1(1,2) // 有默认值的参数放前面,当传入的参数个数不等于参数的总数时会出现错误 // 一般位置要靠后 let f2 = function( a, b=12, c ) { console.log(a+b+c) } // 1 会赋值给 a // 2 会赋值给 b // c 没有传入值,三个数相加会出现错误 NaN // c 为undefined f2(1,2)
7.2 与解构赋值结合
function connect({host="127.0.0.1", username,password, port}){ console.log(host) console.log(username) console.log(password) console.log(port) } connect({ username: 'root', password: 'root', port: 3306 })
将 对象中的值解构 出来赋值给对应的变量,username: ‘root’ 对应 username,… ,由于对象中没有属性 host ,所以 host 会使用默认值
8. rest 参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
let f1 = function (...args) { // rest 参数 会将传入的多个参数转为一个数组 // 转为数组后可以使用数组的方法 filter some every map ... console.log(args) } f1(1, 2, 3) // 箭头函数也可以使用 rest 参数 let f2 = (...args) => { console.log(args) } f2(4, 5, 6)
8.1 rest 参数必须要放到参数最后
rest 参数相当于一个参数接收多个参数值转成一个数组,如果不放在最后那么相当于前的参数值都被rest 参数获取,后面的参数将不会有参数传入,所以rest 参数必须放在最后。
let f3 = (a, ...args, b)=> { console.log(a) console.log(args) console.log(b) } f3(1,2,3,4,5,6,7)
rest 参数非常适合不定个数参数函数的场景
9. spread 扩展运算符
扩展运算符(spread)也是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
const arr = [1,2,3,4,5] console.log(arr) console.log(...arr)
9.1 数组的合并
先将两个或多个数组进行拓展然后再组合成一个数组
const arr1 = [1,2,3,4,5] const arr2 = [6,7,8,9,10] const newArr = [...arr1, ...arr2] console.log(newArr)
9.2 数组的克隆
使用该方法进行数组的克隆为浅拷贝
const arr1 = [1,2,3,4,5] const arr2 = [...arr1] console.log(arr2)
9.3 将伪数组转为真正的数组
<div></div> <div></div> <div></div>
const divs = document.querySelectorAll('div') console.log(divs) const divArr = [...divs] console.log(divArr)
10. Symbol
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义的对象属性不能使用 for…in 循环遍历,但是可以使用Reflect.ownKeys 来获取对象的所有键名
10.1 创建Symbol
let s1 = Symbol() console.log(s1, typeof s1) // 使用 Symbol() 创建的 Symbol 每次都不一样 let s2 = Symbol('hello') // 'hello'只是一个对于 Symbol 的描述,类似对Symbol的注释 let s3 = Symbol('hello') console.log(s2 === s3) // Symbol.for 创建 // 第一次创建会直接创建一个新的 Symbol // 第二次创建会先查看是否已经传建了,已经有了则不在创建,没有就创建 let s4 = Symbol.for('hello') let s5 = Symbol.for('hello') console.log(s4 === s5)
Symbol 显示的为Symbol(),可以把其理解为一个字符串,具有唯一性的字符串。
Symbol.for()与Symbol()的区别:都会生成新的Symbol,但是调用多次的Symbol()会生成多个不同的Symbol,调用多次的Symbol.for()只会生成一个Symbol。
10.2 不能与其他数据进行运算
let result = s + 100 let result = s > 100 let result = s + s
10.3 Symbol 创建对象属性
let game = { name: '俄罗斯方块', up: function () {}, down: function () {}, }
假设不知道该对象里面有什么属性和方法,向其中添加 up 和 down 方法,但是把确定其中是否有 up 和 down 方法,此时可以使用 Symbol
// 声明一个对象 let methods = { up: Symbol(), down: Symbol() }; // 向对象中添加方法 game[methods.up] = function(){ console.log("我可以改变形状"); } game[methods.down] = function(){ console.log("我可以快速下降!!"); } // 调用 game[methods.up]() game[methods.down]() console.log(game);
let youxi = { name: '狼人杀', [Symbol('say')]: function () { console.log('我可以发言') }, [Symbol('zibao')]: function () { console.log('我可以自爆') }, } console.log(youxi)
如上无法调用,每次Symbol(‘say’)的值都不一样
要使如上的方法能够进行调用,需要进行如下修改:
// 先在外面声明 Symbol 变量 let say = Symbol('say') let zibao = Symbol('zibao') let youxi = { name: '狼人杀', [say]: function () { console.log('我可以发言') }, [zibao]: function () { console.log('我可以自爆') }, } console.log(youxi) youxi[say]() youxi[zibao]()
10.4 Symbol 内置值
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
可以修改内置方法被自动调用时的执行效果
class Person { static [Symbol.hasInstance](param) { console.log(param) console.log('我被用来检测类型了') return false } } let o = {} console.log(o instanceof Person)
const arr = [1, 2, 3] const arr2 = [4, 5, 6] arr2[Symbol.isConcatSpreadable] = false console.log(arr.concat(arr2))