箭头函数this指向的问题

function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

var id = 21;

foo.call({ id: 42 });
// id: 42

箭头函数内部的this是指向定义时所在的对象,不是执行时所在的对象。按照这个道理的话,setTimeout内部的函数不管是不是箭头函数应该都是指向window啊。定义的时候,内部的this不应该指向window,执行的时候才是指向调用的对象{ id: 42 }吗?求教

阅读 966
评论
    17 个回答

    明确两件事

    1. 箭头函数的this在定义时就确定,就是所在作用域
    2. function的this只有调用时能确定,明白这两点才能继续
    function foo() {
      setTimeout(() => {
        console.log('id:', this.id);
      }, 100);
    }
    
    var id = 21;
    
    foo.call({ id: 42 });
    1. function foo内部的箭头函数跟function foo一致
    2. 接下来看function foo的this怎么确定,看到调用方式是用的call,这里this为{id:42}这个对象

    如果是foo({id:42}),那么this是undefined或window(取决于严格模式)

      • 2.2k

      你可以理解成箭头函数写在哪里,就获取哪里的this
      这里明显就直接读取foo的执行环境中的this,而foo被你强制绑定到{ id: 42 }上,所以this自然指向这个对象。

        • 2.8k

        call()apply()方法会改变this的指向。

          • 3.7k

          this不是window,而是{id:42},function的this不是window,foo.call的第一个参数就是foo函数里面的this.

          function foo() {
          var x=this;
          setTimeout(() => {

          var y=this;
          console.log('id:', this.id);

          }, 100);
          }

          定义时的this,指的是x和y都是指向同一个this,显然x是{id:42},所以y也是。

            这里箭头函数中的 this 即函数 foo 里的 this。直接调用时 this.idwindow.id;使用 call 时将 foo 的 this 指向了 {id: 42} 对象,此时 this.id 为 42。

            foo(); // id: 21
            foo.call({ id: 42 }); // id: 42

              因为.call()方法是先将foo的this值绑定到obj对象上,再执行foo 如果含有id就不会在继续在原型链中找了

              function foo() {
                setTimeout(() => {
                  console.log('id:', this.id);
                }, 100);
                
                this.fun =()=>{
                  console.log(this);
                }
              }
              var id = 21;
              var obj = { id: 42 };
              
              foo.call(obj);
              
              console.log(obj)

              clipboard.png

                箭头函数没有自己的this, 它的this是继承而来。默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象。比如:

                function a() { 
                   console.log(this);  //window
                }  
                a(); 

                写到这里相信你应该明白了吧~

                原本foothiswindow的,后来call之后this指向变成{id: 42}了。
                所以执行的是foo.call({}),而不是foo()本身。(这里很关键!)

                如果此时你再去执行foo() ,打印的还是21

                  • 483

                  foo没执行,setTimeout里面箭头函数还没定义啊,就像下面的fun,没有执行foo时候内存是没有fun这个函数的
                  严格来说 “箭头函数内部的this是指向定义时所在的对象”不对的,箭头函数是没有this的,它只会从自己的作用域链的上一层继承this,规则就和下面代码的变量ttt一样;
                  最后看看MDN关于箭头函数的解释

                  var ttt = '888'
                  function foo() {
                    var ttt = '999'
                    setTimeout(() => {
                      console.log(ttt) // 999
                      console.log('id:', this.id);
                    }, 100);
                  
                    var fun = () => {console.log(this.id)}
                    setTimeout(fun, 100)
                  }
                    • 556

                    如果只是想了解箭头函数this指向的问题,我这个例子不知道能不能帮到你

                    var test = {

                    aa:function(){
                        console.log(this);
                        setTimeout(function(){
                            console.log(this)
                        },1)
                    },
                    bb(){
                        console.log(this);
                        setTimeout(()=>{
                            console.log(this)
                        })
                    }};
                    
                    test.aa()
                        >{aa: ƒ, bb: ƒ}
                        >Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
                        
                    test.bb()
                        >{aa: ƒ, bb: ƒ}
                        >{aa: ƒ, bb: ƒ}
                     

                      1.普通函数调用 this 指向 window

                      function fn() {
                          console.log(this);
                      }
                      window.fn();
                      

                      2.方法调用 this 指向 调用该方法的对象

                      var obj = {
                          fun: function () {
                              console.log(this);
                          }
                      }
                      obj.fun();
                      

                      3.作为构造函数的调用 构造函数内部的this指向由该构造函数创建的对象

                      var gf = {
                          name : "tangwei",
                          bar : "c++",
                          sayWhat : function() {
                              console.log(this.name + "said:love you forever");
                          }
                      }
                      

                      4.作为事件的处理函数 触发该事件的对象

                      btn.onclick = function () {
                          console.log(this);
                      }
                      

                      5.作为定时器的参数 this 指向 window

                      setInterval(function() {
                          console.log(this);
                      }, 1000);
                      

                      总结:函数内部的this,是由函数调用的时候来确定其指向的

                        箭头函数的this指向由其定义时所在的上下文环境决定。

                          • 2.3k

                          你要是直接 foo() ,那就是指向全局,但是你写了 foo.call(),就会指向你传入的这个对象。
                          因为箭头函数中的 this 会捕获它外层的 this 指向。

                            • 550
                            fun.call(thisArg, arg1, arg2, ...)

                            其中 thisArg 为函数运行时指定的 this 值。

                            你这里 foo 方法运行时,指定的对象为 { id: 42 } ,那么 this.id 当然是 42

                            参考MDN:https://developer.mozilla.org...

                              箭头函数导致this总是指向函数定义生效时所在的对象,而普通函数则是定义生效的时候。这里箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到 100 毫秒后,100秒后生效时所在对象是{id:42}。
                              http://es6.ruanyifeng.com/#do...

                              另外 call在这里改变了函数的作用域,使其指向{id:42}

                                setTimeOut所传递的函数中的this,会指向全局对象(window)。但是箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this.

                                所以应该使用foo函数作用域中的this,即使用call指定的{id:42}对象

                                  • 881
                                  哇好多答案!

                                  忍不住也跟一波.

                                  call改变了this的指向

                                    function foo() {
                                      //1、首先箭头函数没有this,这个你也说了
                                      setTimeout(() => {
                                      2、这里的this会像(原型链)一样往上找所在的作用域,找到当前所在的函数作用域
                                        console.log('id:', this.id);
                                      }, 100);
                                    }
                                    
                                    var id = 21;
                                    //3、默认当前所在函数作用域是window,当前作用域又通过call改变了this的指向,所以最后执行结果为call指向的this。
                                    foo.call({ id: 42 });
                                    // id: 42

                                    对比问题我来以注释形式描述下我的理解

                                      撰写回答

                                      登录后参与交流、获取后续更新提醒

                                      相似问题
                                      推荐文章