let user = { firstName: "John", sayHi() { alert(`Hello, ${this.firstName}!`); } }; firstName = "spicyLemon" user.sayHi();
结果是什么?
显而易见是Hello,John。
因为这里是user调用的sayHi函数,所以this指向的自然就是user。这和我上面说的结论是一致的。
总结:this的指向是在调用时决定的,和书写的位置没有关系,这一点和闭包还有箭头函数刚刚好时相反的。(大多数情况下)
这里是一个小测验,如果你真正理解了上面的内容,那么应该不难。
var me = { name: 'xiuyan', hello: function() { console.log(`你好,我是${this.name}`) } } var you = { name: 'xiaoming', hello: function() { var targetFunc = me.hello targetFunc() } } var name = 'BigBear' you.hello()
先思考一下再看答案。
如果你对了,那么恭喜你已经掌握this的基本指向规则了(也许)。如果你错了,那么请再仔细揣摩上面的内容。
答案是:BigBear
这是第一例的变体
let user = { firstName: "John", sayHi() { alert(`Hello, ${this.firstName}!`); } }; firstName = "spicyLemon" setTimeout(user.sayHi, 1000);
看完了么,来吧,说输出。
Hello,spicyLemon
这个时候肯定有人有疑惑了。
啊,博主你刚刚不是说谁调用的函数this就归谁么,这里确实是user来调用的啊。
那是因为,这些回调都是在全局作用域下实现的。
无论是 setTimeout 还是 setInterval 里传入的函数,都会首先被交付到全局对象手上。
我们可以理解为,函数直接被整个交给了setTimeout,然后由setTimeout来调用
这时就不是user来调用了
因此,函数中 this 的值,会被自动指向 window。
这里和setTimeout是一样的,我就不再多做赘述了。
由于我们这一篇博客讲的是this指向,我就不再IIFE上多做赘述,这里直接上代码。
不了解的同学可以查看一下资料再回来看代码,我的IIFE是在红宝书(第四版)的314页看的,有书的同学可以直接翻看。
var name = 'spicyLemon' var me = { name: 'xiuyan', sayHello: function() { console.log(`你好,我是${this.name}`) }, hello: function() { (function(cb) { cb() })(this.sayHello) } } me.hello()
来吧,展示你们的输出相信经过这几分钟的锤炼你已经很难再错了。
答案是:你好,我是spicyLemon
不管怎么样,这三个所谓的特殊情况里的this判断,还是离不开我开头说的this指向原则
多数情况下(99%)这三种情况的this都指向window
真传一句话,假传万卷书。我们直接说结论:箭头函数它没有自己的this,它的this是别人的,是定义它的对象的this。(这里不太严谨,但是比较好理解)
看代码
var name = 'BigBear' var me = { name: 'xiuyan', hello: () => { console.log(this.name) } } me.hello()
答案是spicyLemon
箭头函数比较特殊,这里我来一步一步引导大家
于是答案就解释的通了
箭头函数中的 this 比较特别,它和严格模式、非严格模式啥的都没关系。它和闭包很相似,都是 认“死理”——
认“词法作用域”的家伙。所以说箭头函数中的 this,和你如何调用它无关,由你书写它的位置决定(和咱们普通函数的 this规则恰恰相反~)
箭头函数正是由于没有自己的this所以它可以在那些没有自己的“上下文”,但在当前上下文中起作用的短代码的使用场景中大放异彩。
如有错误,请在评论区指正,看到后会修改。不明白的可以私信问我(虽然我也不是特别明白哈哈哈)