萌新关于 js 箭头函数 this 的问题,头好晕

2019-02-28 16:53:19 +08:00
 waibunleung

萌新想问一个关于箭头函数 this 的问题,看了好多例子还是理解不了。

代码:

var obj = {
    a : 12,
    b : () => {console.log(this)},
    c : {
        d: () => {console.log(this)},
        f: function(){console.log(this)}
    },
    e : function(){console.log(this)}
}

obj.b();
obj.c.d();
obj.c.f();
obj.e();

问题:obj.c.f();处打印出来的为什么是 window 对象而不是 obj 对象 ?

5059 次点击
所在节点    JavaScript
41 条回复
stillsilly
2019-02-28 16:57:55 +08:00
obj.c.f() 打印的是 c
wxsm
2019-02-28 16:58:31 +08:00
建议你 Google 一下箭头函数与普通函数的区别。
stillsilly
2019-02-28 16:58:47 +08:00
是 obj.c
不是你说的 window,也不是 obj
Exia
2019-02-28 16:59:55 +08:00
obj.c.f() 应该是 c 吧
dmjob2015222
2019-02-28 17:00:34 +08:00
貌似是打印 obj.c 吧,箭头就是一个语法,看看介绍就明白了
roscoecheung1993
2019-02-28 17:02:15 +08:00
obj.c.f() 打印的是 obj.c 啊...

var obj = {
a : 12,
b : () => {console.log(this)},
c : {
d: () => {console.log(this)},
f: function(){console.log(this); return this;}
},
e : function(){console.log(this)}
}

obj.b();
obj.c.d();
console.log(obj.c.f() === obj.c);
obj.e();
roscoecheung1993
2019-02-28 17:05:05 +08:00
把这坨代码粘贴到 babel 的 playground 里面,你就懂了
Mexion
2019-02-28 17:07:03 +08:00
楼上正解,c 是普通函数,谁调用它 this 就是谁,所以打印的是 c
而箭头函数中的 this 始终指向自身外的第一个 this,也就是始终等于调用它的函数的 this
Mexion
2019-02-28 17:08:16 +08:00
@Mexion 打错了,f 是普通函数,谁调用它 this 就是谁,所以打印的是 c
myl0204
2019-02-28 17:10:22 +08:00
问题:obj.c.d();处打印出来的为什么是 window 对象而不是 obj 对象 ?
binux
2019-02-28 17:14:37 +08:00
你想问的是 obj.c.d() 吧
so1n
2019-02-28 17:18:27 +08:00
rabbbit
2019-02-28 17:18:43 +08:00
@myl0204
1 this 是 function 的关键字,而箭头函数没有这个关键字
2 关键字其实本质上就是函数作用域里的一个变量

因为箭头函数里没有 this, 所以只能向上一层作用域里去找这个变量, 也就是 windows 了
Chingim
2019-02-28 17:28:10 +08:00
@myl0204 因为 d() 函数的 this 指向它外层的 this

问题变成了 c 的 this 是什么?

如果 c 是一个函数, 那调用 obj.c() , c 里的 this 肯定是 obj.
但是 c 不是一个函数, 它没有 this, obj 也没有 this

所以 d() 的外层的 this 就是 window 对象
waibunleung
2019-02-28 17:39:06 +08:00
@wxsm 这种东西我没 google 过我是不会上来问的,建议你下次不要提这种建议
waibunleung
2019-02-28 17:39:42 +08:00
@binux 对的对的
dmjob2015222
2019-02-28 18:00:15 +08:00
@waibunleung 你这 google 能力不行啊,这种问题 google 不出来???
almost00
2019-02-28 18:45:59 +08:00
// 你可以拷贝代码 到 jsbin 点 com 运行下试试
// 你不知道 this 是因为 你不用 call
// this 是 fn.call(this) 的 第一个参数
// 这是历史原因,js 作者创造 js 的一个需求就是 要求它像 java
// 所以你会看到很多 java 的面向对象写法,但是如果你是一个 js 程序员 就不会那样用
// 比如 js 你声明数组 var arr = [ ] java 就会这样 var arr = new Array( )
// 比如 var o = {} java 就要 var o = new Object()

// 默认当前环境是浏览器且没用 严格模式
function a(){console.log(this);}
a(); // window
// a() 等价于 a.call(undefined) 所以是 window
a.call(1); // 1
var o = {};
a.call(o); // o

var o2 = {};
o2.a = a;
o2.a(); // o2

console.log('----------华丽的分割线----------')
var b = ()=>{console.log(this);}
b();
b.call(1);
// ES6 的箭头函数干掉了 this 和 arguments 参数
// 所以就算你强行指定 this 也会指向外层的 this
a4854857
2019-02-28 19:05:33 +08:00
this 指向的固定化,并不是因为箭头函数内部有绑定 this 的机制,实际原因是箭头函数根本没有自己的 this,导致内部的 this 就是外层代码块的 this。正是因为它没有 this,所以也就不能用作构造函数。

所以,箭头函数转成 ES5 的代码如下。

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

// ES5
function foo() {
var _this = this;

setTimeout(function () {
console.log('id:', _this.id);
}, 100);
}

上面代码中,转换后的 ES5 版本清楚地说明了,箭头函数里面根本没有自己的 this,而是引用外层的 this。

http://es6.ruanyifeng.com/#docs/function#%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0
DOLLOR
2019-02-28 19:15:14 +08:00
箭头函数并没有 this,如果你在箭头函数里写 this,实际上这个 this 属于它外层的普通函数,而不属于这个箭头函数。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/539691

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX