少廢話,show my codegit
原理都在註釋裏了github
// 不覆蓋原生call方法,起個別名叫myCall,接收this上下文context和參數params Function.prototype.myCall = function (context, ...params) { // context必須是個對象而且不能爲null,默認爲window const _this = typeof context === "object" ? context || window : window; // 爲了不和原有屬性衝突,定義一個Symbol類型的屬性 const key = Symbol(); // call方法的目的是改變函數的this指向,函數的this指向它的調用者,也就是說咱們的目標是改變函數的調用者。 // 下面的this就是函數自己,給_this增長一個名爲[key]的方法指向this,就能用_this來調用this了 _this[key] = this; const result = _this[key](...params); // 獲取函數執行結果後,刪除以上添加的屬性 delete _this[key]; return result; };
和call的區別在於第二個參數app
Function.prototype.myApply = function (context, params) { return this.myCall(context, ...params); };
和call的區別在於不當即執行,返回一個函數便可函數
Function.prototype.myBind = function (context, ...params) { const _this = this; // 返回的函數也能接收參數,可是是放在params後面 return function (...args) { return _this.myCall(context, ...[...params, ...args]); }; };
函數柯里化,舉例,有以下函數this
function test(a, b, c, d, e) { console.log(a + b + c + d + e); }
有一個curry轉換函數對test函數進行一些轉換prototype
function curry(){ // todo } const transformTest = curry(test, ...args)
轉換以後,本來一次性傳過去的參數如今能夠分步傳參code
// 使得 test(1,2,3,4,5) // 等同於 transformTest(1)(2)(3)(4)(5) // 或者 transformTest(1, 2)(3)(4, 5) // 又或者 transformTest(1, 2, 3, 4)(5)
curry函數應該怎麼寫?orm
function curry(fn, ...args) { // 判斷參數個數是否是等於原函數參數個數 // 若是是,直接返回調用結果 if ([...args].length >= fn.length) { return fn(...args); } else { // 若是不是,則返回一個函數 return (...params) => { // 將前面傳的所有參數傳給curry,回到第一步的if判斷,直到參數個數知足要求 return curry(fn, ...args, ...params); }; } }
本文GitHub連接:手寫系列:call、apply、bind、函數柯里化對象