如果沒有傳參,那麼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會指向a delete 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);