JavaScriptES6函数的扩展

ES6中的函数相当于前面的版本发生了翻天覆地的变化。

目录

函数的默认值

解构赋值与默认值结合使用

参数默认值的位置

函数的length属性

作用域

参数默认值和独立作用域的应用

rest参数

严格模式

name属性


函数的默认值

ES6允许为函数的参数设置默认值,即直接写在形参定义的后面

function log(x,y = 'World'){
    console.log(x,y);
}
log('Hello');    //Hello World
log('Hello','wang');    //Hello wang
log('Hello',"");    //Hello 
log('Hello',0);   //Hello 0

函数形参变量是默认声明的,所以不能再函数体中用let或者const再次声明,否则会报错。

function(x = 5){
    let x = 10;    //error
    const x = 10;    //error
    console.log(x);
}

函数使用默认参数时,函数不能有同名参数,否则会报错。

function foo(x,x,y){
    //不报错
}
function foo(x,x,y = 1){
    //报错
}

另外,一个容易忽略的地方是,参数默认值不是传值的,而是每次都重新计算默认表达式的值,也就是说,参数默认值是惰性求值的。

let x = 99;
function foo(p = x + 1){
    console.log(p);
}
foo();    100
foo();    100
x = 102;
foo();    103

解构赋值与默认值结合使用

参数默认值可以与结构赋值的默认值结合起来用。

function foo({x, y = 5}){
     console.log(x,y);
}
foo({});    // undefined 5
foo({x : 1});   // 1 5
foo({x : 1 , y : 2});   //1 2
foo();  //error

上面代码只使用了对象的解构赋值默认值,没有使用函数参数的默认值,只有当函数foo的参数是一个对象时,变量x和y才会通过结构赋值生成。如果函数foo调用时没提供参数,变量x和y就不会生成,从而报错,通过提供函数参数的默认值,就可以避免这种情况。

如果没有参数foo函数的参数默认为一个空对象。

function foo({x,y = 5} = {}){
    console.log(x,y);
}
foo();  //undefined 5

function fetch(url,{body = "" , method = 'GET', headers = {} }){
     console.log(method);
}
fetch('http://example.com',{})  //GET
fetch('http://example.com');    //error

上面代码中,如果函数fetch的第二个参数是一个对象,就可以为它的三个属性设置默认值,这种写法不能省略第二个参数,如果结合函数参数的默认值,就可以省略第二个参数。

function fetch(url,{ body = "", method = 'GET' , headers = {}} = {}){
     console.log(method);
}
fetch('http://example.com');    //GET
//函数fetch没有第二个参数时,函数参数的默认值就会生效,然后才是解构赋值的默认值生效,变量method才会取到默认值GET。

参数默认值的位置

通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。如果传入undefined,将触发该参数等于默认值,null则没有这个效果。

function f(x = 1 , y ){
     console.log(x,y);
}
f();    // 1 undefined
f(2);   //2 undefined
f(,2);  // error
f(undefined,2);    //1 2

函数的length属性

指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数,也就是说,指定了默认值后,length属性将失真。

函数的length属性查找函数非默认参数的个数,是从左向右开始查找,当遇到默认值参数时停止查找。此时的值就是表示函数得length属性,也就是当设有默认值的时候length属性失真。

function fun (a,b,c){}
console.log(fun.length);  //3  
function fun( a = 1, b, c){}
console.log(fun.length);    // 0 
function fun ( a, b = 1 ,c){};
console.log(fun.length);    //1

作用域

一旦设置了参数的默认值,函数声明初始化时,参数会形成一个单独的作用域(content),等到初始化结束后,这个作用域就会消失,这种语法行为,在不设置参数的默认值时,是不会出现的。

var x = 1 ; 
function f(x, y = x){
    console.log(y);
}
f(2);    // 2
//上面代码中,参数y的默认值等于变量x,调用函数f时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x会指向第一个参数x,而不是全局变量x,所以输出的是2。

