前言

今天在做项目遇到箭头函数this指向问题:

export default {
    data() {
        return {
        name: 'Hello World'
      }
    },
    methods: {
        getName6: () => {
            console.log(this.name); //=>undefined
        }
    }
}

发现在控制台输出undefined,原本一时没想到,然后经过同事提醒,突然明白箭头函数的this并非是普通函数的this,故引起对此探讨研究和一些笔记。

基本

MDN文档对于箭头函数解释:箭头函数表达式的语法比函数表达式更短,并且没有自己的this,arguments,super或 new.target。这些函数表达式更适用于那些本来需要匿名函数的地方,并且它们不能用作构造函数。

全局和函数:

如果不理解可以从头再来看看,在普通函数或者在全局对象中this指向的是window对象:

console.log(this); //=>全局代码, 输出window对象
 
function hello() {
    console.log(this);
}
hello(); //=>函数输出,输出window对象

对象方法:

var obj = {
    name:'Hello'
  };
 
  function foo(){
    console.log(this);
  }
  obj.newFoo = foo;
  obj.newFoo(); //=> {name: "test",newFoo: ƒ foo()}

上面的this指向调用该方法的对象,如果在控制台你会看到下面的信息:

{
    arguments: null,
    caller: null,
    length: 0,
    name: "foo"
}

构造方法:

function hello(){
    this.name = 'test';
    this.age = 18;
    console.log(this);
}
var h = new hello(); //=>hello {name: "test", age: 18}
console.log(c); //=> hello {name: "test", age: 18}
var w = hello(); //=> 输出window对象

诸如上面几种方法,觉得this调用是在是太莫名其妙的,所以javascript吐槽得太恶心。

所以为了让this正确指向作用一般采用全局this使用self替代或者使用bind()方法。

所以箭头函数的this永远指向函数定义时的this值:

var C = function(){
  this.name = 'test';
  this.greet = () => {
    console.log('Hello,I am '+ this.name + '!');
  };
  this.oldGreet = function() {
    console.log('Hello,I am '+ this.name + '!');
  }
}
var obj = new C();
obj.greet();                 //=>Hello,I am test!
setTimeout(obj.greet, 1000); //=>输出 Hello,I am test!

总结

在函数被传递后, 如果使用了箭头函数, this 最终将指向其定义处上下文的 this 对象。

箭头函数和普通函数一个很大的区别在于箭头函数不仅不重新绑定作用域,而且箭头函数的作用域不可以被重新绑定, 这是造成上述行为差异的原因。所以针对开头那段代码完全可以修改成这样:

export default {
    data() {
        return {
        name: 'Hello World'
      }
    },
    methods: {
        getName6: function() {
            () => {
                console.log(this); //=>Hello World
            }
        }
    }
}

虽然箭头函数看来很美观并且使用方便,但在开发项目需要根据自身情况而定,如果不明确this指定方向请不要滥用箭头函数。

"箭头函数" 的 this, 总是指向定义时所在的对象, 而不是运行时所在的对象

参考资料:

关于箭头函数this的理解几乎完全是错误的

MDN

ES6 箭头函数中的 this?你可能想多了