this是函數調用時産生的對象,該對象綁定函數調用時所在執行環境。
call/bind方法在使用一個指定的 this 值和若幹個指定的參數值的前提下調用某個函數或方法。
function myApply(obj = window,[...args]){//接受第二個參數為數組
obj.fn = this
const res = obj.fn(...args)
delete fn //delete可以删除對象的屬性。詳細參考對象的屬性(資料屬性和通路器屬性)
return res
}
function myCall(obj = window, ...args){
obj.fn = this
const res = obj.fn(...args)
delete fn
return res
}
bind() 方法會建立一個新函數。當這個新函數被調用時,bind() 的第一個參數将作為它運作時的 this,之後的一序列參數将會在傳遞的實參前傳入作為它的參數。(來自于 MDN )
實作要點:
1、傳回值為函數
2、函數調用時this指向于傳入對象
3、函數可傳遞參數
4、該函數可作為構造函數
第一版:實作1~3
Function.prototype.myBind = function (obj = window, ...args){
let self = this
return function(...params){
return self.apply(obj, args.concat(params))
}
}
第二版:實作4
作為構造函數調用時,使用new關鍵字。該關鍵字将this指向生成執行個體,是以實際調用時this指向執行個體。
Function.prototype.myBind = function (obj = window, ...args){
let self = this
function F = function (...params){
return self.apply(this instanceof F ? this : obj, args.concat(params))
}
//修改傳回函數的 prototype 為綁定函數的 prototype,那麼執行個體就可以繼承綁定函數的原型中的值
F.prototype = self.prototype
//F與self共用一個原型
//如果直接修改F.prototype,則self.prototype也會變化,做一個優化
return F
}
逐句講解:
```js
//建立函數并傳回該函數
function F(){}
//...
return F
// this instanceof F 若作為構造函數調用,則this指向執行個體
//不作為構造函數調用時, this指向傳入對象obj
self.apply(this instanceof F ? this : obj, args.concat(params))
第三版:優化傳回函數原型
function myBind (obj = window, ...args){
let self = this
function F = function (...params){
return self.apply(this instanceof F ? this : obj, args.concat(params))
}
function f (){}
f.prototype = self.prototype
F.prototype = new f()
return F
}