การส่งต่ออาร์กิวเมนต์ไปยังฟังก์ชัน javascript อื่น


386

ฉันได้ลองทำสิ่งต่อไปนี้โดยไม่ประสบความสำเร็จ:

function a(args){
    b(arguments);
}

function b(args){
    // arguments are lost?
}

a(1,2,3);

ในฟังก์ชั่น a, ฉันสามารถใช้อากิวเมนต์อาร์กิวเมนท์เพื่อเข้าถึงอาเรย์ของอาร์กิวเมนท์, ในฟังก์ชัน b สิ่งเหล่านี้จะหายไป มีวิธีการส่งผ่านข้อโต้แย้งไปยังฟังก์ชั่นจาวาสคริปต์อื่นอย่างที่ฉันพยายามทำหรือไม่?


3
@ BobStein-VisiBone เห็นด้วย นอกจากนี้ทราบว่าargumentsไม่จริงอาร์เรย์ ( แต่ค่อนข้างวัตถุที่อาร์เรย์เช่นการดำเนินการความหมาย ) และดังนั้นจึงไม่ได้อย่างสิ้นเชิงล้างได้อย่างรวดเร็วก่อนไม่ว่าจะสามารถนำมาใช้ในทางเดียวกันเป็นอาร์เรย์สามารถเกิดขึ้นจริง
จูลส์

@Jules ยังคงโหวตให้เปิดใหม่หลังจากหลายปีที่ผ่านมา ตราสัญลักษณ์สำหรับการเผาไหม้งานอันมีค่าของคนอื่นคืออะไร? ผู้คนมากมายต้องเดินไปรอบ ๆ
Bob Stein

คำตอบ:


542

ใช้.apply()เพื่อให้มีการเข้าถึงแบบเดียวกันargumentsในฟังก์ชั่นbเช่นนี้:

function a(){
    b.apply(null, arguments);
}
function b(){
   alert(arguments); //arguments[0] = 1, etc
}
a(1,2,3);​

คุณสามารถทดสอบได้ที่นี่


21
@Brett - คุณสามารถคัดลอกลงในอาร์เรย์จากนั้นจัดการกับมันก่อนที่จะผ่านมันไปตัวอย่างเช่น:var copy = [].slice.call(arguments); <remove what you want> myFunc.apply(this, copy);
Nick Craver

18
แต่การใช้applyเช่นนี้อาจจะกรูขึ้นขอบเขตของb(ถ้ามันเป็นฟังก์ชั่นด้านในบางส่วนของวัตถุสำหรับตัวอย่าง)
vSync

3
@vsync เป็นจุดที่ดี แต่ปัญหาง่ายต่อการแก้ไข: ส่งผ่านวัตถุเป็นอาร์กิวเมนต์แรกที่ใช้
ตาด Lispy

11
ไม่ให้ความรู้สึกที่จะใช้ "args" และ "ข้อโต้แย้ง" ด้วยกัน ...
เพื่อน

3
แต่แล้ว "นี่" อาจจะเปลี่ยนเป็นอย่างอื่นนอกเหนือจากต้นฉบับของ b นี้
trusktr

223

ผู้ประกอบการแพร่กระจาย

ตัวดำเนินการการแพร่กระจายช่วยให้การแสดงออกที่จะขยายในสถานที่ที่มีข้อโต้แย้งหลาย ๆ (สำหรับการเรียกใช้ฟังก์ชั่น) หรือหลายองค์ประกอบ (สำหรับตัวอักษรอาร์เรย์) คาดว่า

ECMAScript ES6 เพิ่มผู้ประกอบการใหม่ที่ช่วยให้คุณทำเช่นนี้ในทางปฏิบัติมากขึ้น: ...กระจายผู้ประกอบการ

ตัวอย่างโดยไม่ต้องใช้applyวิธีการ:

function a(...args){
  b(...args);
  b(6, ...args, 8) // You can even add more elements
}
function b(){
  console.log(arguments)
}

a(1, 2, 3)

Note ตัวอย่างนี้ส่งคืนข้อผิดพลาดทางไวยากรณ์หากเบราว์เซอร์ของคุณยังคงใช้ ES5

หมายเหตุจากบรรณาธิการ: เนื่องจากข้อมูลโค้ดใช้console.log()คุณต้องเปิดคอนโซล JS ของเบราว์เซอร์เพื่อดูผลลัพธ์ - จะไม่มีผลลัพธ์ในหน้าเว็บ

มันจะแสดงผลลัพธ์นี้:

รูปภาพของตัวอย่างอาร์กิวเมนต์ตัวดำเนินการสเปรด

