ฉันต้องการเพิ่มองค์ประกอบของอาเรย์เข้าไปอีกอันหนึ่งดังนั้นฉันจึงลองทำสิ่งนี้:
[1,2] + [3,4]
มันตอบสนองด้วย:
"1,23,4"
เกิดอะไรขึ้น?
[5,6,7][1,2]
เป็น7
เพราะใช้รายการสุดท้ายในอาร์เรย์ที่สอง Oo
ฉันต้องการเพิ่มองค์ประกอบของอาเรย์เข้าไปอีกอันหนึ่งดังนั้นฉันจึงลองทำสิ่งนี้:
[1,2] + [3,4]
มันตอบสนองด้วย:
"1,23,4"
เกิดอะไรขึ้น?
[5,6,7][1,2]
เป็น7
เพราะใช้รายการสุดท้ายในอาร์เรย์ที่สอง Oo
คำตอบ:
+
ผู้ประกอบการไม่ได้ถูกกำหนดสำหรับอาร์เรย์
สิ่งที่เกิดขึ้นคือ Javascript แปลงอาร์เรย์เป็นสตริงและเชื่อมต่อกัน
เนื่องจากคำถามนี้และด้วยเหตุนี้คำตอบของฉันจึงได้รับความสนใจเป็นอย่างมากฉันรู้สึกว่ามันจะมีประโยชน์และเกี่ยวข้องกับการมีภาพรวมเกี่ยวกับการ+
ทำงานของผู้ปฏิบัติงานโดยทั่วไปเช่นกัน
ดังนั้นนี่มันไป
ไม่รวม E4X และสิ่งเฉพาะสำหรับการใช้งาน Javascript (as ES5) มี6 ชนิดข้อมูลในตัว :
โปรดทราบว่าแม้ว่าtypeof
จะส่งกลับค่า object
เป็น Null และfunction
สำหรับวัตถุที่เรียกได้ แต่ Null ไม่ใช่วัตถุและพูดอย่างเคร่งครัดในการใช้งานจาวาสคริปต์ที่สอดคล้องกับข้อกำหนดคุณสมบัติฟังก์ชั่นทั้งหมดจะถือว่าเป็นวัตถุ
ถูกต้อง - Javascript ไม่มีอาร์เรย์แบบดั้งเดิมเช่นนี้ อินสแตนซ์ของวัตถุที่เรียกว่าArray
มีน้ำตาล syntactic เพียงเพื่อบรรเทาความเจ็บปวด
เพิ่มมากขึ้นเพื่อความสับสน, เสื้อคลุมหน่วยงานเช่นnew Number(5)
, new Boolean(true)
และnew String("abc")
มีทุกobject
ชนิดไม่ได้ตัวเลข booleans หรือสตริงเป็นหนึ่งอาจคาดหวัง อย่างไรก็ตามสำหรับตัวดำเนินการทางคณิตศาสตร์Number
และBoolean
ทำงานเป็นตัวเลข
ง่ายใช่มั้ย ด้วยวิธีการทั้งหมดที่ทำให้เราสามารถไปยังภาพรวมได้
ประเภทผลลัพธ์ที่แตกต่างกันของ+
ประเภทตัวถูกดำเนินการ
|| undefined | null | boolean | number | string | object |
=========================================================================
undefined || number | number | number | number | string | string |
null || number | number | number | number | string | string |
boolean || number | number | number | number | string | string |
number || number | number | number | number | string | string |
string || string | string | string | string | string | string |
object || string | string | string | string | string | string |
* ใช้กับ Chrome13, FF6, Opera11 และ IE9 การตรวจสอบเบราว์เซอร์และรุ่นอื่น ๆ นั้นจะเป็นแบบฝึกหัดสำหรับผู้อ่าน
หมายเหตุ:ในฐานะที่เป็นแหลมออกโดยCMSสำหรับบางกรณีของวัตถุเช่นNumber
, Boolean
และคนที่กำหนดเอง+
ผู้ประกอบการไม่จำเป็นต้องผลิตผลสตริง มันอาจแตกต่างกันไปขึ้นอยู่กับการนำวัตถุไปใช้กับการแปลงดั้งเดิม ยกตัวอย่างเช่นvar o = { valueOf:function () { return 4; } };
การประเมินผลการo + 2;
ผลิต6
ที่มีnumber
การประเมินผลo + '2'
การผลิตเป็น'42'
string
หากต้องการดูวิธีสร้างตารางภาพรวมโปรดไปที่http://jsfiddle.net/1obxuc7m/
+
ตัวดำเนินการของ JavaScript มีจุดประสงค์สองประการ: เพิ่มตัวเลขสองตัวหรือเข้าร่วมสองสาย มันไม่มีพฤติกรรมที่เฉพาะเจาะจงสำหรับอาร์เรย์ดังนั้นมันจึงแปลงเป็นสตริงแล้วจึงเข้าร่วม
หากคุณต้องการที่จะเข้าร่วมสองอาร์เรย์ในการผลิตใหม่ใช้วิธีการแทน:.concat
[1, 2].concat([3, 4]) // [1, 2, 3, 4]
ถ้าคุณต้องการเพิ่มองค์ประกอบทั้งหมดจากอาร์เรย์หนึ่งไปยังอีกอย่างมีประสิทธิภาพคุณต้องใช้วิธีการ. push :
var data = [1, 2];
// ES6+:
data.push(...[3, 4]);
// or legacy:
Array.prototype.push.apply(data, [3, 4]);
// data is now [1, 2, 3, 4]
พฤติกรรมของ+
ผู้ปฏิบัติงานถูกกำหนดไว้ในECMA-262 5e มาตรา 11.6.1 :
11.6.1 ผู้ประกอบการเพิ่มเติม (+)
ตัวดำเนินการการเติมดำเนินการต่อสตริงหรือการเพิ่มตัวเลข การผลิต
AdditiveExpression : AdditiveExpression + MultiplicativeExpression
ได้รับการประเมินดังนี้:
- อนุญาตเป็นผลมาจากการประเมิน
lref
AdditiveExpression
- อนุญาตเป็น
lval
GetValue(lref)
- อนุญาตเป็นผลมาจากการประเมิน
rref
MultiplicativeExpression
- อนุญาตเป็น
rval
GetValue(rref)
- อนุญาตเป็น
lprim
ToPrimitive(lval)
- อนุญาตเป็น
rprim
ToPrimitive(rval)
- ถ้า
Type(lprim)
เป็นString
หรือType(rprim)
เป็นString
แล้ว
- ส่งคืนสตริงที่เป็นผลลัพธ์ของการต่อกัน
ToString(lprim)
ตามด้วยToString(rprim)
- กลับผลของการใช้การดำเนินการนอกเหนือไปจากและ
ToNumber(lprim)
ToNumber(rprim)
ดูหมายเหตุด้านล่าง 11.6.3
ToPrimitive
คุณจะเห็นว่าแต่ละตัวถูกดำเนินการจะถูกแปลง โดยการอ่านเพิ่มเติมเราจะพบว่าToPrimitive
จะแปลงอาร์เรย์เป็นสตริงเสมอโดยสร้างผลลัพธ์นี้
Array.prototype.push.apply(data, [3, 4])
แทนdata.concat([3,4])
?
concat
สร้างArray ใหม่อีกต่อไปการโทรที่ยาวขึ้นจะเป็นการเพิ่มArray ที่มีอยู่
[].push.apply(data, [3,4])
verbosity น้อยกว่าเล็กน้อย นอกจากนี้ที่รับประกันได้ว่าจะทนกับคนอื่น ๆ Array
ที่มีการเปลี่ยนแปลงค่าของ
มันจะเพิ่มสองอาร์เรย์ราวกับว่าพวกเขาสตริง
การเป็นตัวแทนสตริงสำหรับอาร์เรย์แรกจะเป็น"1,2"และครั้งที่สองจะเป็น"3,4" ดังนั้นเมื่อ+
พบสัญญาณแล้วจะไม่สามารถหาผลรวมของอาร์เรย์และต่อกันเป็นสตริงได้
+
สตริง concats จึงแปลงอาร์เรย์สตริง
[1,2] + [3,4]
'1,2' + '3,4'
1,23,4
concat
ที่จะรวมอาร์เรย์ใช้
[1,2].concat([3,4])
[1,2,3,4]
ใน JavaScript ตัวดำเนินการเพิ่มไบนารี ( +
) ดำเนินการทั้งการบวกเชิงตัวเลขและการต่อสตริง อย่างไรก็ตามเมื่ออาร์กิวเมนต์แรกไม่ใช่ตัวเลขหรือสตริงก็จะแปลงเป็นสตริง (ดังนั้น " 1,2
") จากนั้นก็จะทำเช่นเดียวกันกับตัวที่สอง " 3,4
" และต่อกันเป็น " 1,23,4
"
ลองใช้วิธี "concat" ของ Arrays แทน:
var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];
มันจะแปลงแต่ละอาร์เรย์เป็นสตริงจากนั้นรวมสตริง
ดูเหมือนว่า JavaScript กำลังเปลี่ยนอาร์เรย์ของคุณเป็นสตริงและรวมเข้าด้วยกัน หากคุณต้องการเพิ่มสิ่งอันดับด้วยกันคุณจะต้องใช้การวนซ้ำหรือฟังก์ชั่นแผนที่
[1,2]+[3,4]
ใน JavaScript เหมือนกับการประเมิน:
new Array( [1,2] ).toString() + new Array( [3,4] ).toString();
และเพื่อแก้ปัญหาของคุณสิ่งที่ดีที่สุดคือการเพิ่มสองอาร์เรย์ในสถานที่หรือไม่สร้างอาร์เรย์ใหม่:
var a=[1,2];
var b=[3,4];
a.push.apply(a, b);
มันทำสิ่งที่คุณขอให้ทำ
สิ่งที่คุณกำลังเพิ่มเข้าด้วยกันคือการอ้างอิงอาร์เรย์ (ซึ่ง JS แปลงเป็นสตริง) ไม่ใช่ตัวเลขตามที่เห็น มันเหมือนกับการเพิ่มสตริงเข้าด้วยกัน: "hello " + "world"
="hello world"
จะดีถ้าคุณสามารถโอเวอร์โหลดโอเปอเรเตอร์ใน JavaScript แต่คุณไม่สามารถ: ฉันสามารถกำหนดโอเปอร์เรเตอร์ที่กำหนดเองใน Javascript ได้ไหม คุณสามารถแฮ็กโอเปอเรเตอร์ "==" เท่านั้นซึ่งจะแปลงเป็นสตริงก่อนที่จะเปรียบเทียบ: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx
เป็นเพราะตัวดำเนินการ + ถือว่าโอเปอเรเตอร์เป็นสตริงหากไม่ใช่ตัวดำเนินการ ดังนั้นก่อนอื่นให้แปลงเป็นสตริงและ concats เพื่อให้ผลลัพธ์สุดท้ายหากไม่ใช่ตัวเลข นอกจากนี้ยังไม่รองรับอาร์เรย์
คำตอบบางส่วนได้อธิบายถึงวิธีการที่ผลลัพธ์ที่ไม่คาดคิด'1,23,4'
เกิดขึ้น( ) และบางส่วนได้อธิบายวิธีการรับสิ่งที่พวกเขาคิดว่าจะเป็นผลลัพธ์ที่ต้องการ ( [1,2,3,4]
) เช่นการต่อเรียงอาเรย์ อย่างไรก็ตามลักษณะของผลลัพธ์ที่ต้องการนั้นค่อนข้างคลุมเครือเพราะคำถามดั้งเดิมกล่าวไว้ง่ายๆว่า "ฉันต้องการเพิ่มองค์ประกอบของอาเรย์เข้าไปอีก ... " นั่นอาจหมายถึงการเรียงต่อกันอาร์เรย์ แต่มันอาจจะยังนอกจากเฉลี่ย tuple (เช่นที่นี่และที่นี่ ) คือการเพิ่มค่าสเกลาขององค์ประกอบในอาร์เรย์กับค่าสเกลาขององค์ประกอบที่สอดคล้องกันในครั้งที่สองเช่นการรวม[1,2]
และการที่จะได้รับ[3,4]
[4,6]
สมมติว่าทั้งสองอาร์เรย์มี arity / length เหมือนกันนี่เป็นวิธีแก้ปัญหาง่ายๆ
const arr1 = [1, 2];
const arr2 = [3, 4];
const add = (a1, a2) => a1.map((e, i) => e + a2[i]);
console.log(add(arr1, arr2)); // ==> [4, 6]
ผลลัพธ์อีกรายการที่ใช้เพียงแค่เครื่องหมาย "+" ง่ายๆก็คือ:
[1,2]+','+[3,4] === [1,2,3,4]
ดังนั้นสิ่งนี้ควรใช้งานได้ (แต่!):
var a=[1,2];
var b=[3,4];
a=a+','+b; // [1,2,3,4]
... แต่มันจะแปลงตัวแปร a จาก Array เป็น String! เก็บไว้ในใจ