ES6小实验-函数的扩展
函数参数默认值
ES6允许为函数的参数直接设置默认值,即直接写在参数定义的后面
function log (x, y = "world") { console.log(x, y) } log("Hello")//Hello world
上面代码中,y是默认声明的,参数默认值可以与解构赋值的默认值,结合使用
function log ({x, y = "world"}) { console.log(x, y) } log({x: "Hello"})//Hello world log({x:1, y:2})//1 2
通常情况下,定义了默认值的参数,应该是函数的尾参数,如果非尾部的参数设置默认值,那这个参数就没法省略了
function log (x="Hello", y ) { console.log(x, y) } log(, "world")//Uncaught SyntaxError: Unexpected token , log(undefined, "world")//Hello world
上面x不能省略,否则会报错,如果不能写在尾部,可以在调用时,用undefined代替默认值只是起到开始默认赋值的作用,赋值结束就可以忽略掉了
rest参数
ES6引入rest参数(...),用于获取函数的多余参数,rest参数搭配的变量是一个数组,该变量将多余的参数放进数组里
function rest(...values) { console.log(values)//[1, 2, 3, 4] } rest(1,2,3,4)
注意:rest参数之后不能再有其他的参数,否则会报错
扩展运算符
扩展运算符(spread)是三个点(...),将一个数组转为逗号分隔的参数序列,感觉就是上面的rest参数
console.log(...[1,2,3])//1 2 3
扩展运算符有不少应用
1.合并数组
var arr1 = [1,2,3] var arr2 = [4,5,6] console.log([...arr1,...arr2])//[1, 2, 3, 4, 5, 6]
2.可以将字符串转为真正的数组
var str = "hello" console.log([...str])//["h", "e", "l", "l", "o"]
3.任何Iterator接口的对象,都可以用扩展运算符转为真正的数组
var nodeList = document.querySelectorAll('div'); var array = [...nodeList];
但对于那些没有部署Iterator接口的类似数组对象,扩展运算符就无法将其转换为真正的数组了,这时可以改为Array.from()
var str = { '1': 'a', '2': 'b', '3': 'c', length: 3 } console.log([...str])//Uncaught TypeError: undefined is not a function
4.Map和Set结构,Generator函数
扩展运算符内部调用的是数据结构的Iterator接口,因此只要具有Iterator接口的对象,都可以使用扩展运算符
var map = new Map([ ['1', 'a'], ['2', 'b'], ['3', 'c'], ]) console.log([...map.keys()])//["1", "2", "3"]
总结:扩展运算符就是一个破坏王,专门把具有Iterator接口的数据结构拆掉,数组,字符串,Map,Set等等都可以被拆成用逗号隔开的序列
name属性
函数的name属性,返回该函数的函数名,有点自问自答的感觉
var func = function () { } console.log(func.name)//func
箭头函数( => ) 如果箭头函数不需要或需要多个参数,就使用一个圆括号代表参数部分
var f = () => 5 //等同于: var f = function f() { return 5; };
如果箭头函数直接返回一个对象,必须在对象外面加上括号
var f = () => ({id: 1,name: 'tom'})
使用箭头函数有几点要注意
函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象,在箭头函数中this指向是固定的
function foo() { setTimeout(function () { console.log('id:', this.id);//21 }, 100); setTimeout(() => {console.log('id:', this.id)}, 100)//42 } var id = 21; foo.call({id: 42});
上面的第一个setTimeout里面是普通函数,执行时this指向全局对象window,所以输出21,第二个箭头函数this总是指向函数定义生效时所在的对象,所以输出42,this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码的this,正因为没有this,所以也就不能做构造函数,上面的代码转成ES5如下:
function foo() { var _this = this; setTimeout(function () { console.log('id:', this.id); //21 }, 100); setTimeout(function () { console.log('id:', _this.id); }, 100); //42 } var id = 21;
长期以来,JS语言的this对象一直是个令人头疼的问题,在对象方法中使用this,必须非常小心,
箭头函数在很大程度上解决了这个困扰。