ในระยะสั้นผู้ประกอบการแพร่กระจายสามารถนำมาใช้เพื่อวัตถุประสงค์ที่แตกต่างกันถ้าคุณกำลังใช้อาร์เรย์จึงยังสามารถนำมาใช้สำหรับการขัดแย้งฟังก์ชั่นที่คุณสามารถดูตัวอย่างที่คล้ายกันที่อธิบายไว้ในเอกสารอย่างเป็นทางการ: พารามิเตอร์ส่วนที่เหลือ


6
นี่เป็นโอเปอเรเตอร์ที่ดีมากและฉันตั้งตารอที่จะใช้ อย่างไรก็ตามมันจะไม่เกิดขึ้น เบราว์เซอร์เดียวที่รองรับผู้ให้บริการสเปรดคือ FF ในขณะนี้ ดูตารางความเข้ากันได้สำหรับข้อมูลที่สมบูรณ์และทันสมัย: kangax.github.io/compat-table/es6/#spread_%28...%29_operator
TMG

10
ทำไมจึงไม่ควรใช้ มันเป็นเรื่องง่ายที่จะ transpile กับ babel คุณจะได้รับคุณสมบัติใหม่ทั้งหมดและความเข้ากันได้กับเบราว์เซอร์รุ่นเก่า
adgelbfish

นี่เป็นวิธีที่ดีกว่าโซลูชันแรกเนื่องจากทำงานในฟังก์ชันที่กำหนดด้วยตัวดำเนินการลูกศร
sarfata

คุณไม่จำเป็นต้อง...argsอยู่ในaฟังก์ชั่น คุณสามารถสร้างฟังก์ชั่นโดยไม่มีข้อโต้แย้งและส่งต่อให้bกับ...arguments
cronoklee

1
สำหรับทุกคนที่อ่านคำตอบนี้: ตรงกันข้ามกับความคิดเห็นของ @ cronoklee การระบุ...argsว่าการaป้อนข้อมูลของชัดแจ้งอาจมีความสำคัญหากคุณมีฟังก์ชั่นที่ซ้อนกัน
Arshia001

81

คำอธิบายที่ว่าไม่มีคำตอบที่อุปกรณ์อื่น ๆ ที่มีปากเสียงเดิมที่มียังคงมีอยู่ แต่ไม่ได้อยู่ในตำแหน่งเดิมในargumentsวัตถุ

argumentsวัตถุมีองค์ประกอบสำหรับแต่ละพารามิเตอร์จริงอย่างใดอย่างหนึ่งให้กับฟังก์ชั่น เมื่อคุณเรียกaคุณจัดหาอาร์กิวเมนต์ที่สาม: ตัวเลข1, และ2 3ดังนั้นมีarguments[1, 2, 3]

function a(args){
    console.log(arguments) // [1, 2, 3]
    b(arguments);
}

เมื่อคุณเรียกbแต่คุณจะผ่านตรงหนึ่งอาร์กิวเมนต์: a's argumentsวัตถุ ดังนั้นargumentsมี[[1, 2, 3]](เช่นองค์ประกอบหนึ่งซึ่งเป็นaของargumentsวัตถุซึ่งมีคุณสมบัติที่มีข้อโต้แย้งเดิมa)

function b(args){
    // arguments are lost?
    console.log(arguments) // [[1, 2, 3]]
}

a(1,2,3);

ตามที่ @Nick สาธิตคุณสามารถใช้applyเพื่อจัดเตรียมชุดargumentsวัตถุในการโทร

ผลลัพธ์ต่อไปนี้ได้ผลลัพธ์เดียวกัน:

function a(args){
    b(arguments[0], arguments[1], arguments[2]); // three arguments
}

แต่applyเป็นทางออกที่ถูกต้องในกรณีทั่วไป


คุณควรส่งthisต่อไปapplyหรือไม่
Flimm

1
@ Flimm— ใช่เนื่องจากอาร์กิวเมนต์เป็นอาร์กิวเมนต์ที่สองจึงต้องมีบางสิ่งสำหรับอาร์กิวเมนต์แรก (อาจเป็นโมฆะ )
RobG

0

ลองนี้

function global_func(...args){
  for(let i of args){
    console.log(i)
  }
}


global_func('task_name', 'action', [{x: 'x'},{x: 'x'}], {x: 'x'}, ['x1','x2'], 1, null, undefined, false, true)




//task_name
//action
//(2) [{...},
//    {...}]
//    {
//        x:"x"
//    }
//(2) [
//        "x1",
//        "x2"
//    ]
//1
//null
//undefined
//false
//true
//func
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.