首先引入MDN中對(duì)this的解釋:
在絕大多數(shù)情況下,函數(shù)的調(diào)用方式?jīng)Q定了
this
的值(運(yùn)行時(shí)綁定)欢摄。this
不能在執(zhí)行期間被賦值,并且在每次函數(shù)被調(diào)用時(shí)this
的值也可能會(huì)不同。ES5 引入了 bind 方法來設(shè)置函數(shù)的this
值膨报,而不用考慮函數(shù)如何被調(diào)用的静浴。ES2015 引入了箭頭函數(shù)卑吭,箭頭函數(shù)不提供自身的 this 綁定(this
的值將保持為閉合詞法上下文的值)
1)this是一個(gè)對(duì)象,表示為當(dāng)前代碼的執(zhí)行環(huán)境
2)this的值取決由ta所處的環(huán)境決定:
- 在全局環(huán)境中马绝,this的值總是Window
- 在函數(shù)環(huán)境中豆赏,this的值取決于函數(shù)的調(diào)用方式(下面會(huì)講到)
3)this的值可以改變,可以使用call富稻、apply掷邦、bind 方法設(shè)置this的值
下文主要討論this的值(this的指向)問題
1、全局執(zhí)行環(huán)境
全局上下文默認(rèn)this指向window,嚴(yán)格模式下指向undefined椭赋。
// 在全局環(huán)境中打印this:
console.log(this) // => Window
2抚岗、直接調(diào)用函數(shù)
這種情況是直接調(diào)用,this相當(dāng)于全局執(zhí)行環(huán)境的情況哪怔。
// 在全局中定義的函數(shù):
function _this() {
console.log(this)
}
// 直接調(diào)用函數(shù)的方式
_this() // => Window
立即執(zhí)行函數(shù)也是一樣的情況宣蔚。
3向抢、對(duì)象.方法的形式調(diào)用
這種情況調(diào)用時(shí),this就是ta的調(diào)用者
let obj = {
name: 'zs',
say() { // es6語法
console.log(this)
}
}
// 對(duì)象.方法的方式
obj.say() // => { name: 'zs', say: f } 即為上面定義的 obj
類似的 window.setTimeout(fn, 1000) 也是相同情況胚委。
4.挟鸠、DOM事件綁定
this就是dom事件綁定的元素
// 定義一個(gè)html元素
<input type="button" value="點(diǎn)擊" id="btn">
<script>
let btn = document.querySelector('#btn') // 獲取元素
btn.addEventListener('click', function () { // 綁定事件
console.log(this) // => <input type="button" value="點(diǎn)擊" id="btn">
})
</script>
5、new+構(gòu)造函數(shù)
此時(shí)構(gòu)造函數(shù)中的this值為其實(shí)例對(duì)象亩冬。
function Person(name) { // 構(gòu)造函數(shù)Person
this.name = name // this為new創(chuàng)建出來的新對(duì)象艘希,this.name就是為新創(chuàng)建的對(duì)象添加name屬性。
// 這就是為什么在構(gòu)造函數(shù)中用this.xx來創(chuàng)建屬性
}
let zs = new Person('zs') // Person的實(shí)例對(duì)象
console.log(zs) // => Person {name: "zs"}
6硅急、 箭頭函數(shù)覆享?
在箭頭函數(shù)中,this
與封閉詞法環(huán)境的this
保持一致营袜。this的值為當(dāng)前最近的非箭頭函數(shù)的this
// 全局環(huán)境
let fn = () => {
console.log(this) // => Window
}
fn()
// 對(duì)象
let obj = {
do: () => {
console.log(this) // => Window
},
go: function () {
console.log(this) // => obj
let child = () => {
console.log(this) // => obj
//child為go函數(shù)中定義的箭頭函數(shù)撒顿,因?yàn)榧^函數(shù)沒有this,故child繼承g(shù)o函數(shù)中的this
}
child()
}
}
obj.go()