首先看一段代碼:
let obj = { x: 100 }; function fn(y) { this.x += y; console.log(this); }
現在有一個需求:在1秒后,執行函式fn,并讓其this指向obj,
如果寫成
setTimeout(fn, 1000);
這么寫的話,fn函式中的this是指向window的,而且也沒有傳遞引數,
如果寫成
setTimeout(fn(200), 1000);
這么寫的話,this指向依然是window,而且相當于立即執行fn函式,并把結果賦給定時器1秒后再執行,這樣肯定不行,
如果寫成
setTimeout(fn.call(obj,200), 1000);
這么寫的話,用call或apply雖然改變了this指向,但都是函式立即執行并把回傳結果賦給了定時器,依然無法完成需求,
如果寫成
setTimeout(function() { fn.call(obj, 200); }, 1000);
這么寫的話,用一個匿名函式包起來,等到1秒后執行匿名函式里邊的代碼,這樣便可以完成上述需求,
從中我們可以看出,在某一個階段之后執行某些代碼,我們需要預先把this指向、引數等預先準備好,這種預先處理的思想即柯理化思想,
即,柯理化函式的思想:利用閉包的機制,把一些內容事先存盤和處理了,等到后期需要的時候拿來用即可,當然,這個需求如果用bind寫的話,也能實作
setTimeout(fn.bind(obj,200), 1000);因為bind不會立即執行函式,而且可以預先存盤一些內容,和柯理化函式的思想相似,但問題是bind不兼容IE8及以下,那么為了通用,我們可以自己封裝一個bind方法,從而實作這種需求,
/* * bind:預先處理內容 * @params * func:要執行的函式 * context:需要改變的this指向 * args:給函式傳遞的引數 * @return * 回傳一個代理函式 */ function bind(func, context, ...args) { return function proxy() { func.call(context, ...args); //call和apply兼容低版本IE }; }
完成最開始的需求
setTimeout(bind(fn, obj, 200), 1000);
理解了這種思想,有助于我們更好的閱讀別人的代碼,如redux原始碼中applyMiddleware.js、combineReducers.js等很多都用到了這種方式或思想,以后更有助于我們自己寫一些插件、組件等,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/149369.html
標籤:JavaScript
上一篇:JS的基本概念和資料型別
下一篇:03.JS運算子
