ES6函数新特性及箭头函数与普通函数的区别
前言:项目中也经常用到es6的箭头函数,但是也没怎么去细看es6更新了哪些函数特性,毕竟es7, es8都出来了。今天细看了《深入了解ES6》这本书的第三章,函数这一节,特此记录一下es6更新了哪些函数的新特性。
1.函数形参的默认值。
e5及之前,设置默认参数值均在函数内部去判断是否传了该参数,未传值便赋予默认值,说实话我现在还在用这种思维写函数,看来要改一改了,不然真的没点进步了。
举例:
function makeRequest(url,timeout,callback){
timeout=timeout||2000; //未传值是undefined,这种写法不安全,传入0也是false 设为默认值
callback=callback||function(){};
//doSomething
}
//安全写法,
function makeRequest(url,timeout,callback){
timeout=(typeof timeout!=="undefined")?timeout:2000; //虽安全但仍需额外代码来执行
callback=(typeof callback!=="undefined")?callback:function(){};
//doSomething
}
而ES6中的默认参数值:若未为参数传值或传入undefined,则为其提供默认值
举例:
function makeReques(url,timeout=2000,callback=function(){}){
//doSomething
}
默认参数的特点:
(1)默认参数对arguments对象的影响
es5非严格模式下,命名参数的变化会同步更新到arguments对象中。严格模式下将不会导致arguments改变
function mixArgs(first,second){//非严格模式
console.log(first===arguments[0]);
console.log(second===arguments[1]);
first="c",second="d";
console.log(first===arguments[0]);
console.log(second===arguments[1]);
}
mixArgs("a","b");
true
true
true
true
//严格模式下
function mixArgs(first,second){
"use strict"
console.log(first===arguments[0]);
console.log(second===arguments[1]);
first="c",second="d";
console.log(first===arguments[0]);
console.log(second===arguments[1]);
}
mixArgs("a","b")
true
true
false
false
在es6中:无论是否显示定义了严格模式,arguments对象都将与es5严格模式下保持一致,默认参数值的存在将使arguments对象与命名参数分离。
(2)默认参数表达式
//非原始值传参:
let value=5;
function getValue(){
return value++;
}
function add(fiirst,second=getValue()){
return first+second;
}
console.log(add(1,1));//2
console.log(add(1));//6
console.log(add(7));//6 每调用一次 未传第二各参数的add将改变value的值。
正因默认参数是在函数调用时求值,可使用先定义的参数作为默认值,反之不可,默认参数的临时死区。
(3)默认参数的临时死区
函数参数有自己的作用域和临时死区,其与函数体的作用域是各自独立的,就是说参数的默认值不可访问函数体内声明的变量。
2.不定参数
在命名参数前加三个点(...)就表明这是一个参数,该参是一个数组,包含着自他之后的所有参数,通过数组名即可逐一访问各个参数;
function pick(object,...keys){
let result=Object.create(null);
for(let i=0,len=keys.length;i<len;i++){
result[keys[i]]=object[keys[i]];
}
return result;
}
let as={title:"es6",name:'Nicks',years:2012};
pick(as,...["name","years"]);//{name: "Nicks", years: 2012}
ES5中无命名参数
javascripts提供arguments对象来检查函数的所有参数,因此不必定义每个要用的参数。实际使用有些笨重,不如es6不定参数
举例:
function pick(object){
let result=Object.create(null);
//从第二个参数开始
for(let i=1,len=arguments.length;i<len;i++){
result[arguments[i]]=object[arguments[i]];
}
return results;
}
let as={title:"es6",name:'Nicks',years:2012};
pick(as,"name","years");//{name: "Nicks", years: 2012}
不定参数的使用限制:
① 每个函数最多只能声明一个不定参,必须在所有参数的末尾
②不定参不能用于对象字面量setter之中
③无论是否是用不定参数arguments对象总是包含所有传入函数的参数。
注:另外还有其他特性:增强Function构造函数、展开运算符、name属性,明确多重用途,(this),元属性new.target、块级函数,在此不细细说明
3、箭头函数
(1)与传统函数不同之处:
①没有this,super,arguments和new.target绑定,箭头函数中的这些值由外围最近一层非箭头函数决定。
②不能通过new关键字调用。它没有[[Construct]],所以不能用作构造函数。如用会报错
③没有原型(prototype)
④不可以改变this的绑定,函数内部的this值不可被改变,在函数的生命周期内始终保持一致。
⑤不支持arguments对象。所以只能通过命名参数和不定参数两种形式访问函数参数。
⑥不支持重复的命名函数。
(2)箭头函数语法:
let 函数名=(参数1,参数2,...)=>{ };
当只有一个参数时,可直接写参数名。箭头后也可不跟{},直接跟表达式或要返回的值,对象字面量要用()括住。
辨识方法:typeof instanceof
(3)创建立即执行函数表达式:
是javasscript函数比较流行的使用方式,可定义一个匿名函数并立即调用,自始至终不保存对该函数的引用。(想创建一个与其他程序隔离的作用域时,该模式比较方便)。
//es5
let person =function(name){
return {
getName:function(){
return name;
}
};
}("Nicholas");
console.log(person.getName());//"Nicholas"
//es6:
let person =((name)=>{
return {
getName:function(){
return name;
}
};
})("Nicholas");
consol.log(person.getName());//"Nicholas"
(3)ES6尾调用优化(尾调用系统的引擎优化)。
尾调用指的是函数作为另个函数的最后一句被调用:
function doSomething(){
return doSomethingElse();//尾调用
}
暂时也不太明白 ,书上是这么说:尾调用优化可帮函数保持一个更小的调用栈,从而减少内存的使用,避免栈溢出错误,当程序满足优化条件时,引擎会自动对其进行优化。
//递归:
function factorial(n){
if(n<=1){
return 1;
}else{
//无法优化,必在返回后执行乘法操作。
return n*factorial(n-1);
}
}
//ES6引擎优化:
function factorial(n,p=1){
if(n<=1){
return 1*p;
}else{
let result=n*p;
//优化后
return factorial(n-1,result);
}
}
暂时就了解这么多,后续有新见解再多补充。