手寫 call、apply、bind
阿新 • • 發佈:2021-02-05
手寫 call、apply、bind
JavaScript 中 call()、apply()、bind() 的用法
ES6
實現,參考 awesome-coding-js
模擬實現 call
/*
foo.call(db, fm, t) 的結果可以理解為
1. db 物件呼叫了 foo 函式;
2. fm 和 t 引數也傳到 foo 函式裡去了
那麼我們要實現 call,就要做到以上兩點
第一點:
但是問題是 db 物件本身沒有 foo 函式啊,怎麼解決呢?
解決方案就是把 foo 函式傳到 db 物件裡面成為 db 物件的方法,然後就可以實現 db.foo 了,直接執行就可以了
第二點
我們需要把引數傳進去 foo 函式,利用 ES6 的 ...args 就可以實現
*/
Function.prototype.myCall = function (context = Window, ...args) {
if (this === Function.prototype) {
return undefined // 防止 Function.prototype.myCall() 直接呼叫
}
// 這裡還可以優化,如果傳進來的是 null,undefined,字串,該咋整
context = context || Window // 儲存傳進來的物件,this 就是要繫結給它的
const fn = Symbol() // 確保不會重名
context[fn] = this // 儲存要被呼叫的函式到物件中
const result = context[fn](...args) // 將引數傳進去呼叫
delete context[fn] // 刪除 fn 屬性
return result
}
// 測試
var foo = function (fm, t) {
console.log(this.name + " 年齡 " + this.age, " 來自" + fm + '去往' + t)
}
var db = {
name: '德瑪',
age: 99
}
foo.call(db, '成都', '上海') // 德瑪年齡99 來自成都去往上海
foo.myCall(db, '成都', '上海') // 德瑪年齡99 來自成都去往上海
模擬實現 apply
Function.prototype.myApply = function (context = Window, args) {
if (this === Function.prototype) {
return undefined // 防止 Function.prototype.myApply() 直接呼叫
}
context = context || Window // 儲存傳進來的物件,this 就是要繫結給它的
const fn = Symbol() // 確保不會重名
context[fn] = this // 儲存要被呼叫的函式到物件中
let result
if (Array.isArray(args)) {
result = context[fn](...args)
} else {
result = context[fn]()
}
delete context[fn] // 刪除 fn 屬性
return result
}
// 測試 myApply
foo.apply(db, ['成都', '上海']) // 德瑪年齡99 來自成都去往上海
foo.myApply(db, ['成都', '上海']) // 德瑪年齡99 來自成都去往上海
模擬實現 bind
/*
foo.bind(target) 返回的是一個函式物件(閉包),foo.bind(target)() 這樣子才會執行
*/
Function.prototype.myBind = function (context = Window, ...args1) {
if (this === Function.prototype) {
throw new TypeError('Error')
}
const _this = this
// 這裡的 F 相當於 foo.bind(db, fm, t)() 的 foo.bind(db, fm, t)
return F = function (...args2) {
// 這裡可以優化,暫時不理解,先放著
return _this.call(context, ...args1.concat(...args2)) // 用 call 實現 foo.bind(db, fm, t)()
}
}
// 測試 myBind
foo.bind(db, '成都', '上海')() // 德瑪年齡99 來自成都去往上海
foo.myBind(db, '成都', '上海')() // 德瑪年齡99 來自成都去往上海
`
ES5實現,參考 [位元組大佬lhyt
Github`](https://github.com/lhyt/issue/issues/14)
暫未實現,後續將更新…