箭头函数this指向的陷阱

箭头函数没有this
箭头函数没有this!!
箭头函数没有this!!!

重要的事情说三遍!


那你可能要问我在箭头函数中明明可以取到this啊!

function foo() {
  this.a = 1
  let b = () => console.log(this.a)

  b()
}

foo()  // 1

以上箭头函数中的this其实是父级作用域中的this,箭头函数引用了父级作用域的变量,构成了一个闭包。

以上代码等价于:

function foo() {
  this.a = 1

  let self = this
  let b = () => console.log(self.a)

  b()
}

foo()  // 1

箭头函数不仅没有this,常用的arguments也没有。如果你能获取到arguments,那它一定是来自于父级作用域

function foo() {
  return () => console.log(arguments[0])
}

foo(1, 2)(3, 4)  // 1

如果箭头函数有arguments,就应该输出3而不是1。
一个常犯的错误是使用箭头函数定义对象的方法,如:

let a = {
  foo: 1,
  bar: () => console.log(this.foo)
}

a.bar()  //undefined

以上代码中,箭头函数中的this指向并不是指向a这个对象。对象a并不能构成一个作用域,所以再往上到达全局作用域this就指向全局作用域。如果我们使用普通函数的定义方法,输出结果就能符合预期,这是因为a.bar()函数执行时作用域绑定到了a对象。

let a = {
  foo: 1,
  bar: function() { console.log(this.foo) }
}

a.bar()  // 1

以上文章提到了this指向和作用域概念,这里进一步介绍下。

this指向

首先必须要说的是,this的指向在函数定义时是确定不了的,只有函数执行时才能确定,实际上this最终指向的是调用它的对象。

在函数没有调用时,this的值无法确定。

还是拿例子来说明,

扫描二维码关注公众号,回复: 6106563 查看本文章
function a(){
    var user = "追梦子";
    console.log(this.user); //undefined
    console.log(this); //Window
}
a();

因为this最终指向的是调用它的对象,函数a实际上是被window调用的。
再来个例子。

var o = {
    user:"追梦子",
    fn:function(){
        console.log(this.user);  //追梦子
    }
}
o.fn();

这里this指向o,好像没什么好说的,最终指向调用它的对象。
好了,看到这里还不要骄傲,下面几个例子才有真正的坑。

var o = {
    a:10,
    b:{
        // a:12,
        fn:function(){
            console.log(this.a); //undefined
        }
    }
}
o.b.fn();

这是因为this指向的是上一级调用的对象,而不能一级一级往上寻找。

作用域

刚才讲到普通函数的this指向是运行时确定的,然而,不同的是,

JavaScript中的作用域是的嵌套关系是定义时确定的。

也就是说,JavaScript的作用域是静态作用域,又叫词法作用域,这是因为作用域的嵌套关系在语法分析时就可以确定,而不是在运行时确定。
例如,

var scope = 'top';
  var f1 = function() { 
      console.log(scope);
  };
  f1(); // 输出 top
  var f2 = function() { 
      var scope = 'f2'; 
      f1();
  };
   f2(); // 输出 top`

参考

https://jingsam.github.io/2016/12/08/things-you-should-know-about-arrow-functions.html
https://segmentfault.com/a/1190000004589779
https://juejin.im/entry/589be5b1b123db16a3bec5c2
https://juejin.im/post/5aa1eb056fb9a028b77a66fd
https://segmentfault.com/a/1190000018119191

猜你喜欢

转载自blog.csdn.net/colinandroid/article/details/89525952