this
this
關鍵字,就是所謂的執行上下文。this
關鍵字在函數中,表示的是一個指向,this
的指向永遠是一個對象。
哪個對象調用函數,函數裏面的this指向哪個對象。
代碼示例:
function f() {
let text="哈哈哈"
console.log(this.text) // undefined
console.log(this) // Window
}
f()
上面的代碼等價於:
function f() {
let text="哈哈哈"
console.log(this.text) // undefined
console.log(this) // Window
}
window.f()
f()
函數實際上是被window
對象調用的
var o = {
text:'呵呵',
f:function(){
console.log(this.text) // 呵呵
console.log(this) // {text: "呵呵", f: ƒ}
}
}
o.f()
這裏this
指向對象o
,因爲是對象o
調用f()
上面代碼等價於:
var o = {
text:'呵呵',
f:function(){
console.log(this.text) // 呵呵
console.log(this) // {text: "呵呵", f: ƒ}
}
}
window.o.f()
由此可以看出this指向的是最後調用它的對象
下面再來看看這個:
var o = {
text:'呵呵',
a:{
text:'嘿嘿',
f:function(){
console.log(this.text) // undefined
console.log(this) // Window
}
}
}
var fun = o.a.f
fun()
上面this
指向window
, 最下面的fun()
等價於window.fun()
。而this
指向的是最後調用它的對象
function f(){
this.text="呵呵"
}
var o = new f()
console.log(o.text) // 呵呵
console.log(o) // f {text: "呵呵"}
上面,new
關鍵字創建了一個對象實例o
。new
關鍵字會改變this
的指向,這個時候指向對象o
假如,函數裏有return
,this
指向會怎樣?
function f() {
this.text="呵呵"
return {}
}
var o = new f
console.log(o.text) // undefined
onsole.log(o) // {}
function f() {
this.text="呵呵"
return function(){};
}
var o = new f
console.log(o.text) // undefined
console.log(o) // ƒ (){}
function f() {
this.text="呵呵"
return 1
}
var o = new f
console.log(o.text) // 呵呵
console.log(o) // f {text: "呵呵"}
function f() {
this.text="呵呵"
return null
}
var o = new f
console.log(o.text) // 呵呵
console.log(o) // f {text: "呵呵"}
由以上代碼可知:
如果返回值是一個對象,this指向這個返回的對象;
如果返回值不是一個對象,this還是指向函數的實例
注意: 雖然null也是對象,但它比較特殊,this指向的是函數的實例
匿名函數的this
指向問題:
var o = {
text:'呵呵',
f:function(){
return function(){
console.log(this.text) // undefined
console.log(this) // Window
}
}
}
o.f()()
上面,f
方法return
了一個匿名函數,這個匿名函數中的this
指向window
關於setInterval
和setTimeout
中的this
指向問題
const people = {
name: '小白',
sayHi() {
// this 即當前對象
console.log(this)
},
wait() {
setTimeout(function() {
// this === window
console.log(this)
})
}
}
people.sayHi() // {name: "小白", sayHi: ƒ, wait: ƒ}
people.wait() // Window
從上面可以看出,setTimeout
中的this
指向了window
對象。
這是因爲setTimeout()
調用的代碼運行在與所在函數完全分離的執行環境上。這會導致這些代碼中包含的 this
關鍵字會指向 window
對象
箭頭函數
箭頭函數的this 是取上級作用域的值
箭頭函數的this
定義:箭頭函數的this
是在定義函數時綁定的,不是在執行過程中綁定的。簡單的說,函數在定義時,this
就繼承了定義函數的對象。
const people = {
name: '小白',
sayHi() {
// this 即當前對象
console.log(this)
},
wait() {
// 箭頭函數的this 是取上級作用域的值
setTimeout(() => {
// this === 即當前對象
console.log(this)
})
}
}
people.sayHi() // {name: "小白", sayHi: ƒ, wait: ƒ}
people.wait() // {name: "小白", sayHi: ƒ, wait: ƒ}
如果想改變this的指向,可以使用:call()
apply()
bind()
fn.call(this, p1, p2, p3)
fn.apply(this, arguments)
var fn1 = fn.bind(this, p1, p2, p3)
fn1()
相同點:
- 改變對象的執行上下文(總的來說,就是改變
this
的指向) - 都可以指定調用實參。
不同點:
call()
和bind()
的參數是直接連續傳遞,而apply
傳遞參數是以一個數組傳遞bind()
會返回一個方法。