程序員節,給本身準備點什麼禮物好呢?準備‘加班’吧。javascript
前言:在前端面試中,最多見的面試題前端
若是面試官問到this的指向問題,那麼你去引導面試官,讓他問你如何改變this指向,call、apply和bind的區別以及源碼解析,這樣主動權就掌握在本身的手中,自古深情留不住,老是套路得人心,或者你回答中提到改變this指向及call、apply和bind的區別以及源碼解析,是否是就能夠給你本身加分了。嘻嘻~java
咱們知道在javascript中call和apply以及bind均可以改變this指向,彼此之間有什麼區別呢?那麼它們是怎麼實現的呢? 首先,咱們先說下call、apply和bind的用法程序員
再聊聊區別面試
call() 和apply()的第一個參數相同,就是指定的對象。這個對象就是該函數的執行上下文。數組
call()和apply()的區別就在於,二者之間的參數。call()在第一個參數以後的 後續全部參數就是傳入該函數的值。apply() 只有兩個參數,第一個是對象,第二個是數組,這個數組就是該函數的參數。bash
bind() 方法和前二者不一樣在於:bind()方法會返回執行上下文被改變的函數而不會當即執行,而前二者是直接執行該函數。他的參數和call()相同。app
最後看看源碼解析函數
一、call()源碼解析ui
Function.prototype.myCall = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
context = context || window
// 誰調用call方法,this就指向誰
context.fn = this
// 去掉全部參數中第一參數(指定的對象)
const args = [...arguments].slice(1)
const result = context.fn(...args)
delete context.fn
return result
}
複製代碼
如下是對call()實現的分析:
二、apply()源碼解析
apply 的實現和 call 相似,區別在於對參數的處理。
Function.prototype.apply = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
context = context || window
context.fn = this
let result
// 處理參數和 call 有區別,apply只有兩個參數,第一個是對象,第二個是數組
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
複製代碼
如下是對apply()實現的分析:
三、bind()源碼解析
bind 的實現對比其餘兩個函數略微地複雜了一點,由於 bind 須要返回一個函數,須要判斷一些邊界問題,如下是 bind 的實現
Function.prototype.bind = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
const _this = this
const args = [...arguments].slice(1)
// 返回一個函數
return function F() {
// 由於返回了一個函數,咱們能夠 new F(),因此須要判斷
if (this instanceof F) {
// 忽略傳入的this
return new _this(...args, ...arguments)
}
// 直接調用,將兩邊的參數拼接起來
return _this.apply(context, args.concat(...arguments))
}
}
複製代碼
如下是對bind()實現的分析:
it's over.
結語:感謝您的閱讀,但願此篇文章對您有所幫助,以上有不足的地方,歡迎指正呀!!!文章有些內容來自 前端面試之道,若有侵權,請聯繫做者刪除,小冊很不錯喲~!最後在此佳節,祝全部程序員無BUG,向可愛的程序員們致敬!