this
的不同應用場景,如何取值
作為普通函式被呼叫
使用 call apply bind
作為物件方法被呼叫
在class方法中呼叫
箭頭函式 (找上級作用域)
this
取什麼值是在函式執行的時候確認的,不是在函式定義的時候確認的
/*
this 指向 window 因為 他當做執行函式 執行函式會直接確認this指向
*/
/*
this 指向 當前物件 因為 箭頭函式 作為回撥函式來使用 只有當函式被呼叫的 時候才會觸發 this指向
*/
const pepole = {
await(){
setTimeout(function (){
console.log(this);
})
setTimeout(() =>{
console.log(this);
})
}
}
call, apply, bind都是改變函式執行的上下文,說的直白點就是改變了函式this的指向。不同的是:call和apply改變了函式的this,並且執行了該函式,而bind是改變了函式的this,並返回一個函式,但不執行該函式。
call 內部實現原理
call()
方法呼叫一個函式, 其具有一個指定的 this
值和分別地提供的引數(引數的列表)。
注意:該方法的作用和 apply()
方法類似,只有一個區別,就是 call()
方法接受的是若干個引數的列表,而 apply()
方法接受的是一個包含多個引數的陣列。
語法:
fun.call(thisArg[, arg1[, arg2[, ...]]])
引數:
thisArg
- 在 fun 函式執行時指定的 this 值
- 如果指定了 null 或者 undefined 則內部 this 指向 window
arg1, arg2, ...
- 指定的引數列表
Function.prototype.call = function(thisArg, args) { // this指向呼叫call的物件 if (typeof this !== 'function') { // 呼叫call的若不是函式則報錯 throw new TypeError('Error') } thisArg = thisArg || window thisArg.fn = this // 將呼叫call函式的物件新增到thisArg的屬性中 const result = thisArg.fn(...[...arguments].slice(1)) // 執行該屬性 delete thisArg.fn // 刪除該屬性 return result }
apply 內部實現原理
apply()
方法呼叫一個函式, 其具有一個指定的 this
值,以及作為一個陣列(或類似陣列的物件)提供的引數。
注意:該方法的作用和 call()
方法類似,只有一個區別,就是 call()
方法接受的是若干個引數的列表,而 apply()
方法接受的是一個包含多個引數的陣列。
語法:
fun.apply(thisArg, [argsArray])
引數:
thisArg
argsArray
apply()
與 call()
非常相似,不同之處在於提供引數的方式。apply()
使用引數陣列而不是一組引數列表。例如:
fun.apply(this, ['eat', 'bananas'])
Function.prototype.apply = function(thisArg, args) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
thisArg = thisArg || window
thisArg.fn = this
let result
if(args) {
result = thisArg.fn(...args)
} else {
result = thisArg.fn()
}
delete thisArg.fn
return result
}
bind 內部實現原理
bind
後的函式會返回一個函式,而這個函式也可能被用來例項化
bind
方法後面有一對空格,所以得出結論bind返回的是一個函式必須呼叫才會執行 bind({x:20})()
語法:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
返回值:返回由指定的this值和初始化引數改造的原函式的複製。
Function.prototype.bind = function(thisArg) {
if(typeof this !== 'function'){
throw new TypeError(this + 'must be a function');
}
// 儲存函式本身
const _this = this;
// 去除thisArg的其他引數 轉成陣列
const args = [...arguments].slice(1)
// 返回一個函式
const bound = function() {
// 可能返回了一個建構函式,我們可以 new F(),所以需要判斷
if (this instanceof bound) {
return new _this(...args, ...arguments)
}
// apply修改this指向,把兩個函式的引數合併傳給thisArg函式,並執行thisArg函式,返回執行結果
return _this.apply(thisArg, args.concat(...arguments))
}
return bound
}
對 bind this 指向的 一些總結
bind this 指向問題 ,就是 誰呼叫,在哪裡呼叫,this指向 就會在哪裡 傳送, 並且this 就會指向 他。
簡單來說 就是 this 指向 是 根據自由變數來決定的 ,自由變數在他被呼叫 ,被使用的 時候 他會在 他的作用域來進行查詢 這個當前 使用的 變數 ,然後根據 他 需要訪問的變數 ,然後 來 使他這個 變數值進行 改變,this 指向的是在 哪裡 進行呼叫 ,就會在哪個作用域中進行呼叫。
自由變數的查詢,是在函式定義的地方,向上級作用域查詢,不是在執行的地方查詢!
this
指向的是當前物件。如果在全域性範圍內使用 this ,則指代當前頁面 window 如果在函式中使用this
, 則this指代什麼是根據當前函式是什麼物件上呼叫。我們可以call
和apply
和bind
改變函式中this
的 具體指向
本作品採用《CC 協議》,轉載必須註明作者和本文連結