對不少前端開發者來講,JavaScript語言的this指向是一個使人頭疼的問題。先看下面這道測試題,若是你能實現並解釋緣由,那本文對你來講價值不大,能夠直接略過。前端
**開篇測試題:**嘗試實現註釋部分的Javascript代碼,可在其餘任何地方添加更多代碼(如不能實現,說明一下不能實現的緣由):瀏覽器
let Obj = function (msg) {
this.msg = msg
this.shout = function () {
alert(this.msg)
}
this.waitAndShout = function () {
// 隔5秒後執行上面的shout方面
setTimeout(function () {
let self = this
return function () {
self.shout()
}
}.call(this), 5000)
}
}
複製代碼
題目的參考答案在文末,但我不建議你直接查看答案,而是先閱讀並思考文章的中的知識點。app
this
指向的是對象自己,即例子中的obj
var obj = {
x: 123,
fn: function () {
console.log(this) // {x: 123, fn: ƒ}
console.log(this.x) // 123
}
}
obj.fn()
複製代碼
this
指向的是window
var obj = {
x: 456,
fn: function () {
console.log('fn', this) // {x: 456, fn: ƒ}
var f1 = function () {
console.log('fn.f1', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
console.log(this.x) // undefined
var f2 = function () {
console.log('fn.f2', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
}
f2()
}
f1()
}
}
obj.fn()
複製代碼
從上面的例子,咱們能夠總結出,對象屬性中,嵌套超過一級及以上的函數,this指向都是window
函數
new
出來的實例(例子中的person
)var Person = function () {
this.name = 'linlif'
this.fn = function () {
console.log('fn', this) // {name: "linlif", fn: ƒ}
}
}
var person = new Person()
person.fn()
複製代碼
window
var Person = function () {
this.name = 'linlif'
this.fn = function () {
console.log('fn', this) // {name: "linlif", fn: ƒ}
var f2 = function () {
console.log('f2', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
var f3 = function () {
console.log('f3', this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
}
f3()
}
f2()
}
}
var person = new Person()
person.fn()
複製代碼
從上面的例子,咱們能夠總結出,構造函數中,嵌套超過一級及以上的函數,this指向的都是window
post
全局上下文環境,this指向瀏覽器的window
對象,例如:測試
// 全局的this
console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
console.log(this === window) // true
// 全局的普通函數
var global = function () {
console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
}
global()
複製代碼
使用call()
方法後,this
指向call()
方法的參數。使用apply()
的結果和call()
是一致的,這裏不作贅述。關於call()
和apply()
用法的區別,請自行查詢相關資料。ui
// 改變調用對象爲gObj
var gObj = {
name: 'gName'
}
var aaa = function () {
console.log(this) // {name: "gName"}
console.log(this.name) // gName
}
aaa.call(gObj)
// 改變調用對象爲window
var name = 'global'
var bbb = function () {
console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
console.log(this.name) // global
}
bbb.call(this)
複製代碼
總結:這就是一些關於this的指向問題的我的理解了,若是發現不妥之處,歡迎在評論區指出,或者私信我。this
彩蛋 開篇測試題的參考答案,僅供參考!(有意思的地方:題目中,函數名的第一個字母大寫,已經暗示這是一個構造函數)spa
let Obj = function (msg) {
this.msg = msg
this.shout = function () {
alert(this.msg)
}
this.waitAndShout = function () {
// 隔5秒後執行上面的shout方面
setTimeout(function () {
let self = this
return function () {
self.shout()
}
}.call(this), 5000)
}
}
let obj = new Obj('msg')
obj.waitAndShout()
複製代碼
本篇完。code