Hàm
Spread và Rest
Toán tử spread và rest của Node.js so với tham số variadic thật trong Swift và Java, slice destructuring trong Rust, và `...T` trong Go.
- Phiên bản tối thiểu
- Node.js ≥ 12.20Go ≥ 1.18Rust ≥ 1.58Swift ≥ 5.1Java ≥ 25
- Đã chạy thử trên
- Node.js 24.12.0Go 1.27.1Rust 1.98.1Swift 6.2.4Java 25.0.4.1
Code Node.js là ES module: lưu file .mjs hoặc đặt "type": "module" trong package.json.
Node.js dùng cùng một ký hiệu ... cho hai việc trái ngược nhau: "trải" một mảng thành nhiều giá trị (spread) và "gom" nhiều giá trị thành một mảng (rest). Go tách hai việc này ra: ... khi gọi hàm để trải một slice, và ...T trong khai báo tham số để gom thành slice. Swift và Java có tham số variadic thật (Int..., int...) — gần với rest của JS nhất; Java thậm chí cho phép truyền thẳng một mảng có sẵn vào tham số variadic, gần giống spread. Rust không có spread lẫn rest theo nghĩa JS: mảng cỡ cố định thì destructure qua pattern, còn "nhiều tham số" thì nhận một slice.
Spread operator
const array = [1, 2, 3, 4, 5];
console.log(...array); // 1 2 3 4 5package main
import "fmt"
func main() {
array := []byte{1, 2, 3, 4, 5}
var i []any // any = interface{}, chứa được phần tử khác kiểu
for _, value := range array {
i = append(i, value)
}
fmt.Println(i...) // 1 2 3 4 5
}fn main() {
let array = [1, 2, 3, 4, 5];
// Rust không có spread; một mảng cỡ cố định thì destructure được qua
// pattern rồi in từng biến — không tổng quát hoá cho mảng cỡ động.
let [a, b, c, d, e] = array;
println!("{a} {b} {c} {d} {e}"); // 1 2 3 4 5
}let array = [1, 2, 3, 4, 5]
// Swift không spread một mảng vào tham số variadic; phải join thủ công.
print(array.map(String.init).joined(separator: " ")) // 1 2 3 4 5static String joinAll(Object... items) {
return Arrays.stream(items).map(String::valueOf).collect(Collectors.joining(" "));
}
void main() {
Integer[] array = {1, 2, 3, 4, 5};
// truyền thẳng một mảng có sẵn vào tham số variadic — gần nhất với spread
IO.println(joinAll((Object[]) array)); // 1 2 3 4 5
}Rest operator
function sum(...nums) {
let t = 0;
for (let n of nums) {
t += n;
}
return t;
}
console.log(sum(1, 2, 3, 4, 5)); // 15func sum(nums ...int) int {
var t int
for _, n := range nums {
t += n
}
return t
}
func main() {
fmt.Println(sum(1, 2, 3, 4, 5)) // 15
}// Rust không có hàm variadic thật; tương đương gần nhất là nhận một slice.
fn sum(nums: &[i32]) -> i32 {
nums.iter().sum()
}
fn main() {
println!("{}", sum(&[1, 2, 3, 4, 5])); // 15
}// Swift có tham số variadic thật, gần với rest của JS nhất.
func sum(_ nums: Int...) -> Int {
nums.reduce(0, +)
}
print(sum(1, 2, 3, 4, 5)) // 15// Java cũng có tham số variadic thật.
static int sum(int... nums) {
int total = 0;
for (int n : nums) total += n;
return total;
}
void main() {
IO.println(sum(1, 2, 3, 4, 5)); // 15
}Khác biệt chính
Node.js (...) |
Go (...) |
Rust | Swift | Java | |
|---|---|---|---|---|---|
| Trải mảng thành các đối số | fn(...arr) |
fn(slice...) (chỉ với tham số variadic) |
không có; destructure mảng cỡ cố định qua pattern | không có; phải join thủ công | mảng có sẵn truyền thẳng vào tham số variadic |
| Gom tham số thành mảng/slice | function f(...args) |
func f(args ...T) |
nhận &[T] (không phải variadic thật) |
func f(_ args: T...) (variadic thật) |
void f(T... args) (variadic thật) |
| Kiểu phần tử | có thể khác nhau (mixed) | phải cùng kiểu T (hoặc dùng any) |
phải cùng kiểu T |
phải cùng kiểu T |
phải cùng kiểu T (hoặc Object...) |
Tham khảo: github.com/miguelmota/golang-for-nodejs-developers#spread-operator