手動實現call、apply和bind
阿新 • • 發佈:2021-01-20
如果沒有傳參,那麼this預設指向的window
let a = { value: 1 } function parent(sex, weight) { this.name = '1' this.age = 12 this.sex = sex ? sex : null this.weight = weight ? weight : null console.log(123) }
call的實現 call接受引數的方式 call(obj, params1, params2, ....)
Function.prototype.myCall = function(context) { let currentObj = context ? context : window // 這裡就是傳入的第一個引數 currentObj.fn = this // 將parent函式存起來,parent呼叫的myCall,此時this指向的就是該方法 let arg = [...arguments].slice(1) // 將引數中除了第一個之後的全部存起來,第一個就是上下文要用的這個物件 console.log(...arg) currentObj.fn(...arg) // 將引數傳入,此時呼叫fn的是currentObj 即為傳入的物件a,所以parent中的this會指向adelete context.fn // 將函式刪除 }
// 測試程式碼
// parent.myCall(a, 'mingzi', 'nianling')
// console.log(a);
apply的實現 apply接受引數的方式 call(obj, [params1, params2, ....])
Function.prototype.myApply = function (context) { let currentObj = context ? context : window // 這裡就是傳入的第一個引數 currentObj.fn = this // 將parent函式存起來,parent呼叫的myCall,此時this指向的就是該方法console.log(arguments) // [{value: 1}, ['張三', '12']] if(arguments[1]) { currentObj.fn(...arguments[1]) } else { currentObj.fn() } delete currentObj.fn } // 測試程式碼 // parent.myApply(a, ['boy', '50']) // console.log(a)
bind()實現
// 實現bind()方法 呼叫bind()必須是一個函式 可以通過new修改this new的優先順序最高 bind()可以將引數分兩次傳遞進來 Function.prototype.myBind = function (context) { if(typeof this !== "function") { // 如果不是函式則直接丟擲 throw new TypeError('Error') } let self = this // 儲存this,即為parent let arg = [...arguments].slice(1) // 將引數中除了第一個之後的全部存起來 // bind()返回的是一個函式,所以可以使用new,並且會修改this的指向 return function F() { if(this instanceof F) { // 如果new執行此時即為true return new self(...arg, ...arguments) // 返回new parent(第一次傳遞的引數, 第二次傳遞的引數) =》 arguments是執行返回的函式時的引數 } return self.apply(context, [...arg, ...arguments]) // 如果沒有執行new 那麼直接執行parent,通過apply會將this執行最初傳進來的物件a } } // 測試程式碼 let bindResult = parent.myBind(a, 'women') let result = new bindResult('666') console.log(result);