Tôi muốn thêm các phần tử của một mảng vào một mảng khác, vì vậy tôi đã thử điều này:
[1,2] + [3,4]
Nó trả lời với:
"1,23,4"
Chuyện gì đang xảy ra vậy?
[5,6,7][1,2]
là 7
vì nó sử dụng mục cuối cùng trong mảng thứ hai. Oo
Tôi muốn thêm các phần tử của một mảng vào một mảng khác, vì vậy tôi đã thử điều này:
[1,2] + [3,4]
Nó trả lời với:
"1,23,4"
Chuyện gì đang xảy ra vậy?
[5,6,7][1,2]
là 7
vì nó sử dụng mục cuối cùng trong mảng thứ hai. Oo
Câu trả lời:
Các +
nhà điều hành không được định nghĩa cho mảng .
Điều gì xảy ra là Javascript chuyển đổi các mảng thành chuỗi và nối các chuỗi đó.
Vì câu hỏi này và do đó, câu trả lời của tôi đang được chú ý rất nhiều, tôi cảm thấy nó sẽ hữu ích và phù hợp để có cái nhìn tổng quan về cách +
hành xử của người vận hành nói chung.
Vì vậy, ở đây nó đi.
Không bao gồm E4X và triển khai cụ thể các công cụ, Javascript (như của ES5) có 6 built-in các kiểu dữ liệu :
Lưu ý rằng mặc dù typeof
trả lại một cách khó hiểu object
cho Null vàfunction
cho các Đối tượng có thể gọi được, Null thực sự không phải là Đối tượng và nói đúng ra, trong các triển khai Javascript tuân thủ đặc tả, tất cả các chức năng đều được coi là Đối tượng.
Điều đó đúng - Javascript không có mảng nguyên thủy như vậy; chỉ các trường hợp của một đối tượng được gọi Array
với một số đường cú pháp để giảm đau.
Thêm nhiều hơn vào sự nhầm lẫn, các thực thể của trình bao bọc new Number(5)
, new Boolean(true)
và new String("abc")
là tất cả các object
loại, không phải là số, booleans hoặc chuỗi như người ta có thể mong đợi. Tuy nhiên, đối với các toán tử số học Number
và Boolean
hành xử như số.
Dễ chứ hả? Với tất cả những điều đó, chúng ta có thể chuyển sang phần tổng quan.
Các loại kết quả khác nhau của các +
loại toán hạng
|| 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 |
* áp dụng cho Chrome13, FF6, Opera11 và IE9. Kiểm tra các trình duyệt và phiên bản khác là một bài tập cho người đọc.
Lưu ý: Như được chỉ ra bởi CMS , đối với một số trường hợp nhất định của các đối tượng Number
, Boolean
và các đối tượng tùy chỉnh, +
toán tử không nhất thiết phải tạo ra kết quả chuỗi. Nó có thể thay đổi tùy thuộc vào việc thực hiện đối tượng để chuyển đổi nguyên thủy. Ví dụ: var o = { valueOf:function () { return 4; } };
đánh giá o + 2;
sản xuất 6
, a number
, đánh giá o + '2'
sản xuất '42'
, astring
.
Để xem bảng tổng quan được tạo như thế nào, hãy truy cập http://jsfiddle.net/1obxuc7m/
+
Toán tử của JavaScript có hai mục đích: thêm hai số hoặc nối hai chuỗi. Nó không có hành vi cụ thể cho mảng, vì vậy nó chuyển đổi chúng thành chuỗi và sau đó nối chúng.
Nếu bạn muốn tham gia hai mảng để tạo ra một hình mới, sử dụng các .concat
phương pháp thay vì:
[1, 2].concat([3, 4]) // [1, 2, 3, 4]
Nếu bạn muốn thêm hiệu quả tất cả các phần tử từ mảng này sang mảng khác, bạn cần sử dụng phương thức .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]
Hành vi của +
toán tử được định nghĩa trong ECMA-262 5e Mục 11.6.1 :
11.6.1 Toán tử bổ sung (+)
Toán tử cộng hoặc thực hiện nối chuỗi hoặc cộng số. Việc sản xuất
AdditiveExpression : AdditiveExpression + MultiplicativeExpression
được đánh giá như sau:
- Hãy
lref
là kết quả của việc đánh giáAdditiveExpression
.- Hãy để
lval
nóGetValue(lref)
.- Hãy
rref
là kết quả của việc đánh giáMultiplicativeExpression
.- Hãy để
rval
nóGetValue(rref)
.- Hãy để
lprim
nóToPrimitive(lval)
.- Hãy để
rprim
nóToPrimitive(rval)
.- Nếu
Type(lprim)
làString
hoặcType(rprim)
làString
, thì
- Trả về Chuỗi là kết quả của việc nối
ToString(lprim)
tiếp theo sauToString(rprim)
- Trả về kết quả của việc áp dụng các hoạt động bổ sung cho
ToNumber(lprim)
vàToNumber(rprim)
. Xem chú thích bên dưới 11.6.3.
Bạn có thể thấy rằng mỗi toán hạng được chuyển đổi ToPrimitive
. Bằng cách đọc thêm chúng ta có thể thấy rằng ToPrimitive
sẽ luôn chuyển đổi các mảng thành chuỗi, tạo ra kết quả này.
Array.prototype.push.apply(data, [3, 4])
thay vì data.concat([3,4])
?
concat
tạo ra một Mảng mới , cuộc gọi dài hơn có hiệu quả mở rộng một Mảng hiện có .
[].push.apply(data, [3,4])
cho độ dài ít hơn một chút. Ngoài ra, điều đó được đảm bảo để chống lại những người khác thay đổi giá trị của Array
.
Nó thêm hai mảng như thể chúng là các chuỗi .
Biểu diễn chuỗi cho mảng đầu tiên sẽ là "1,2" và chuỗi thứ hai sẽ là "3,4" . Vì vậy, khi +
tìm thấy dấu hiệu, nó không thể tính tổng các mảng và sau đó ghép chúng thành các chuỗi.
Các +
chuỗi concats, do đó, nó chuyển đổi các mảng thành chuỗi.
[1,2] + [3,4]
'1,2' + '3,4'
1,23,4
Để kết hợp mảng, sử dụng concat
.
[1,2].concat([3,4])
[1,2,3,4]
Trong JavaScript, toán tử cộng nhị phân ( +
) thực hiện cả phép cộng số và nối chuỗi. Tuy nhiên, khi đối số đầu tiên của nó không phải là một số cũng không phải là một chuỗi thì nó sẽ chuyển đổi nó thành một chuỗi (do đó " 1,2
"), sau đó nó làm tương tự với "" thứ hai 3,4
và nối chúng thành " 1,23,4
".
Thay vào đó, hãy thử sử dụng phương pháp "concat" của Mảng:
var a = [1, 2];
var b = [3, 4];
a.concat(b) ; // => [1, 2, 3, 4];
Có vẻ như JavaScript đang biến các mảng của bạn thành các chuỗi và nối chúng lại với nhau. Nếu bạn muốn thêm các bộ dữ liệu với nhau, bạn sẽ phải sử dụng một vòng lặp hoặc chức năng bản đồ.
[1,2]+[3,4]
trong JavaScript cũng giống như đánh giá:
new Array( [1,2] ).toString() + new Array( [3,4] ).toString();
và vì vậy để giải quyết vấn đề của bạn, điều tốt nhất là thêm hai mảng tại chỗ hoặc không tạo một mảng mới:
var a=[1,2];
var b=[3,4];
a.push.apply(a, b);
Đó là làm chính xác những gì bạn yêu cầu nó làm.
Những gì bạn đang thêm vào là các tham chiếu mảng (mà JS chuyển đổi thành chuỗi), không phải là số như có vẻ. Nó hơi giống như thêm các chuỗi lại với nhau: "hello " + "world"
="hello world"
sẽ rất tuyệt nếu bạn có thể quá tải toán tử trong JavaScript nhưng bạn không thể: Tôi có thể xác định quá tải toán tử tùy chỉnh trong Javascript không? bạn chỉ có thể hack toán tử "==" chuyển đổi thành chuỗi trước khi so sánh: http://blogger.xs4all.nl/peterned/archive/2009/04/01/462517.aspx
Đó là bởi vì, toán tử + giả định rằng các toán hạng là chuỗi, nếu chúng không phải là số. Vì vậy, trước tiên, nó chuyển đổi chúng thành chuỗi và concats để đưa ra kết quả cuối cùng, nếu đó không phải là một số. Ngoài ra, nó không hỗ trợ mảng.
Một số câu trả lời ở đây đã giải thích làm thế nào đầu ra không mong muốn ( '1,23,4'
) không mong muốn xảy ra và một số đã giải thích làm thế nào để có được cái mà họ cho là đầu ra mong muốn ( [1,2,3,4]
), nghĩa là nối mảng. Tuy nhiên, bản chất của đầu ra mong muốn thực sự hơi mơ hồ vì câu hỏi ban đầu chỉ đơn giản là "Tôi muốn thêm các phần tử của một mảng vào một ...". Điều đó có thể có nghĩa là nối mảng nhưng cũng có thể có nghĩa là bổ sung tuple (ví dụ ở đây và ở đây ), nghĩa là thêm các giá trị vô hướng của các phần tử trong một mảng vào các giá trị vô hướng của các phần tử tương ứng trong phần thứ hai, ví dụ: kết hợp [1,2]
và [3,4]
thu được[4,6]
.
Giả sử cả hai mảng có cùng độ dài / độ dài, đây là một giải pháp đơn giản:
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]
Một kết quả khác chỉ sử dụng dấu "+" đơn giản sẽ là:
[1,2]+','+[3,4] === [1,2,3,4]
Vì vậy, một cái gì đó như thế này sẽ hoạt động (nhưng!):
var a=[1,2];
var b=[3,4];
a=a+','+b; // [1,2,3,4]
... nhưng nó sẽ chuyển đổi biến a từ Mảng thành Chuỗi! Hãy ghi nhớ nó.