【問題】pip3連結不上python3
阿新 • • 發佈:2022-03-17
柯里化,是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數而且返回結果的新函式的技術。
常用場景
- 引數複用
- 提前返回
- 延遲計算/執行
// 普通的add函式
function add(x, y) {
return x + y
}
// Currying後
function curryingAdd(x) {
return function (y) {
return x + y
}
}
add(1, 2) // 3
curryingAdd(1)(2) // 3
常用場景
引數複用
/* * 正常正則驗證字串 reg.test(txt) * * 需求: * 驗證字串中是否含有數字或者字母 * */ //直接呼叫正則驗證 /\d+/g.test('hello') //false /[a-z]+/g.test('hello') //true // 常規函式封裝 function check(reg, txt) { return reg.test(txt) } check(/\d+/g, 'hello') //false check(/[a-z]+/g, 'hello') //true // Currying 注:專案中需要多次用到規則函式時,將該函式定義為全域性函式,函式複用性更好。 function curryingCheck(reg) { return function(txt) { return reg.test(txt) } } /** * hasNumber驗證全域性是否含有數字 * hasLetter驗證全域性是否含有字母 * hasNumber,hasLetter此時已經定義為對應的工具函式,呼叫時只需要傳遞一個引數 * 使用起來更加方便而且語義化更強,程式碼複用度更高 * **/ const hasNumber = curryingCheck(/\d+/g) const hasLetter = curryingCheck(/[a-z]+/g) hasNumber('hello') // false hasLetter('hello') // true
提前確認
/** * * 相容現代瀏覽器以及IE瀏覽器的事件新增方法 * **/ //常規寫法 //問題:每次使用addEvent為元素新增事件的時候,都會判斷一次。 var addEvent = function(element, event, handler) { if (document.addEventListener) { if (element && event && handler) { element.addEventListener(event, handler, false); } } else { if (element && event && handler) { element.attachEvent('on' + event, handler); } } } //Currying //初始addEvent的執行其實值實現了部分的應用,而剩餘的引數應用都是其返回函式實現。 var addEvent = (function() { if (document.addEventListener) { return function(element, event, handler) { if (element && event && handler) { element.addEventListener(event, handler, false); } }; } else { return function( event, handler) { if (element && event && handler) { element.attachEvent('on' + event, handler); } }; } })(); //不使用自啟動函式寫法 var addEvent = function() { const isSupport = document.addEventListener; if (isSupport) { return function(element, event, handler) { if (element && event && handler) { element.addEventListener(event, handler, false); } } } else { return function( event, handler) { if (element && event && handler) { element.attachEvent('on' + event, handler); } }; } }
延遲執行
/**
*
* 函式常用的bind方法實質就是延遲執行
*
**/
Function.prototype.bind = function (context) {
var _this = this
var args = Array.prototype.slice.call(arguments, 1)
return function() {
return _this.apply(context, args)
}
}
經典習題
// 實現一個add方法,使計算結果能夠滿足如下預期: add(1)(2)(3)()= 6; add(1, 2, 3)(4)() = 10; add(1)(2)(3)(4)(5)() = 15; // 定義引數累加方法 function adder(...args) { return args.reduce( (total, currentVal) => { total += currentVal; return total; }) } function addCurry(fn) { // _allargs 儲存所有的引數 // _tempargs 傳遞給累加方法的複製所有引數的臨時引數 // _tempargs 作用在收集到所有引數時使_allargs清空引數,否則重複呼叫時,_allargs會將上一次呼叫時引數與此次呼叫的引數合拼,造成錯誤的結果。 var _allargs = []; var _tempargs= []; return function reFn(...args){ if(args.length === 0){ _tempargs = _allargs; _allargs = []; return fn.apply(this,_tempargs); } else{ _allargs = _allargs.concat(args) return reFn; } } } console.log(add(1, 2, 3)(4)()); // 10 console.log(add(5)(6)(7)(8)(9)()); // 35 /* * 可重複呼叫寫法 * * 知識點:物件(包括陣列,物件,函式等)參與原始運算如算術或邏輯運算時,會無參呼叫其toString或者valueOf方法得到 * 一個原始值,然後用這個原始值參與運算。 ** */ function add(...args) { // 將引數繫結到add上 // 此時f其實還是add函式,但已經固定了一些引數,所以並不是原來的add函式 // 用bind返回新函式以保證滿足**柯里化保留引數**的特性 var f = add.bind(null/*this不用繫結*/, ...args) // 重新實現這個bound add函式的toString方法 // f參與運算應該被當成args的和,與f自己再接收的引數無關 // 考慮到lazy的特性,還是需要時再計算,但又沒了快取,每次用都會重新計算 // 如果有需要,可以改成有快取的版本 f.toString = () => { return args.reduce((a, b) => a + b, 0) } return f; } // 考慮到add可能直接被用於運算中,可以加上這句 add.toString = () => 0 /* 注意以上程式碼中的add,add3,add8,add8p,add9都是不同的函式,且每個函式要加的數是不一樣的。 */ const add3 = add(0, 1)(2) // add3的功能是對傳入的數值加3並返回 console.log( add3(2) + 0 ) // log出5 const add8 = add3(1)(2)(2) // add8由add3的持續呼叫得到 const add8p = add3(5) // 另一種方式得到add8,注意兩個add8不是同一個函式,起名add8p const add9 = add8(1) // 由add8再傳入得到add9函式 console.log( add9(1) + 3 ) // log出13 console.log( add8(1) + 3 ) // log出12