首先需要從函式的呼叫開始講起。
js(es5)裡面有三種函式呼叫形式:
func(p1, p2)
obj.child.method(p1, p2)
一般,初學者都知道前兩種形式,而且認為前兩種形式「優於」第三種形式。
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,就是上面**中的 context。就這麼簡單。
this 是你 call 乙個函式時傳的 context,由於你從來不用 call 形式的函式呼叫,所以你一直不知道。
先看 func(p1, p2) 中的 this 如何確定:
當你寫下面**時
function func()
func()
等價於
function func()
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 =
}obj.foo()
按照「轉換**」,我們將 obj.foo() 轉換為
obj.foo.call(obj)
好了,this 就是 obj。搞定。
回到題目:
var obj =
}var bar = obj.foo
obj.foo() // 轉換為 obj.foo.call(obj),this 就是 obj
bar()
// 轉換為 bar.call()
// 由於沒有傳 context
// 所以 this 就是 undefined
// 最後瀏覽器給你乙個預設的 this —— window 物件
function fn ()
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 形式。
以後你遇到所有跟 this 有關的筆試題,都不會有疑問了。
完。
關於this的指向問題
呼叫方式有以下四種只需要記住一點,this的指向取決於以什麼樣的方式去呼叫它 1 函式呼叫模式 funcction fn fn 那麼此時的this,指向的是我們的windows 2 方法呼叫模式 var obj obj.sayhi obj.sayhi 裡面的this 那麼必定指向這個 obj 3 構...
關於 this 指向問題
一 面試題 function foo foo 全域性物件 foo.call 123 123二 面試題 const obj1 obj1.foo obj1 const fn obj1.foo fn 三 面試題 const obj2 bar obj2.foo 沿著作用域向上找最近的乙個 function ...
關於js中的this指向問題
1.在普通函式和全域性環境下 this指向window function demo demo console.log this x 102.建構函式 建構函式就是函式new出來的物件,所以this指向該物件 function foo var foo newfoo console.log foo.x ...