上面代码中,person.say2()方法是一个箭头函数,调用person.say2()时,使得this指向全局对象,因此不会得到预期结果。这是因为对象不构成单独的作用域,导致say2()箭头函数定义时的作用域就是全局作用域。而say()定义的是一个普通函数,它内部的this就指向调用它的那个对象,所以使用普通函数符合预期。
当函数需要动态this时 var button = document.querySelector('.btn'); button.addEventListener('click', () => { this.classList.toggle('on'); });这里很显然会报错,因为按钮点击的回调是一个箭头函数,而箭头函数内部的this永远都是指向它的上层作用域中的this,在这里就是window,所以会报错。这里只需要将箭头函数改成普通函数就能正常调用了!
看完来做个题吧~ var name = '南玖' function Person (name) { this.name = name this.foo1 = function () { console.log(this.name) }, this.foo2 = () => console.log(this.name), this.foo3 = function () { return function () { console.log(this.name) } }, this.foo4 = function () { return () => { console.log(this.name) } } } var person1 = new Person('nan') var person2 = new Person('jiu') person1.foo1() // 'nan' person1.foo1.call(person2) // 'jiu' person1.foo2() // 'nan' person1.foo2.call(person2) // 'nan' person1.foo3()() // '南玖' person1.foo3.call(person2)() // '南玖' person1.foo3().call(person2) // 'jiu' person1.foo4()() // 'nan' person1.foo4.call(person2)() // 'jiu' person1.foo4().call(person2) // 'nan'解析:
全局代码执行,person1 = new Person('nan'),person2 = new Person('jiu')执行完,person1中的this.name为nan,person2中的this.name为jiu,OK这一点清楚后,继续往下看:
执行person1.foo1(),foo1为普通函数,所以this应该指向person1,打印出nan
执行person1.foo1.call(person2),foo1为普通函数,并且用call改变了this指向,所以它里面的this应该指向person2,打印出jiu
执行person1.foo2(),foo2为箭头函数,它的this指向上层作用域,也就是person1,所以打印出nan
执行person1.foo2.call(person2),箭头函数的this指向无法使用call改变,所以它的this还是指向person1,打印出nan
执行person1.foo3()(),这里先执行person1.foo3(),它返回了一个普通函数,接着再执行这个函数,此时就相当于在全局作用域中执行了一个普通函数,所以它的this指向window,打印出南玖
执行person1.foo3.call(person2)()这个与上面类似,也是返回了一个普通函数再执行,其实前面的执行都不用关心,它也是相当于在全局作用域中执行了一个普通函数,所以它的this指向window,打印出南玖
执行person1.foo3().call(person2)这里就是把foo3返回的普通函数的this绑定到person2上,所以打印出jiu
执行person1.foo4()(),先执行person1.foo4()返回了一个箭头函数,再执行这个箭头函数,由于箭头函数的this始终指向它的上层作用域,所以打印出nan
执行person1.foo4.call(person2)(),与上面类似只不过使用call把上层作用域的this改成了person2,所以打印出jiu
执行person1.foo4().call(person2),这里是先执行了person1.foo4(),返回了箭头函数,再试图通过call改变改变该箭头函数的this指向,上面我们说到箭头函数的this始终指向它的上层作用域,所以打印出nan
推荐阅读前端常见的安全问题及防范措施
为什么大厂前端监控都在用GIF做埋点?
介绍回流与重绘(Reflow & Repaint),以及如何进行优化?
Promise、Generator、Async有什么区别?
JS定时器执行不可靠的原因及解决方案
从如何使用到如何实现一个Promise
超详细讲解页面加载过程
原文首发地址,欢迎大家关注公众号 「前端南玖」
我是南玖,我们下期见!!!