js中this的指向问题
?JS 面試題:
var?obj?=?{
??foo:?function(){
????console.log(this)
??}
}
?
var?bar?=?obj.foo
obj.foo()?// 打印出的 this 是 obj
bar()?// 打印出的 this 是 window
?
請解釋最后兩行函數的值為什么不一樣。
?
——-
?
初學者關于 this 的理解一直很模糊。今天這篇文章就要一次講清楚了。
?
而且這個解釋,你在別的地方看不到。看懂這篇文章,所有關于 this 的面試題,都是小菜。
?
函數調用
?
首先需要從函數的調用開始講起。
?
JS(ES5)里面有三種函數調用形式:
?
func(p1,?p2)
obj.child.method(p1,?p2)
func.call(context,?p1,?p2)?// 先不講 apply
?
一般,初學者都知道前兩種形式,而且認為前兩種形式「優于」第三種形式。
?
從看到這篇文章起,你一定要記住,第三種調用形式,才是正常調用形式:
?
func.call(context, p1, p2)
?
其他兩種都是語法糖,可以等價地變為 call 形式:
?
func(p1,?p2)?等價于
func.call(undefined,?p1,?p2)
?
obj.child.method(p1,?p2)?等價于
obj.child.method.call(obj.child,?p1,?p2)
?
請記下來。(我們稱此代碼為「轉換代碼」,方便下文引用)
?
至此我們的函數調用只有一種形式:
?
func.call(context, p1, p2)
?
這樣,this 就好解釋了
?
this,就是上面代碼中的 context。就這么簡單。
?
this 是你 call 一個函數時傳的 context,由于你從來不用 call 形式的函數調用,所以你一直不知道。
?
先看 func(p1, p2) 中的 this 如何確定:
?
當你寫下面代碼時
?
function?func(){
??console.log(this)
}
?
func()
?
等價于
?
function?func(){
??console.log(this)
}
?
func.call(undefined)?// 可以簡寫為 func.call()
?
按理說打印出來的 this 應該就是 undefined 了吧,但是瀏覽器里有一條規則:
?
如果你傳的 context 就 null 或者 undefined,那么 window 對象就是默認的 context(嚴格模式下默認 context 是 undefined)
因此上面的打印結果是 window。
?
如果你希望這里的 this 不是 window,很簡單:
?
func.call(obj) // 那么里面的 this 就是 obj 對象了
?
再看 obj.child.method(p1, p2) 的 this 如何確定
?
var?obj?=?{
??foo:?function(){
????console.log(this)
??}
}
?
obj.foo()
?
按照「轉換代碼」,我們將 obj.foo() 轉換為
?
obj.foo.call(obj)
?
好了,this 就是 obj。搞定。
?
回到題目:
?
var?obj?=?{
??foo:?function(){
????console.log(this)
??}
}
?
var?bar?=?obj.foo
obj.foo()?// 轉換為 obj.foo.call(obj),this 就是 obj
bar()
// 轉換為 bar.call()
// 由于沒有傳 context
// 所以 this 就是 undefined
// 最后瀏覽器給你一個默認的 this —— window 對象
?
[ ] 語法
?
function?fn?(){?console.log(this)?}
var?arr?=?[fn,?fn2]
arr[0]()?// 這里面的 this 又是什么呢?
?
我們可以把 arr[0]( ) 想象為arr.0( ),雖然后者的語法錯了,但是形式與轉換代碼里的 obj.child.method(p1, p2) 對應上了,于是就可以愉快的轉換了:
?
??arr[0]()
假想為????arr.0()
然后轉換為?arr.0.call(arr)
那么里面的?this?就是?arr?了?:)?
?
總結
?
this 就是你 call 一個函數時,傳入的 context。
如果你的函數調用形式不是 call 形式,請按照「轉換代碼」將其轉換為 call 形式。
?
轉載于:https://www.cnblogs.com/alex-415/p/6763393.html
總結
以上是生活随笔為你收集整理的js中this的指向问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LF模式是个坑,ZeroIce中间件让你
- 下一篇: CentOS赋予一个普通用户root权限