ผ่านอาร์เรย์เป็นพารามิเตอร์ฟังก์ชันใน JavaScript


292

ฉันต้องการเรียกใช้ฟังก์ชันโดยใช้อาร์เรย์เป็นพารามิเตอร์:

const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it

function call_me (param0, param1, param2 ) {
  // ...
}

มีวิธีที่ดีกว่าในการส่งผ่านเนื้อหาของxลงในcall_me()?

คำตอบ:


422
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);

ดูเอกสาร MDN Function.prototype.apply()สำหรับ


หากสภาพแวดล้อมรองรับ ECMAScript 6 คุณสามารถใช้อาร์กิวเมนต์การกระจายแทน:

call_me(...args);

9
ในฐานะที่เป็นบันทึกด้านข้างถ้าใครต้องการที่จะผ่านอาร์เรย์ที่เชื่อมโยง (คีย์ที่มีชื่อ) แทนแล้วใช้วัตถุ มาจาก PHP (และนำไปสู่กระทู้นี้โดย google) ทำให้ฉันต้องใช้เวลาพอสมควร คุณสามารถผ่านวัตถุทั้งหมดเป็นพารามิเตอร์แล้ว w3schools.com/js/js_objects.asp
timhc22

ขอบคุณสำหรับการชี้ให้เห็นข้อโต้แย้ง 'การแพร่กระจาย'! ไม่รู้เรื่องเลย
โทมัส An

@ Timhc - ความคิดเห็นด้านข้างของคุณนั้นน่าสนใจ แต่ฉันไม่สามารถแยกมันได้ (ฉันเป็นจาวาสคริปต์ที่ไม่มีงานทำผ่านแบบฝึกหัดสองสามข้อ) ใน JS อาร์เรย์ที่เชื่อมโยงเป็นวัตถุตามบทเรียนหลายบท
NateT

@ timhc22 และเมื่อใช้ออบเจ็กต์ json เพื่อส่งผ่านเป็นพารามิเตอร์ไปยังฟังก์ชันอย่าลืมการทำลายพารามิเตอร์เพื่อให้อ่านง่ายขึ้น
Muhammad Omer Aslam

113

ทำไมคุณไม่ผ่านอาร์เรย์ทั้งหมดและดำเนินการตามที่จำเป็นในฟังก์ชั่น?

var x = [ 'p0', 'p1', 'p2' ]; 
call_me(x);

function call_me(params) {
  for (i=0; i<params.length; i++) {
    alert(params[i])
  }
}

37
เป็นเพราะฉันไม่สามารถแก้ไข call_me () มันถูกกำหนดไว้ในไลบรารี่อื่นและมันเป็นไปไม่ได้ที่จะยุ่งกับ API
Robert

62
+1 เพราะแม้ว่าจะไม่ได้ตอบคำถามเดิม แต่อาจเป็นสิ่งที่ผู้คนที่ดูหน้านี้กำลังมองหา
Ishikawa

บางคนสามารถอธิบายว่าบรรทัด "call_me (x)" ทำอะไรได้บ้าง ดูเหมือนว่าเป็นชื่อฟังก์ชันที่ไม่มีคีย์เวิร์ดของฟังก์ชัน? มันทำอะไรกันแน่?
ว่าย

1
@swam มันเป็นการเรียกใช้call_meฟังก์ชัน มันขาดเซมิโคลอนในตอนท้าย
SantiBailors

@ สวิตช์จะทำการประมวลผลฟังก์ชัน call_me (params) ที่ประกาศไว้
Julio Rodriguez

43

สมมติว่า call_me เป็นฟังก์ชันสากลดังนั้นคุณจึงไม่คาดหวังว่าจะได้รับการตั้งค่านี้

var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);

41

ในมาตรฐาน ES6 มีตัวดำเนินการส เปรดใหม่...ซึ่งทำสิ่งนั้นอย่างแน่นอน

call_me(...x)

ได้รับการสนับสนุนโดยเบราว์เซอร์หลักทั้งหมดยกเว้น IE

ผู้ดำเนินการแพร่กระจายสามารถทำสิ่งที่มีประโยชน์อื่น ๆ อีกมากมายและเอกสารที่เชื่อมโยงนั้นทำได้ดีมากในการแสดงว่า



7

@KaptajnKold ได้ตอบแล้ว

var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);

และคุณไม่จำเป็นต้องกำหนดทุกพารามิเตอร์สำหรับฟังก์ชัน call_me คุณสามารถใช้arguments

function call_me () {
    // arguments is a array consisting of params.
    // arguments[0] == 'p0',
    // arguments[1] == 'p1',
    // arguments[2] == 'p2'
}

