You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constamerica={name: 'The United States of America',yearFounded: 1776,describe(){console.log(`${this.name} was founded in ${this.yearFounded}.`)},}america.describe()
Output"The United States of America was founded in 1776."
constamerica={name: 'The United States of America',yearFounded: 1776,details: {symbol: 'eagle',currency: 'USD',printDetails(){console.log(`The symbol is the ${this.symbol} and the currency is ${this.currency}.`)},},}america.details.printDetails()
Output"The symbol is the eagle and the currency is USD."
functionCountry(name,yearFounded){this.name=namethis.yearFounded=yearFoundedthis.describe=function(){console.log(`${this.name} was founded in ${this.yearFounded}.`)}}constamerica=newCountry('The United States of America',1776)america.describe()
Output"The United States of America was founded in 1776."
classCountry{constructor(name,yearFounded){this.name=namethis.yearFounded=yearFounded}describe(){console.log(`${this.name} was founded in ${this.yearFounded}.`)}}constamerica=newCountry('The United States of America',1776)america.describe()
describe方法中的this指向Country的实例,即america。
Output"The United States of America was founded in 1776."
constbraveNewWorldSummary=summary.bind(book)braveNewWorldSummary()// Brave New World was written by Aldous Huxley.constbook2={title: '1984',author: 'George Orwell',}braveNewWorldSummary.bind(book2)braveNewWorldSummary()// Brave New World was written by Aldous Huxley.
this
关键词在JavaScript
中是个很重要的概念,也是一个对初学者和学习其他语言的人来说晦涩难懂。在JavaScript
中,this
是一个对象的引用。this
指向的对象可以是基于全局的,在对象上的,或者在构造函数中隐式更改的,当然也可以根据Function
原型方法的bind
,call
和apply
使用显示更改的。尽管
this
是个复杂的话题,但是也是你开始编写第一个JavaScript
程序后出现的话题。无论你尝试访问the Document Object Model (DOM)中的元素或事件,还是以面向对象的编程风格来构建用于编写的类,还是使用常规对象的属性和方法,都见遇到this
。在这篇文章中,你将学习到基于上下文隐式表示的含义,并将学习如何使用
bind
,call
和apply
方法来显示确定this
的值。隐式上下文
在四个主要上下文中,我们可以隐式地推断出
this
的值:全局
在全局上下文中,
this
指向全局对象。当你使用浏览器,全局上下文将是window
。当你使用Node.js,全局上下文就是global
。针对例子,你可以在浏览器的开发者工具栏中验证。如果你不是很熟悉在浏览器中运行
JavaScript
代码,可以去阅读下How to Use the JavaScript Developer Console 文章。如果你只是简单打印
this
,你将看到this
指向的对象是什么。你可以看到,
this
就是window
,也就是浏览器的全局对象。在Understanding Variables, Scope, and Hoisting in JavaScript中,你学习到函数中的变量有自己的上下文。你可能会认为,在函数内部
this
会遵循相同的规则,但是并没有。顶层的函数中,this
仍然指向全局对象。你可以写一个顶层的函数,或者是一个没有关联任何对象的函数,比如下面这个:
即使在一个函数中,
this
仍然指向了window
,或全局对象。然而,当使用严格模式,全局上下文中,函数内
this
的上下文指向undefined
。总的来说,使用严格模式更加安全,能减少
this
产生的非预期作用域的可能性。很少有人想直接将this
指向window
对象。对象方法
一个方法是对象上的函数,或对象可以执行的一个任务。方法使用
this
来引用对象的属性。在这个例子中,
this
等同于america
。在嵌套对象中,
this
指向方法当前对象的作用域。在下面这个例子,details
对象中的this.symbol
指向details.symbol
。另一种思考的方式是,在调用方法时,
this
指向.
左侧的对象。函数构造器
当你使用new关键字,会创建一个构造函数或类的实例。在
ECMAScript 2015
更新为JavaScript
引入类语法之前,构造函数是初始化用户定义对象的标准方法。在Understanding Classes in JavaScript中,你将学到怎么去创建一个函数构造器和等效的类构造函数。在这个上下文中,现在
this
绑定到Country
的实例,该实例包含在America
常量中。类构造器
类上的构造函数的作用与函数上的构造函数的作用相同。在Understanding Classes in JavaScript中,你可以了解到更多的关于构造函数和
ES6
类的相似和不同的地方。describe
方法中的this
指向Country
的实例,即america
。DOM事件处理程序
在浏览器中,事件处理程序有一个特殊的
this
上下文。在被称为addEventListener
调用的事件处理程序中,this
将指向event.currentTarget
。开发人员通常会根据需要简单地使用event.target
或event.currentTarget
来访问DOM
中的元素,但是由于this
引用在此上下文中发生了变化,因此了解这一点很重要。在下面的例子,我们将创建一个按钮,为其添加文字,然后将它追加到DOM中。当我们使用事件处理程序打印其
this
的值,它将打印目标内容。如果你复制上面的代码到你的浏览器运行,你将看到一个有
Click me
按钮的页面。如果你点击这个按钮,你会看到<button>Click me</button>
出现在控制台上,因为点击按钮打印的元素就是按钮本身。因此,正如你所看到的,this
指向的目标元素,就是我们向其中添加了事件监听器的元素。显式上下文
在所有的先前的例子中,
this
的值取决于其上下文 -- 在全局的,在对象中,在构造函数或类中,还是在DOM
事件处理程序上。然而,使用call, apply
或bind
,你可以显示地决定this
应该指向哪。决定什么时候使用
call, apply
或bind
是一件很困难的事情,因为它将决定你程序的上下文。当你想使用事件来获取嵌套类中的属性时,bind
可能有用。比如,你写一个简单的游戏,你可能需要在一个类中分离用户接口和I/O
,然后游戏的逻辑和状态是在另一个类中。由于游戏逻辑需要用户输入,比如按键或点击事件,你可能想要bind
事件去获取游戏逻辑类中的this
的值。最重要的部分是,要知道怎么决定
this
对象指向了哪,这样你就可以像之前章节学的隐式操作那样操作,或者通过下面的三种方法显示操作。Call 和 Apply
call
和apply
非常相似--它们都调用一个带有特定this
上下文和可选参数的函数。call
和apply
的唯一区别就是,call
需要一个个的传可选参数,而apply
只需要传一个数组的可选参数。在下面这个例子中,我们将创建一个对象,创建一个
this
引用的函数,但是this
没有明确上下文(其实this默认指向了window)。因为
summary
和book
没有关联,调用summary
本身将只会打印出undefined
,其在全局对象上查找这些属性。然而,你可以在函数中使用
call
和apply
调用book
的上下文this
。现在,当上面的方法运用了,
book
和summary
之间有了关联。我们来确认下,现在this
到底是什么。在这个案例中,
this
实际上变成的所传参数的对象。这就是说
call
和apply
一样,但是它们又有点小区别。除了将第一个参数作为
this
上下文传递之外,你也可以传递其他参数。使用
call
时,你使用的每个额外的值都会被作为附加参数进行传递。如果你尝试使用
apply
去发送相同的参数,就会发生下面的事情:针对
apply
,作为替代,你需要将参数放在一个数组中传递。通过单个参数传递和形成一个数组参数传递,两个之间的差别是微妙的,但是值得你留意。使用
apply
更加简单和方便,因为如果一些参数的细节改变了,它不需要改变函数调用。Bind
call
和apply
都是一次性使用的方法 -- 如果你调用带有this
上下文的方法,它将含有此上下文,但是原始的函数依旧没改变。有时候,你可能需要重复地使用方法来调用另一个对象的上下文,所以,在这种场景下你应该使用
bind
方法来创建一个显示调用this
的全新函数。在这个例子中,每次你调用
braveNewWorldSummary
,它都会返回绑定它的原始this
值。尝试绑定一个新的this
上下文将会失败。因此,你始终可以信任绑定的函数来返回你期待的this
值。虽然这个例子中
braveNewWorldSummary
尝试再次绑定bind
,它依旧保持着第一次绑定就保留的this
上下文。箭头函数
Arrow functions没有自己的
this
绑定。相反,它们上升到下一个执行环境。在你想将
this
执行外部上下文的情况下,箭头函数会很有用。比如,在类中有一个事件监听器,你可能想将this
指向此类中的一些值。在下面这个例子中,像之前一样,你将创建一个按钮并将其追加到
DOM
中,但是,类中将会有一个事件监听器,当按钮被点击时候会改变其文本值。如果你点击按钮,其文本会变成
buttonText
的值。如果在这里,你并没有使用箭头函数,this
将等同于event.currentTarget
,如没有显示绑定this
,你将不能获取类中的值。这种策略通常使用在像React
这样框架的类方法上。总结
在这篇文章中,你学到了关于
JavaScript
的this
,和基于隐式运行时绑定的可能具有的不同值,以及通过bind
,call
和apply
的显示绑定。你还了解到了如何使用箭头函数缺少this
绑定来指向不同的上下文。有了这些知识,你应该能够在你的程序中明确this
的价值了。参考
The text was updated successfully, but these errors were encountered: