网易试题——关于箭头函数与this和arguments的关系

昨天做试题的时候遇到了这个题目

        var a = 1;
        function fn1() {
            console.log(this.a)
        }
        const fn2 = () => {
            console.log(this.a)
        }

        const obj = {
            a: 10,
            fn1: fn1,
            fn2: fn2
        }

        fn1()
        fn2()

        obj.fn1()
        obj.fn2()

哦这该死的网易,怎么出这么简单的题目,答案是:1,1,10,10   对,应该是这样的,吧?

可是再仔细一想,不对啊,我记得箭头函数的this对象好像不是在运行时基于函数的执行环境绑定的,他是有点奇怪的,事后仔细查了资料才知道,原来正确答案应该是 :1,1,10,1

一言概之,是因为:箭头函数的this和arguments只会从它自己所在作用域链的上一层继承,不会创建自己的this和argumrnts!!!(只有函数才会有this和arguments属性)

 让我再举几个例子给泥们looklook:

//普通函数

   var obj = {
            bar: function () {
                console.log(this); // 被obj调用,this指向{bar: ƒ}bar: ƒ ()__proto__: Object             
                var x = function() {
                    console.log(this)//Window对象
                };
                return x;//闭包,this通常(即不使用箭头函数的情况)默认为全局对象,若在严格模式则为undefined
            }
        };

        var fn = obj.bar();
        fn() ; 


//箭头函数
// 创建一个含有bar方法的obj对象,
        // bar返回一个函数,
        // 这个函数返回this,
        // 这个返回的函数是以箭头函数创建的,
        // 所以它的this被永久绑定到了它外层函数的this。
        // bar的值可以在调用中设置,这反过来又设置了返回函数的值。
        var obj = {
            bar: function () {
                console.log(this); // {bar: ƒ}bar: ƒ ()__proto__: Object             
                var x = (() => this);
                return x;
            }
        };

        // 作为obj对象的一个方法来调用bar,把它的this绑定到obj。
        // 将返回的函数的引用赋值给fn。
        var fn = obj.bar();//此时外层函数已经运行完毕,他的this已经绑定到{bar: ƒ}这个环境

        console.log(fn() === obj); // true
        console.log(fn()); // {bar: ƒ}bar: ƒ ()__proto__: Object  

        // 直接调用fn而不设置this,
        // 通常(即不使用箭头函数的情况)默认为全局对象
        // 若在严格模式则为undefined

        // 但是注意,如果你只是引用obj的方法,
        // 而没有调用它,this没有及时绑定到{bar: ƒ}这个环境
        var fn2 = obj.bar;
        // 那么调用箭头函数后,this指向window,因为它从 bar 继承了this。
        console.log(fn2()() == window); // true
        /* 此时等于在全局环境中调用 
        function () {
                console.log(this); // {bar: ƒ}bar: ƒ ()__proto__: Object             
                var x = (() => this);
                return x;
            }
        */

 再来一粒,这次带有arguments

  //普通函数
         var name = "The Window";
   
           var object = {
               name: "My Object",
   
               getNameFunc: function () {
                   console.log(arguments[0],'aa')//4
                   console.log(this.name)//"My Object"

                   return function () {//闭包,this通常指向window
                       console.log(arguments[0],'a')//5
                       return this.name;
                   };
               }
           };
   
           console.log(object.getNameFunc('4')('5'));  // The Window

//箭头函数
           var name = "The Window";
               
           var object = {
               name : "My Object",
               
               getNameFunc : function(a) {
                   console.log(this.name)//"My Object"
                   console.log(arguments[0],'aa')//4

                   return (a) => {
                       console.log(arguments[0],'a')//4,这里是继承了上一层的arguments
                       return this.name;    //虽然是闭包,但成功继承了上一层的this
                   };
               }
           };
               
           console.log(object.getNameFunc('4')('5'));  //"The Object"



//函数都是箭头函数
           var name = "The Window";
                       
           var object = {
               name : "My Object",
                       
               getNameFunc : (a) => {
                   console.log(this.name)//"The Window"
                   //console.log(arguments[0],'aa')//error

                   return (a) => {
                     //console.log(arguments[0],'a')//error
                     return this.name;    
                   };
               }
           };
                       
           console.log(object.getNameFunc('4')('5'));  //"The Window"
           //此时虽然是object调用了getNameFunc函数,但是箭头函数的this是指向上一层环境,即全局环境,所以this指向Window对象,而Window对象没有arguments,所以会出错

箭头函数还有一个值得注意的特性—— 无法使用call或者apply绑定this值。

由于 箭头函数没有自己的this指针,通过 call() 或 apply() 方法调用一个函数时,只能传递参数(不能绑定this),他们的第一个参数会被忽略。(这种现象对于bind方法同样成立)

          var name = "The Window";
                       
          var object = {
            name : "My Object",
                       
            getNameFunc : function(a) {
              console.log(this.name)//"outer"
              console.log(arguments[0],'aa')//4

              return (a) => {
                console.log(arguments[0],'a')//4
                return this.name;    
               };
           }
       };
                                                                                           
       console.log(object.getNameFunc.call({name:'outer'},'4').call({name:'inner'},'5'));  //"outer" 
  

再来一题,也是网易的

        function fun() {
            return () => {
                return () => {
                    return () => {
                        console.log(this.name)
                    }
                }
            }
        }
 
var f = fun.call({ name: 'foo' });
f.call({name:'1'})()()//foo
f().call({name:'2'})()//foo
f()().call({name:'3'})//foo 

 你做对了吗?

推荐阅读

this 指向详细解析(箭头函数)

箭头函数

this

JavaScript中的匿名函数及函数的闭包

彻底理解js中this的指向,不必硬背。

对匿名函数的深入理解(彻底版)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值