zoukankan      html  css  js  c++  java
  • 深入理解this机制系列第三篇——箭头函数

    前面的话

      this机制函数调用有关,而作用域则与函数定义有关。有没有什么是可以将this机制和作用域联系起来的呢?本文将介绍ES6新增的内容——箭头函数

    痛点

      对于闭包的痛点在于,闭包的this默认绑定到window对象,但又常常需要访问嵌套函数的this,所以常常在嵌套函数中使用var that = this,然后在闭包中使用that替代this,使用作用域查找的方法来找到嵌套函数的this值 

    var a = 0;
    function foo(){
        function test(){
            console.log(this.a);
        }
        return test;
    };
    var obj = {
        a : 2,
        foo:foo
    }
    obj.foo()();//0
    var a = 0;
    function foo(){
        var that = this;
        function test(){
            console.log(that.a);
        }
        return test;
    };
    var obj = {
        a : 2,
        foo:foo
    }
    obj.foo()();//2

    解决

      而箭头函数的出现就可以很好的解决该问题。箭头函数根据当前的词法作用域而不是根据this机制顺序来决定this,所以,箭头函数会继承外层函数调用的this绑定,而无论this绑定到什么

    var test = () => {
        console.log(this.a);
    }
    //形式上等价于
    var test = function(){
        console.log(this.a);
    }
    //实质上等价于
    function fn(){
        var that = this;
        var test = function(){
            console.log(that.a);
        }
    }
    var a = 0;
    function foo(){
        var test = () => {
            console.log(this.a);
        }
        return test;
    };
    var obj = {
        a : 2,
        foo:foo
    }
    obj.foo()();//2

    基本用法

      ES6允许使用“箭头”(=>)定义函数,一般称为胖箭头

    var f = v => v;
    console.log(f(1));//1
    //等同于
    var f = function(v) {
      return v;
    };
    console.log(f(1));//1

      如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分

    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) => { 
        var restult = num1 + num2;
        return result; 
    }

      由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号

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

    回调函数

      箭头函数最常用于回调函数,如事件处理器或定时器中

    function foo() {
        setTimeout(() => {
            console.log( this.a );
        },100);
    }
    var obj = {
        a: 2
    };
    foo.call( obj ); // 2
    //等价于
    function foo() {
        var that = this; 
        setTimeout( function(){
            console.log( that.a );
        }, 100 );
    }
    var obj = {
        a: 2
    };
    foo.call( obj ); // 2

    注意事项

      【1】this在箭头函数中被绑定,4种绑定规则中的无论哪种都无法改变其绑定

    var a = 0;
    function foo(){
        var test = () => {
            console.log(this.a);
        }
        return test;
    };
    var obj1 = {
        a : 1,
        foo:foo
    }
    var obj2 = {
        a : 2,
        foo:foo    
    }
    obj1.foo()();//1
    var bar = foo.call(obj1);
    //由于上一条语句已经把this绑定到obj1上,且无法修改。所以本条语句call(obj2)无效,返回的值是obj1.a的值1
    bar.call(obj2);//1

      【2】箭头函数不可以当作构造函数,也就是不可以使用new命令,否则会报错

    var foo = () =>{return 1;}
    foo();//1
    var obj = new foo();//Uncaught TypeError: foo is not a constructor

      【3】箭头函数中不存在arguments对象

    var foo = () =>{
        console.log(arguments);//Uncaught ReferenceError: arguments is not defined
        return 1;
    }
    foo();

    最后

      虽然箭头函数可以把作用域和this机制联系起来,但是却容易混淆,使代码难以维护。应该在作用域和this机制中二选一,否则它们就真的汇成一锅粥了。或者只使用词法作用域,或者只使用this机制,必要时使用bind()。尽量避免使用that=this和箭头函数

      this机制系列介绍完了。最重要的还是第一篇this机制的绑定原则,第二篇this机制的优先级属于要点,而本篇则是拓展部分。如有不妥之处,欢迎交流

      以上

  • 相关阅读:
    HTML5 表单新增属性
    js中获取css属性
    Java 枚举(enum)【感觉不是很常用】
    Java数组
    Java的反射机制
    IO,NIO【重点掌握】,Socket,Channel等的网络编程
    多线程
    注解
    动态代理
    动态编译
  • 原文地址:https://www.cnblogs.com/xiaohuochai/p/5737876.html
Copyright © 2011-2022 走看看