做者:Dmitri Pavlutin
来源:dmitripavlutin
译者:前端小智
点赞再看,养成习惯本文
GitHub
https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类,也整理了不少个人文档,和教程资料。欢迎Star和完善,你们面试能够参照考点复习,但愿咱们一块儿有点东西。前端
你们都说简历没项目写,我就帮你们找了一个项目,还附赠【搭建教程】。git
我喜欢在JS中更改函数执行上下文的指向,也称为 this
指向。github
例如,我们能够在类数组对象上使用数组方法:面试
const reduce = Array.prototype.reduce; function sumArgs() { return reduce.call(arguments, (sum, value) => { return sum += value; }); } sumArgs(1, 2, 3); // => 6
另外一方面,this
很难把握。数组
我们常常会发现本身用的 this
指向不正确。下面的教你如何简单地将 this
绑定到所需的值。浏览器
在开始以前,我须要一个辅助函数execute(func)
,它仅执行做为参数提供的函数。微信
function execute(func) { return func(); } execute(function() { return 10 }); // => 10
如今,继续理解围绕this
错误的本质:方法分离。函数
假设有一个类Person
包含字段firstName
和lastName
。此外,它还有一个方法getFullName()
,该方法返回此人的全名。以下所示:工具
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = function() { this === agent; // => true return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智'
能够看到Person
函数做为构造函数被调用:new Person('前端', '小智')
。 函数内部的 this
表示新建立的实例。this
getfullname()
返回此人的全名:'前端 小智'
。正如预期的那样,getFullName()
方法内的 this
等于agent
。
若是辅助函数执行agent.getFullName
方法会发生什么:
execute(agent.getFullName); // => 'undefined undefined'
执行结果不正确:'undefined undefined'
,这是 this
指向不正确致使的问题。
如今在getFullName()
方法中,this
的值是全局对象(浏览器环境中的 window
)。 this
等于 window
,${window.firstName} ${window.lastName}
执行结果是 'undefined undefined'
。
发生这种状况是由于在调用execute(agent.getFullName)
时该方法与对象分离。 基本上发生的只是常规函数调用(不是方法调用):
execute(agent.getFullName); // => 'undefined undefined' // 等价于: const getFullNameSeparated = agent.getFullName; execute(getFullNameSeparated); // => 'undefined undefined'
这个就是所谓的方法从它的对象中分离出来,当方法被分离,而后执行时,this
与原始对象没有链接。
为了确保方法内部的this
指向正确的对象,必须这样作
agent.getFullName()
this
绑定到包含的对象(使用箭头函数、.bind()
方法等)方法分离问题,以及由此致使this
指向不正确,通常会在下面的几种状况中出现:
回调
// `methodHandler()`中的`this`是全局对象 setTimeout(object.handlerMethod, 1000);
在设置事件处理程序时
// React: `methodHandler()`中的`this`是全局对象 <button onClick={object.handlerMethod}> Click me </button>
接着介绍一些有用的方法,即若是方法与对象分离,如何使this
指向所需的对象。
保持this
指向类实例的最简单方法是使用一个额外的变量self
:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; const self = this; this.getFullName = function() { self === agent; // => true return `${self.firstName} ${self.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
getFullName()
静态地关闭self
变量,有效地对this
进行手动绑定。
如今,当调用execute(agent.getFullName)
时,一切工做正常,由于getFullName()
方法内 this
老是指向正确的值。
有没有办法在没有附加变量的状况下静态绑定this
? 是的,这正是箭头函数的做用。
使用箭头函数重构Person
:
function Person(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = () => `${this.firstName} ${this.lastName}`; } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
箭头函数以词法方式绑定this
。 简单来讲,它使用来自其定义的外部函数this
的值。
建议在须要使用外部函数上下文的全部状况下都使用箭头函数。
如今让我们更进一步,使用ES6中的类重构Person
。
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => 'undefined undefined'
不幸的是,即便使用新的类语法,execute(agent.getFullName)
仍然返回“undefined undefined”
。
在类的状况下,使用附加的变量self
或箭头函数来修复this
的指向是行不通的。
可是有一个涉及bind()
方法的技巧,它将方法的上下文绑定到构造函数中:
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; this.getFullName = this.getFullName.bind(this); } getFullName() { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
构造函数中的this.getFullName = this.getFullName.bind(this)
将方法getFullName()
绑定到类实例。
execute(agent.getFullName)
按预期工做,返回'前端 小智'
。
bind
方式有点太过冗长,我们可使用胖箭头的方式:
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName = () => { return `${this.firstName} ${this.lastName}`; } } const agent = new Person('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
胖箭头方法getFullName =() =>{…}
绑定到类实例,即便将方法与其对象分离。
这种方法是在类中绑定this
的最有效和最简洁的方法。
与对象分离的方法会产生 this 指向不正确问题。静态地绑定this
,能够手动使用一个附加变量self
来保存正确的上下文对象。然而,更好的替代方法是使用箭头函数,其本质上是为了在词法上绑定this
。
在类中,可使用bind()
方法手动绑定构造函数中的类方法。固然若是你不用使用 bind
这种冗长方式,也可使用简洁方便的胖箭头表示方法。
原文:https://github.com/valentinog...
代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug。
文章每周持续更新,能够微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,另外关注公众号,后台回复福利,便可看到福利,你懂的。