手寫call、apply、bind方法
阿新 • • 發佈:2020-12-16
call、apply、bind 都是為了改變函式執行時上下文(this指向)而存在的。
它們有什麼不同?
- 它們接收的第一個引數都是函式上下文也就是要繫結的this指向。
- apply的第二個引數是一個引數陣列,call和bind的第二個及之後的引數作為函式實參按順序傳入。
- bind繫結完this的指向後會返回一個新的函式體,不會被立即呼叫,其他兩個會立即呼叫。
實現call方法
Function.prototype.myCall = function(thisObj,...args){
if(typeof this !== 'function') { // this 必須是函式
throw new TypeError(`It's must be a function`)
}
thisObj = thisObj || window
let fn = Symbol()
thisObj[fn] = this
let res = thisObj[fn](...args)
delete thisObj[fn]
return res
}
實現apply方法
Function.prototype.myApply = function(thisObj,args=[]){
if(typeof this !== 'function') { // this 必須是函式
throw new TypeError(`It's must be a function`)
}
thisObj = thisObj || window
let fn = Symbol()
thisObj[fn] = this
let res = thisObj[fn](...args)
delete thisObj[fn]
return res
}
實現bind方法
Function.prototype.myBind = function (thisObj, ...args) {
const fn = this
if(typeof fn !== 'function'){
throw new TypeError('It must be a function')
}
thisObj = thisObj || window
return function (...otherArgs) {
return fn.apply(thisObj, [...args, ...otherArgs])
}
}
如果要支援new:
Function.prototype.myBind = function (thisObj, ...args) {
var fn= this
if(typeof fn !== 'function'){
throw new TypeError('It must be a function')
}
thisObj = thisObj || window
// new優先順序
var result = function () {
return fn.apply(this instanceof result ? this : thisObj, args.concat(Array.prototype.slice.call(arguments)))
}
// 繼承原型上的屬性和方法
result.prototype = Object.create(fn.prototype)
return result
}