4
นี่เป็นการฝึกฝนที่ไม่ดี ... คุณจะไม่สามารถเห็นสิ่งที่ฟังก์ชั่นต้องการและพารามิเตอร์ทุกตัวเป็นตัวเลือกถ้าคุณดูที่ฟังก์ชั่น
Robin

3

จดบันทึกสิ่งนี้

function FollowMouse() {
    for(var i=0; i< arguments.length; i++) {
        arguments[i].style.top = event.clientY+"px";
        arguments[i].style.left = event.clientX+"px";
    }

};

// ---------------------------

หน้า html

<body onmousemove="FollowMouse(d1,d2,d3)">

<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>


</body>

สามารถเรียกใช้ฟังก์ชันด้วย Args ใด ๆ

<body onmousemove="FollowMouse(d1,d2)">

หรือ

<body onmousemove="FollowMouse(d1)">

นี่เป็นส่วนหนึ่งของคำตอบที่ชัดเจน จำเป็นต้องมี "อาร์กิวเมนต์" เพื่อรับอาร์เรย์กลับมาหลังจากการโทร ขอบคุณ!
FlorianB

2

ฟังก์ชันอาร์กิวเมนต์อาจเป็นอาร์เรย์:

function foo([a,b,c], d){
  console.log(a,b,c,d);
}

foo([1,2,3], 4)

แน่นอนหนึ่งสามารถใช้สเปรด :

function foo(a, b, c, d){
  console.log(a, b, c, d);
}

foo(...[1, 2, 3], 4)


2

ในขณะที่ใช้โอเปอเรเตอร์สเปรดเราต้องทราบว่ามันจะต้องผ่านพารามิเตอร์ตัวสุดท้ายหรืออย่างเดียวเท่านั้น มิฉะนั้นจะล้มเหลว

function callMe(...arr){ //valid arguments
    alert(arr);
}

function callMe(name, ...arr){ //valid arguments
    alert(arr);
}

function callMe(...arr, name){ //invalid arguments
    alert(arr);
}

หากคุณต้องการส่งผ่านอาร์เรย์เป็นอาร์กิวเมนต์เริ่มต้นคุณสามารถทำได้:

function callMe(arr, name){
    let newArr = [...arr];
    alert(newArr);
}

1

คุณสามารถใช้ตัวดำเนินการสเปรดในรูปแบบพื้นฐานเพิ่มเติม

[].concat(...array)

ในกรณีของฟังก์ชั่นที่ส่งกลับอาร์เรย์ แต่คาดว่าจะผ่านเป็นข้อโต้แย้ง

ตัวอย่าง:

function expectArguments(...args){
  return [].concat(...args);
}

JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))

0

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

ดังนั้นเราจึงมีฟังก์ชั่นการแฮ็ช "super" ซึ่งรับสองตัวเลขเป็นอาร์กิวเมนต์และส่งคืนสตริงแฮช "super safe":

function hash() {
  return arguments[0]+','+arguments[1];
}

hash(1,2); // "1,2" whoaa

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

วิธีแก้ปัญหาตามธรรมชาติจะใช้arr.joinวิธี:

function hash() {
  return arguments.join();
}

hash(1,2,4,..); //  Error: arguments.join is not a function

โอ้มนุษย์ น่าเสียดายที่มันใช้ไม่ได้ เนื่องจากเรากำลังเรียกแฮช (อาร์กิวเมนต์) และวัตถุอาร์กิวเมนต์เป็นทั้ง iterable และ array เหมือน แต่ไม่ใช่อาร์เรย์จริง วิธีการเกี่ยวกับวิธีการด้านล่าง?

function hash() {
  return [].join.call(arguments);
}

hash(1,2,3,4); // "1,2,3,4" whoaa

เคล็ดลับที่เรียกว่า method borrowing.

เรายืมjoinวิธีจากอาร์เรย์ปกติ[].join.และใช้ในการทำงานในบริบทของ[].join.callarguments

ทำไมมันทำงาน

นั่นเป็นเพราะอัลกอริทึมภายในของวิธีการเนทิฟarr.join(glue)นั้นง่ายมาก

นำมาจากข้อมูลจำเพาะเกือบ“ ตามสภาพ”:

Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
Do so until this.length items are glued.
Return result.

ดังนั้นในทางเทคนิคมันต้องใช้สิ่งนี้และเข้าร่วมกับ [0], [1] นี้ ... ฯลฯ พร้อมกัน มันเขียนโดยเจตนาในลักษณะที่อนุญาตให้มีอาเรย์แบบนี้ (ไม่ใช่เรื่องบังเอิญหลายวิธีทำตามแบบฝึกหัดนี้) นั่นเป็นเหตุผลที่มันยังทำงานได้ด้วยthis=arguments.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.