溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript 函數柯里化的深入淺析

發布時間:2020-11-04 16:39:07 來源:億速云 閱讀:207 作者:Leah 欄目:開發技術

JavaScript 函數柯里化的深入淺析?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

柯里化 (Currying)是把接收多個參數的原函數變換成接受一個單一參數(原來函數的第一個參數的函數)并返回一個新的函數,新的函數能夠接受余下的參數,并返回和原函數相同的結果。

ES6的方式實現柯里化的通用

function currying(fn,...rest1){
	return function(...rest2){
		//這里用apply 是為把數組形式的參數直接傳入原函數 null是因為不需要改變this
		return fn.apply(null,rest1.concat(rest2));
	}
}

將一個sayHello函數柯里化

function sayHello(name,age,fruit){
	console.log(`我叫${name},我${age}歲了,我喜歡吃${fruit}`);
}

//傳入第一個參數
let curryingShowMsg = currying(sayHello,'小明');
//執行傳入剩余參數
curryingShowMsg(22,'芒果');

反柯里化 和柯里化剛好相反。為了讓方法使用場景更廣,使用反柯里化,可以把原生方法借出來,讓任何對象擁有原生對象的方法。

二者的區別

//柯里化
//function(arg1,arg2) => function(arg1)(arg2);
//function(arg1,arg2,...,argn) => function(arg1)(arg2)(...)(argn)
//反柯里化
//obj.func(arg1,arg2) => func(obj,arg1,arg2)

ES6實現一個反柯里化

function unCurrying(fn){
	//tar 是我們借給的對象 以前需要xxx.fn(xx) 現在就可以fn(xxx,xx)
	return function(tar,...argu){
		return fn.apply(tar,argu);
	}
}
//比如我們想把Array.prototype.push方法從原生借出來
let push = unCurrying(Array.prototype.push);
//arrguments是我們借給的對象
push(arguments,4);

函數柯里化的高階實現 ,上面的函數只實現一層簡單的柯里化 如果實現完全的柯里化func(xx)(xx)(xx)(xx)的話,我們要反復嵌套我們的柯里化函數,這里我們實現一個更高階的柯里化通用方法。

function curryingHelper(fn,len){
	//這里先說個基本知識點 fn.length 返回的是這個方法需要傳入的參數個數
	//這里第一次運行時通過fn.length 后面遞歸都是用的傳入的len len為剩余的參數個數
	const length = len || fn.length;
	return function(...rest){
		//判斷這次傳入的參數是否大于等于剩下的參數 如果不是遞歸返回下一個方法繼續傳參
		return rest.length >= length 
		? fn.apply(this,rest)
		: curryingHelper(currying.apply(this,[fn].concat(rest)),length-rest.length)
	}
}
//還是剛才的sayHello 函數
let betterShowMsg = curryingHelper(sayHello);
//自動控制傳參層數
betterShowMsg('zyx')(22)('葡萄');
betterShowMsg('zyx',22)('葡萄');

柯里化的三種用法

1 參數的復用

function Say(name,some){
	console.log(name + '說' + some);
}
//如果我們只想讓zyx說一些東西
let zyxSay = currying(Say,'zyx');
zyxSay('1111');//zyx說1111

2 提高適用性

//通用函數解決了兼容性的問題,但是同時在不同場景下,我們可能同一種規則需要反復使用
//這就可能會造成代碼的重復性 比如

function square(i){ return i*i }//平方
function dubble(i){ return i*2 }//雙倍
function map(handler,list){
	//handle 是操作的規則 list是操作的arrguments
	return list.map(handler)
}

map(square,[1,2,3]);//數組每一項平方
map(dubble,[1,2,3]);//數組每一項加倍
//這就是通用性 我可以用同一個函數做很多不同的操作
//但是如果我們需要大量做平方操作 每次我們都需要傳入方法再傳入數組就造成的代碼浪費
//這時我們通過柯里化提高實用性

let mapSQ = currying(map,square);//直接定義出來的新的平凡操作函數
mapSQ([1,2,3]);//以后就不用傳入操作方法了

3 延遲執行

let add = function(...rest){
	//定義一個閉包保存_args
	const _args = [];
	return function cb(...rest){
		if(rest.length == 0){
			//如果不穿參數了 也就是add() 說明我們需要最后執行函數了
			let res = 0;
			//累加
			console.log(_args);
			for(let data of _args){
				res += data;
			}
			return res;
		}else{
			_args.push(...rest);
			//為了鎖住args 閉包
			return _args;
		}
	}
}()

add(1);
add(2);
let a = add();
console.log(a);//3

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女