参数单独作用域,函数内部作用域和函数上级作用域。

var x = 1;
function foo (x, y = () => { x = 2}){
   var x = 3;
   y();
   console.log(x);
}
foo();  // 3 
console.log(x);     // 1

上面代码中, 函数foo的参数形成一个单独作用域。这个作用域里面,首先声明了变量x,然后声明了变量y,y的默认值是一个匿名函数。匿名函数中的内部变量x指向同一作用域中的第一个参数x。函数foo内部又声明了一个内部变量x,该变量与单独作用域的第一个参数x由于不在同一个作用域,所以不是同一个变量,因此执行y后,内部变量和全局变量的值都没变。如果将函数内部变量var x = 3 中的var 去掉的话, 函数内部的x就指向了 单独作用域中的第一个参数x,而函数上级的外部变量x依然不受影响。

参数默认值和独立作用域的应用

可以利用参数的默认值,指定某一个参数不能省略,如果省略就抛出一个错误。

try{
   function throwIfMissing() {
       throw new Error('Missing parameter');
    }
    function foo(mustBeProvided = throwIfMissing()) {
       return mustBeProvided;
    }
    foo();
}
catch(e){
      console.log(e.message);
}

上面代码中可以看到,参数mustBeProvided的默认值等于throwIfMissing函数的执行结果,这表明参数的默认值不在定义时执行,而是在运行时执行。如果参数已经赋值,默认值中国的函数就不会运行。

另外,还可以将参数的默认值设为undefined,这表明这个参数是可以省略的。

function foo( x = undefined){
     console.log(x);
}
 foo();

rest参数

ES6 引入了rest参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了,rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

function fun(x, ...value){
    console.log(x);
    console.log(value);
}
fun(1,2,3,4);
function add (...value){
     let sum = 0;
     for(let val of value){
          sum += val;
     }
     return sum;
}
console.log(add(1,2,3,4));

rest参数可以代替arguments变量。

 //arguments变量的写法
function sortNumber(){
     return Array.prototype.slice.call(arguments).sort();
}
console.log(sortNumber(1,4,7,8,5,2,3,6,9));
//rest参数的写法
const sortNumber1 = (...numbers) => numbers.sort();
console.log(sortNumber1(1,4,7,2,5,8,3,6,9));

注意: rest参数后面不能再有其他参数(即rest只能是最后一个参数),否则会报错;函数的length属性,也同样不包括rest参数也会失真。

严格模式

严格模式从ES5开始,ES6进行了一点修改,规定只要函数使用了 默认值 解构赋值 或者扩展运算符,那么函数内部就不能显示设定严格模式,否则会报错。

function doSomething(a, b  = a ){    //报错
     'use strict';
}
function doSomething ({a,b}){        //报错
     'use strict';
}
function doSomething(...value){     //报错
      'use strict';
}
var obj = {
   doSomething({a,b}){ //报错
   'use strict';
    }
}

有两种方法是可以规避这种限制。

//第一种是设定全局性的严格模式,这是合法的
'use strict';
function  foo (a, b = a){
      console.log(a,b);
}
foo(3);     // 3 3
//第二种是把函数包在一个无参数的立即执行函数里面。
const doSomething = (function(){
    'use strict';
     return function (value = 11){
         console.log(value);
     }
}())
doSomething();   //11

name属性

函数的name属性,返回函数的函数名。

var  f = function (){}
console.log(f.name);    //f

当将一个具有函数名的函数赋予一个变量的时候,ES5和ES6会返回函数原本的名字

var f = function foo(){
    console.log('1');
}
console.log(f.name);    //foo

Function构造函数返回的函数实例,name属性的值为anonymous匿名的

console.log((new Function).name);   //anonymous

bind返回的函数,那么属性值会加上bound前缀

function foo(){}
console.log(foo.bind({}).name);     //bound foo
console.log((function(){}).bind({}).name)   // bound 

主页传送门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值