
คำแนะนำที่เกี่ยวข้อง: บทช่วยสอน JavaScript
apply(context,[arguments]) , call(context,param1,param2,...)Currying เป็นเทคนิคที่แปลงฟังก์ชันที่ยอมรับพารามิเตอร์หลายตัวให้เป็นฟังก์ชันที่ยอมรับพารามิเตอร์ตัวเดียว (พารามิเตอร์แรกของฟังก์ชันดั้งเดิม) และส่งกลับฟังก์ชันใหม่ที่ยอมรับพารามิเตอร์ที่เหลือและส่งกลับผลลัพธ์
ตัวอย่างเช่น นี่คือฟังก์ชัน add() ซึ่งเป็นฟังก์ชันที่ใช้ในการประมวลผลการบวกและผลรวมของพารามิเตอร์ (param1, params2,...) ที่เราส่งผ่านไป
// นี่คือฟังก์ชัน `add(x, y)` ตัวแรกที่มีพารามิเตอร์สองตัว `x`, `y` ฟังก์ชัน add(x, y){
กลับ x + y;
-
// เรียกใช้ฟังก์ชัน `add()` และกำหนดพารามิเตอร์ 2 ตัวคือ `4` และ `6`
เพิ่ม(4,6);
// จำลองการทำงานของคอมพิวเตอร์ ส่งผ่านพารามิเตอร์แรก 4 ในขั้นตอนแรก
เพิ่มฟังก์ชัน(4, y){
กลับ 4 + y;
-
// จำลองการทำงานของคอมพิวเตอร์ ส่งผ่านพารามิเตอร์แรก 6 ในขั้นตอนที่สอง
ฟังก์ชั่นเพิ่ม (4, 6) {
กลับ 4 + 6;
} ถ้าเรารวมเอาฟังก์ชัน add() ไว้ด้วยจะเป็นอย่างไร? นี่เป็นการนำไปใช้อย่างง่าย:
// ฟังก์ชัน curried add() สามารถยอมรับพารามิเตอร์บางตัวได้ ฟังก์ชัน add(x,y){
ถ้า (ประเภทของ y === 'ไม่ได้กำหนด') {
ฟังก์ชั่นส่งคืน (ใหม่) {
กลับ x + ใหม่;
-
-
// ส่งคืนแอปพลิเคชันแบบเต็ม x + y;
-
// ทดสอบการโทร console.log(typeof add(4)); // [ฟังก์ชั่น]
console.log(เพิ่ม(4)(6)); // 10
// คุณสามารถสร้างฟังก์ชั่นบันทึกได้ โดยให้ saveAdd = add(4);
console.log(saveAdd(6)); // 10 ดังที่เห็นได้จากฟังก์ชัน curried add() ข้างต้น ฟังก์ชันสามารถรับฟังก์ชันบางอย่างแล้วส่งคืนฟังก์ชันใหม่เพื่อดำเนินการประมวลผลฟังก์ชันที่เหลือต่อไป
ที่นี่เราสร้างฟังก์ชัน Currying สาธารณะ เพื่อที่เราจะได้ไม่ต้องดำเนินการกระบวนการ Currying ที่ซับซ้อนภายในทุกครั้งที่เราเขียนฟังก์ชัน
//กำหนดฟังก์ชัน createCurry ฟังก์ชัน createCurry(fn){
var ชิ้น = Array.prototype.slice,
Stored_args = Slice.call (อาร์กิวเมนต์,1);
ฟังก์ชันส่งคืน () {
ให้ new_args = Slice.call(อาร์กิวเมนต์)
args = store_args.concat (new_args);
กลับ fn.apply (null, args);
}} ในฟังก์ชันการแกงสาธารณะข้างต้น:
arguments ไม่ใช่อาเรย์จริง แต่เป็นอ็อบเจ็กต์ที่มีแอตทริบิวต์ length ดังนั้นเราจึงยืมเมธอด slice ซ์จาก Array.prototype เพื่อช่วยเราแปลง arguments เป็นอาเรย์จริง เพื่ออำนวยความสะดวกในการดำเนินงานที่ดีขึ้นcreateCurry เป็นครั้งแรก ตัวแปร stored_args จะเก็บพารามิเตอร์ไว้ยกเว้นพารามิเตอร์ตัวแรก เนื่องจากพารามิเตอร์แรกคือฟังก์ชันที่เราจำเป็นต้องแกงcreateCurry ตัวแปร new_args จะได้รับพารามิเตอร์และแปลงเป็นอาร์เรย์stored_args ผ่านการปิดและรวมค่าของตัวแปร new_args เข้ากับอาร์เรย์ใหม่และกำหนดให้กับตัวแปร argsfn.apply(null,args) จะถูกเรียกเพื่อรันฟังก์ชัน curriedทีนี้มาทดสอบฟังก์ชันแกงสาธารณะ
// ฟังก์ชันธรรมดา add()
ฟังก์ชั่นเพิ่ม(x, y){
กลับ x + y;
-
// Curry เพื่อรับฟังก์ชันใหม่ var newAdd = createCurry(add,4);
console.log(เพิ่มใหม่(6)); // 10
//วิธีง่ายๆ อีกวิธีหนึ่ง console.log(createCurry(add,4)(6));// 10 แน่นอนว่านี่ไม่ได้จำกัดอยู่แค่การซ้อนพารามิเตอร์สองตัวเท่านั้น แต่ยังรวมถึงพารามิเตอร์หลายตัวด้วย:
// พารามิเตอร์หลายตัว ฟังก์ชันฟังก์ชันธรรมดาจะเพิ่ม (ก,ข,ค,ง){
กลับ + b + c + d;
-
// Curry ฟังก์ชั่นเพื่อรับฟังก์ชั่นใหม่ สามารถแบ่งพารามิเตอร์ได้หลายตัวที่ will console.log(createCurry(add,4,5)(5,6)); // 20
// แกงสองขั้นตอน ให้ add_one = createCurry(เพิ่ม,5);
console.log(add_one(5,5,5));// 20
ให้ add_two = createCurry(add_one,4,6);
console.log(add_two(6)); // 21จาก ตัวอย่างข้างต้น เราสามารถค้นหาข้อจำกัดได้ กล่าวคือ ไม่ว่าจะเป็นพารามิเตอร์สองตัวหรือหลายพารามิเตอร์ ก็สามารถดำเนินการได้ในสองขั้นตอนเท่านั้น เช่น สูตรต่อไปนี้:
หากเราต้องการความยืดหยุ่นมากขึ้น:
;
หลังจากแบบฝึกหัดข้างต้น เราพบว่าฟังก์ชัน Curried ที่เราสร้างขึ้นมีข้อจำกัดบางประการ เราหวังว่าฟังก์ชันนี้จะสามารถทำงานได้หลายขั้นตอน:
// สร้างฟังก์ชัน Curried ที่สามารถดำเนินการได้หลายขั้นตอน Function ให้ดำเนินการเมื่อถึงจำนวนพารามิเตอร์:
// สูตรฟังก์ชัน: fn(x,y,z,w) ==> fn(x)(y)(z)(w);
ให้ createCurry = (fn,...params)=> {
ให้ args = parsms ||.
ให้ fnLen = fn.length; // ระบุความยาวพารามิเตอร์ของฟังก์ชัน curried
กลับ (...ความละเอียด)=> {
// รับพารามิเตอร์ก่อนหน้านี้ทั้งหมดผ่านห่วงโซ่ขอบเขต ให้ allArgs = args.slice(0);
// คัดลอกพารามิเตอร์ args ที่ใช้ร่วมกันโดยการปิดเพื่อหลีกเลี่ยงผลกระทบของการดำเนินการที่ตามมา (ประเภทอ้างอิง)
allArgs.push(...รายละเอียด);
ถ้า (allArgs.length < fnLen){
// เมื่อจำนวนพารามิเตอร์น้อยกว่าความยาวพารามิเตอร์ของฟังก์ชันดั้งเดิม ให้เรียกใช้ฟังก์ชัน createCurry ซ้ำเพื่อส่งคืน createCurry.call(this,fn,...allArgs);
}อื่น{
// เมื่อครบจำนวนพารามิเตอร์แล้ว การดำเนินการฟังก์ชันทริกเกอร์จะส่งคืน fn.apply(this,allArgs);
-
-
-
// ฟังก์ชันสามัญ เพิ่มฟังก์ชัน(a,b,c,d){ พร้อมพารามิเตอร์หลายตัว
กลับ + b + c + d;
-
//ทดสอบฟังก์ชั่นการแกง ให้curryAdd = createCurry(add,1);
console.log(curryAdd(2)(3)(4)); // เราได้ใช้ฟังก์ชันการแกงแบบยืดหยุ่นมานานกว่า 10 ปี แต่ที่นี่เราพบปัญหาอื่น:
curryAdd(add,1,2,3,4)() ;add() ดั้งเดิม นี่เป็นวิธีหนึ่งเช่นกัน แต่เนื่องจากเราพอใจกับจำนวนพารามิเตอร์ที่นี่ เราจึงยังคงจัดการกับสถานการณ์นี้ที่นี่เราเพียงต้องตัดสินใจก่อนที่จะส่งคืนฟังก์ชัน:
ให้ createCurry = (fn,...params)=> {
ให้ args = parsms ||.
ให้ fnLen = fn.length; // ระบุความยาวพารามิเตอร์ของฟังก์ชัน curried
ถ้า (ความยาว === _args.length) {
//เพิ่มวิจารณญาณ หากจำนวนพารามิเตอร์ในครั้งแรกเพียงพอ ให้เรียกใช้ฟังก์ชันโดยตรงเพื่อรับผลลัพธ์ที่ส่งคืน fn.apply(this,args);
-
กลับ (...ความละเอียด)=> {
ให้ allArgs = args.slice(0);
allArgs.push(...รายละเอียด);
ถ้า (allArgs.length < fnLen){
ส่งคืน createCurry.call (นี่, fn, ... allArgs);
}อื่น{
กลับ fn.apply (นี่คือ allArgs);
-
}} ข้างต้นถือได้ว่าเป็นฟังก์ชัน curried ที่ยืดหยุ่นได้ แต่ที่นี่ไม่ยืดหยุ่นมากนัก เนื่องจากเราไม่สามารถควบคุมได้ว่าเมื่อใดที่จะถูกดำเนินการ ตราบใดที่จำนวนพารามิเตอร์เพียงพอ ก็จะถูกดำเนินการโดยอัตโนมัติ เราควรทำอย่างไรหากเราต้องการบรรลุจังหวะเวลาที่สามารถควบคุมการดำเนินการได้?
ได้ ที่นี่:
// เมื่อพารามิเตอร์ครบแล้ว ให้เรียกใช้ฟังก์ชัน la createCurry = (fn,...params)=> {
ให้ args = parsms ||.
ให้ fnLen = fn.length; // ระบุความยาวพารามิเตอร์ของฟังก์ชัน curried
//แน่นอนว่าจำเป็นต้องใส่ความคิดเห็นในการตัดสินที่นี่ ไม่เช่นนั้นผลลัพธ์จะถูกดำเนินการโดยตรงเมื่อจำนวนพารามิเตอร์เพียงพอในครั้งแรก //if(length === _args.length){
// เพิ่มการตัดสิน หากจำนวนพารามิเตอร์ในครั้งแรกเพียงพอ ให้เรียกใช้ฟังก์ชันโดยตรงเพื่อรับผลลัพธ์ //return fn.apply(this,args);
-
กลับ (...ความละเอียด)=> {
ให้ allArgs = args.slice(0);
allArgs.push(...รายละเอียด);
// ที่นี่จะตัดสินว่าพารามิเตอร์อินพุตมากกว่า 0 หรือไม่ หากมากกว่า 0 จะตัดสินว่าจำนวนพารามิเตอร์เพียงพอหรือไม่
// && ไม่สามารถใช้ที่นี่ได้ หากใช้ && ผลลัพธ์จะถูกดำเนินการเมื่อจำนวนพารามิเตอร์เพียงพอ
ถ้า (res.length > 0 || allArgs.length < fnLen){
ส่งคืน createCurry.call (นี่, fn, ... allArgs);
}อื่น{
กลับ fn.apply (นี่คือ allArgs);
-
-
-
// ฟังก์ชันสามัญ เพิ่มฟังก์ชัน(a,b,c,d){ พร้อมพารามิเตอร์หลายตัว
กลับ + b + c + d;
-
// ทดสอบฟังก์ชันการแกงที่ควบคุมได้ ให้curryAdd = createCurry(add,1);
console.log(curryAdd(2)(3)(4)); // ฟังก์ชั่น
console.log(curryAdd(2)(3)(4)()); // 10
console.log(curryAdd(2)(3)()); // ส่งคืน NaN เมื่อพารามิเตอร์ไม่เพียงพอ : บทช่วยสอนการเรียนรู้ JavaScript
ข้างต้นคือการพูดคุยเกี่ยวกับรายละเอียดของฟังก์ชัน JavaScript โปรดใส่ใจกับบทความ php อื่น ๆ ที่เกี่ยวข้องบนเว็บไซต์จีน!