この記事では、javascript に関する関連知識を提供します。主に JavaScript における関数のカリー化に関連する問題を紹介します。カリー化とは、複数のパラメーターを受け入れる関数を変換することです。単一のパラメーターを受け入れる手法です。そして、残りのパラメータを受け入れて結果を返す新しい関数を返します。
#関連する推奨事項: 1. apply と call ## を簡単に理解します。 #call と apply はどちらも関数実行時のコンテキストを変更するために存在し、言い換えれば関数本体内で this のポインタを変更するためのものです。call(context,param1,param2,...)
。
たとえば、
add() 関数があります。これは、渡すパラメータ (param1、params2、...) の加算と合計を処理するために使用される関数です。 . . <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">// 在这里第一个具有两个参数`x`、`y`的`add(x , y)`函数
function add(x , y){
return x + y;
}
// 调用`add()`函数,并给定两个参数`4`和`6`
add(4,6);
// 模拟计算机操作,第一步 传入第一个参数 4
function add(4 , y){
return 4 + y;
}
// 模拟计算机操作,第二步 传入第一个参数 6
function add(4 , 6){
return 4 + 6;
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
関数をカリー化するとどうなるでしょうか?これは簡単な実装です: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">// 柯里化过的add()函数,可以接受部分参数
function add(x ,y){
if (typeof y === 'undefined') {
return function (newy){
return x + newy;
}
}
// 完整应用
return x + y;
}
// 测试调用
console.log(typeof add(4)); // [Function]
console.log(add(4)(6)); // 10
// 可以创建保存函数
let saveAdd = add(4);
console.log(saveAdd(6)); // 10</pre><div class="contentsignin">ログイン後にコピー</div></div>
上記の単純なカリー化された
関数からわかるように、この関数はいくつかの関数を受け入れてから、新しい関数を返して続行させることができます。残りの機能。 3. パブリック カリー化関数を作成する
// 定义一个createCurry的函数function createCurry(fn){ var slice = Array.prototype.slice, stored_args = slice.call(arguments,1); return function () { let new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null,args); }}
上記のパブリック カリー化関数:
length
Attribute オブジェクトを持つ単なる配列ですそのため、Array.prototype
から slice
メソッドを借用して、arguments
を実際の配列に変換し、より適切な操作を容易にします。
関数 stored_args
は最初のパラメーターを除くパラメーターを保持します。これは、最初のパラメーターが「カリー化された関数が必要」であるためです。
関数 new_args
がパラメーターを取得し、配列に変換します。
返された関数は内部的にクロージャを通じて変数 new_args
の値は新しい配列に結合されて、変数 args
。
最後に
// 普通函数add()
function add(x , y){
return x + y;
}
// 柯里化得到一个新的函数
var newAdd = createCurry(add,4);
console.log(newAdd(6)); // 10
//另一种简便方式
console.log(createCurry(add,4)(6));// 10
// 多个参数的普通函数 function add(a,b,c,d){ return a + b + c + d; } // 柯里化函数得到新函数,多个参数可以随意分割 console.log(createCurry(add,4,5)(5,6)); // 20 // 两步柯里化 let add_one = createCurry(add,5); console.log(add_one(5,5,5));// 20 let add_two = createCurry(add_one,4,6); console.log(add_two(6)); // 21
上記の例を通じて、制限がわかります。つまり、2 つのパラメーターであっても複数のパラメーターであっても、次の式のような 2 つのステップでのみ実行できます。
fn(x,y) ==> fn(x)(y);fn(x,y,z,w) ==> fn(x)(y,z, w) || fn(x,y)(z,w)||…上記の演習の後、作成したカリー化関数には特定の制限があることがわかりました。関数が複数のステップで実行できることを期待します:
// 创建一个可以多步执行的柯里化函数,当参数满足数量时就去执行它: // 函数公式:fn(x,y,z,w) ==> fn(x)(y)(z)(w); let createCurry = (fn,...params)=> { let args = parsms || []; let fnLen = fn.length; // 指定柯里化函数的参数长度 return (...res)=> { // 通过作用域链获取上一次的所有参数 let allArgs = args.slice(0); // 深度拷贝闭包共用的args参数,避免后续操作影响(引用类型) allArgs.push(...res); if(allArgs.length < fnLen){ // 当参数数量小于原函数的参数长度时,递归调用createCurry函数 return createCurry.call(this,fn,...allArgs); }else{ // 当参数数量满足时,触发函数执行 return fn.apply(this,allArgs); } } } // 多个参数的普通函数 function add(a,b,c,d){ return a + b + c + d; } // 测试柯里化函数 let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); // 10
add()
関数を呼び出すだけです。これも 1 つの方法です。しかし、パラメータの数を満たすためにここにいるので、この状況に対処します。」 ここで必要なのは、関数を返す前に判断することだけです:
let createCurry = (fn,...params)=> { let args = parsms || []; let fnLen = fn.length; // 指定柯里化函数的参数长度 if(length === _args.length){ // 加入判断,如果第一次参数数量以经足够时就直接调用函数获取结果 return fn.apply(this,args); } return (...res)=> { let allArgs = args.slice(0); allArgs.push(...res); if(allArgs.length < fnLen){ return createCurry.call(this,fn,...allArgs); }else{ return fn.apply(this,allArgs); } }}
5. 実行時間を制御できるカリー化関数を作成する
ここで関数の式を直接説明しましょう:
// 当参数满足,再次执行时调用函数 let createCurry = (fn,...params)=> { let args = parsms || []; let fnLen = fn.length; // 指定柯里化函数的参数长度 //当然这里的判断需要注释掉,不然当它第一次参数数量足够时就直接执行结果了 //if(length === _args.length){ // 加入判断,如果第一次参数数量以经足够时就直接调用函数获取结果 //return fn.apply(this,args); //} return (...res)=> { let allArgs = args.slice(0); allArgs.push(...res); // 在这里判断输入的参数是否大于0,如果大于0在判断参数数量是否足够, // 这里不能用 && ,如果用&& 也是参数数量足够时就执行结果了。 if(res.length > 0 || allArgs.length < fnLen){ return createCurry.call(this,fn,...allArgs); }else{ return fn.apply(this,allArgs); } } } // 多个参数的普通函数 function add(a,b,c,d){ return a + b + c + d; } // 测试可控制的柯里化函数 let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); // function console.log(curryAdd(2)(3)(4)()); // 10 console.log(curryAdd(2)(3)()); // 当参数不足够时返回 NaN
相关推荐:javascript学习教程
以上がJavaScript 関数のカリー化について話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。