ES6带来最重要的变化之一就是函数的许多新特性,废话不多说,我们直接从最重要的变化开始说起。
箭头函数
ES6这次变化中最令人兴奋的就是引入了箭头(arrow)函数,js的开发者们已经等了太久了,之前的使用中,总是会被各种bind搞得晕头转向。现在有了箭头函数,这些烦恼将不复存在。
基本语法
(params)=>{doSomething}
上面的形式使比较完整的。分为了函数参数、箭头、函数体几个部分。
若无函数参数,可以使用下面的形式:
=>{doSomething}若是函数体只有一句的话,甚至可以省略包含函数体的大括号。
=> return a;
箭头函数的this值:
在ES6之前,我们要是使用回调函数传参就要绑定函数的对象,否则会出错。例:
//如果绑定,函数将没有执行环境 document.getElementsByName('button').onClick(this.callBack.bind(this)); function callBack(){ do somthing }复制代码
而现在有了箭头函数,那这一切将变得轻而易举。
document.getElementsByName('button'.onClick(()=>{ do something... }));复制代码
这是因为箭头函数的this值直接绑定了外部函数的this值,并且这个this值是无法被改变的,虽然你可以使用箭头函数调用call、apply、bind方法,但是他们依然无法改变函数的this绑定。这也是箭头函数最重要的特性之一,不需要我们频繁的手动绑定函数的执行对象了。
箭头函数的参数。
首先要说的一点是箭头函数没有arguments对象。但是可以访问外部函数的arguments对象。举个例子
function createArrowFunction(){ return ()=> arguments[0]; } let test = createArrowFunction(1,2,3,4,5); console.log(test); // 1复制代码
其实也很好理解,既然箭头函数的this直接绑定了外部函数的this,那他就应该可以访问到外部函数的arguments对象。
箭头函数的参数同样支持传递默认参数(详细的会在后面讲)。我们先来看看如何使用。
let sum = (param1 = 1, param2 = 1)=>{ console.log(param1 + param2); } sum(); // 2复制代码
箭头函数的应用
我们上面也看到了一些箭头函数的特性,首先我们来总结一下箭头函数的特点。
- 语法简洁
- 使用方便,无需设置this绑定,支持默认参数等特性
上面的特点导致了我们与数组搭配在一起使用会相得益彰。
let arr = [1,2,3,4,5]; arr.forEach((element)=>{ console.log(element); }); // 1 // 2 // 3 // 4 // 5复制代码
可以说箭头函数是ES6中函数部分变化最大的改变。下面我们将了解一下ES6中函数的其他变化。
函数的默认参数(函数形参的默认值)
在ES6之前我们无法给函数形参添加默认值,但是我们会用另外的形式去模拟这种行为。
function Person(name,age,sex){ this.name = name; this.age = age || 18; this.sex = sex || female; } // name: Nero, age:20, sex:female new Person("Nero",20,female); // name:Geodfrey,age:18,sex:female new Person("Grodfrey");复制代码
在上面的例子中我们如果给函数的某个参数传递参数,那么将使用传递的参数,否则将使用 “||”后面的内容,这样就模拟了函数的默认参数。 上面的做法是一种很安全的做法,并且大多数JavaScript库与开发者们都采用这种方式,但是ES6依然添加进来了新的方式,为的是我们更加方便的使用这种基础操作。
基础语法
function Person(name,age = 20,sex = female){ this.name = name; this.age = age; this.sex = sex; } // name:"Grodfrey", age:20, sex:female new Person("Grodfrey");复制代码
其实很简单,就是才定义形参时加一个 “=”,后面跟上内容,简简单单的。还有一个比较重要的事情是,默认参数并不是只支持传递原始值,也可以传递非原始值。例如函数表达式。这个传递什么类型的原始值取决于你的实际情况。
还有一个比较重要的特点就是,如果你主动传入undefined,函数也会调用默认值。
默认参数的临时死区
函数的默认参数也有临时死区,其实很容易理解,就是拥有默认值的参数不能在定义之前使用。我们来看个例子就好了。
function sun(param1 = param2,param2 = 1){ return param1 + param2; } sum(1,2); // 2 sum(undefined,1); //抛出错误复制代码
如果像下面的用法一样就会报错,简单的来说就是在第一个参数要使用默认值(第二个参数)初始化时,但是第二个参数却还没有被初始化,这就产生了错误。
元属性(new.target)
在ES6中为函数新增了元属性,其实这个属性就是为了让我们区分函数的调用方式,如果使用new操作符调用函数时,元属性就会被赋值为new操作法的目标对象。如果是通过其他方式调用的,那这个属性的值就为undefined。
function Person(name){ if(new.target !== "undefined"){ this.name = name; }else{ console.log("请使用new操作符"); } } let person = new Person("nero"); Person.call(person,"Grodfery"); //请使用new操作符复制代码
这样的化我们就可以明确划分函数的作用了。一些构造函数可以防止被其他类型的对象调用,产生一些错误。
new.target属性只能在函数内部使用,如果在函数外部使用,将会抛出错误。
块级函数
在ES6中引入了块级函数,这次是官方引入的,虽然之前有一些浏览器也都是实现了块级函数,但是各不相同,这次ES6规定了块级函数的语法。
块级函数的语法很简单,其实你完全可以当作一个let定义的变量来使用,唯一的一个区别就是:块级函数会进行变量提升。
if(true){ console.log(typeOf doSomething); // Function function doSomething(){} } console.log(typeof doSomething); // undefined复制代码
当块级函数一旦离开相应的代码块,那么这个函数将被删除。
不定参数与展开运算符
不定参数是运行你传入数量不定的参数进入函数,在函数中会被整合成数组。 而展开运算符与之相反,是将一个数组打散,一个一个的传入数组。
不定参数的基本用法
function Person(name,age,sex,...others){ this.name = name; this.age = age; this.sex = sex; for(let i = 0;i
我们可以在传入固定参数之后传入任意多个参数。,都会被存储在函数内部的不定参数同名的数组中。
不定参数的限制
不定参数有两个需要注意的地方
- 不定参数只能定义在函数参数列表的末尾。
//这种使用方式是有错误的。 // Uncaught SyntaxError: Rest parameter must be last formal parameter function doSomething(param1,...objs,param2){}复制代码
- 不定参数不能用于对象字面量setter中。
//这种操作也是不允许的, let obj = { set name(..key){} }复制代码
不定参数与arguments对象
不定参数中的值也会在arguments中,也就是说,即使不实用不定参数,继续使用原来的arguments对象也是完全没问题的。
展开运算符的基本用法
展开运算符的用法就比较简单了。
let value = [1,2,3,4,5,6,7,8,9]; console.log(Math.max(...value));复制代码
展开运算符极大的方便了我们,我们不需要再写一个循环或者通过其他方式将一个数组的变量传递到函数中去,只需要在数组前面使用 “...”符号,那么就会将他们打散传递给函数。
这次探讨的是ES6中有关函数的变动,有些内容我省略掉了,例如name属性,我只列举了一些我觉得会比较常用的。这都是基于我在工作中的认识,如果您有一些更好的想法或者是本篇文章某处错误,你都可以在下面留言给我!!!