ES6笔记 - 函数参数扩展 与 箭头函数

函数的扩展

1. 函数的默认值

  • ES6允许直接在函数的形参中设置默认值

    function Point(x = 0,y = 0){
        let x;	//不允许重复声明
        
        this.x = x;
        this.y = y;
    }
    
    var p = new Point();
    p; //{x:0,y:0}
    
  • 注意:

    • 参数变量是默认声明的,即不能用let或const再次声明
    • 参数默认值不是传值的,而是每次都重新计算默认值表达式的值

1.1 解构赋值默认值与函数默认值

  • 解构赋值默认值与函数默认值可以组合使用,但两者常常难以区分

    • 解构赋值默认值通常处于"内层",即对象/数组内部
    • 函数默认值通常处于"外层",即在小括号内部的最外层
    //写法1:既设置了函数默认值"xxx={}",又设置了解构赋值默认值"{x=0,y=0}"
    function m1({x=0,y=0}={}){
        return [x,y];
    }
    
    //写法2:只设置了函数默认值"xxx={x:0,y:0}",没有设置解构赋值默认值
    function m2({x,y} = {x:0,y:0}){
        return [x,y];
    }
    
  • 连锁触发

    function fetch(url,{method = 'GET'} = {}){
        console.log(method);
    }
    
    fetch("www.baidu.com",{});	//"GET"
    fetch("www.baidu.com");	//"GET"
    

    解析:

    这里同时使用了解构赋值默认值与函数默认值

    如果传递第二个参数,则按照解构赋值默认值的特性,会获得method="GET"

    但如果不传递第二个参数,解构赋值默认值就不会被触发,此时函数赋值默认值就可以弥补这一点,当函数赋值默认值为{}时,就又触发了解构赋值默认值,这样就又有method="GET"

1.2 参数默认值的位置

  • 带默认值的参数一般都写于尾部,否则无法直接省略该参数

    function f(x = 1 , y){
        return [x,y];
    }
    
    f();	//[1,undefined]
    f(2);	//[2,undefined]
    f(,1);	//报错
    f(undefined,1); //[1,1]
    
    //可以看到,除非显式声明undefined,否则无法跳过x为y赋值
    

2. rest参数

  • ES6引入了rest参数,用于获取函数的多余参数,这个参数一定程度上替代了arguments

    rest参数搭配的变量是一个数组,该变量将多余的参数放入其中,同时由于本质上是一个数组,所以所有数组具有的方法也可以应用于rest参数

    function add(...values){
        let sum = 0;
        for(var val of values){
            sum += val;
        }
        return sum;
    }
    
    add(2.5,3);	//10
    
  • 注意:

    • rest参数必须是最后一个形参,否则会报错
    • rest函数与扩展运算符...[对象]书写方法相似,注意区分。一般来说rest函数只会出现于等号的左边,即被赋值方(形参);而扩展运算符只会出现于等号的右边,即赋值方(实参)

3. 箭头函数

3.1 基础用法

  • ES6允许使用箭头=>定义函数,箭头的左边为形参,右边为return值(或代码块)

    var f = v => v;
    //对应
    var f = function(v){
        return v;
    };
    
    var f = () => 5;
    //对应
    var f = function(){
        return 5;
    };
    
    var sum = (num1,num2) => num1+num2;
    //对应
    var sum = function(num1,num2){
        return num1 + num2;
    };
    
  • 如果箭头函数的代码块部分多于一条语句,需要使用大括号将其括起来

    var sum = (num1,num2) => {return num1 + num2;}
    
  • 由于大括号被解释为代码块,所以若箭头函数直接返回对象,必须在对象外面加上小括号

    var getTempItem = id => ({id:id, name:"Temp"});
    

3.2 箭头函数中的this

  • 箭头函数有以下几个注意事项:

    • 函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象
    • 不可以当作构造函数,即不可使用new命令,否则会报错
    • 不可以使用arguments对象,该对象在函数体内不存在,如果有需要可以使用rest参数代替
    • 不可以使用yield命令,因此箭头函数不能用作Generator函数
  • 其中最值得注意的一点就是箭头函数中this的指向:

    • this对象的指向是可变的,但在箭头函数中它是固定的
    • 箭头函数会让函数中的this绑定定义时所在的作用域,而不是指向运行时所在的作用域
    • this指向的固定化并不是因为箭头函数内部有绑定this的机制,而是因为箭头函数根本没有自己的this
    • 由于没有this,也就不能用call(),apply(),bind()这些方法去改变this的指向
  • 为了方便理解,下面给出差分实例

    普通对象方法

    这里的function作为obj1对象的方法出现,this指向obj1的对象本身

    var obj1 = {
        firstName: "Jackey",
        lastName: "Chen",
        getFullName: function(){
            console.log(this);
            return this.firstName + this.lastName;
        }
    }
    console.log(obj1.getFullName());	//JacktyChen
    

    带有函数的对象方法

    此处在方法中又添加了一个函数,由于函数执行的本质是window.[函数名],所以调用者就变成了window

    而window本身并不具有firstName和lastName,所以输出NaN

    var obj2 = {
        firstName: "Jackey",
        lastName: "Chen",
        getFullName: function(){
            var fn = function(){
                console.log(this);
                return this.firstName + this.lastName;
            }
            return fn();
        }
    }
    console.log(obj2.getFullName());	//NaN
    

    带有箭头函数的对象方法

    此处将方法中的函数替换成了箭头函数,由于箭头函数本身不具有this,它会向上一级寻找this,所以this就是obj3,可以正常调用

    var obj3 = {
        firstName: "Jackey",
        lastName: "Chen",
        getFullName: function(){
            var fn = () => {
                console.log(this);
                return this.firstName + this.lastName;
            }
            return fn();
        }
    }
    console.log(obj3.getFullName());
    

3.3 用途

  • 简化代码

    • map函数
    //正常写法
    [1,2,3].map(function(x){
       return x*x; 
    });
    
    //箭头函数
    [1,2,3].map(x => x*x);
    
    • sort函数
    //正常写法
    var result = values.sort(function(a,b){
        return a - b;
    });
    
    //箭头函数
    var result = values.sort((a,b) => a-b);
    
  • 封装回调函数

    var handler = {
        id:'123456',
        init:function(){
            document.addEventListener('click',event=>this.doSth(event.type),false);
        },
        doSth:function(type){
            console.log('Handling' + type + 'for' + this.id);
        }
    };
    

    解析:

    init方法使用到了对象内的doSth方法,但是doSth方法又使用到了this

    如果单独使用doSth方法是不会有任何问题的,因为在调用方法的时候this默认是指对象本身

    但是在init内,doSth是作为回调函数出现的,也就是说它的this指向的是function的上级,即window

    所以此处需要使用箭头函数,由于箭头函数没有自己的this,所以默认调用上一级的this,即init中的this,此时this便又指向了对象本身

查漏补缺:函数设置默认值后的length属性,函数设置默认值后的作用域,严格模式,name属性,绑定this

posted @   Solitary-Rhyme  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示