Bạn có thể làm như vậy:
var N = 10;
Array.apply(null, {length: N}).map(Number.call, Number)
kết quả: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
hoặc với các giá trị ngẫu nhiên:
Array.apply(null, {length: N}).map(Function.call, Math.random)
kết quả: [0.7082694901619107, 0.9572225909214467, 0.8586748542729765, 0.8653848143294454, 0,00839877473190427, 0.9911756622605026, 0.8133423360995948, 0.8377588757575
Giải trình
Đầu tiên, lưu ý rằng Number.call(undefined, N)
tương đương với Number(N)
, mà chỉ trả về N
. Chúng ta sẽ sử dụng thực tế đó sau.
Array.apply(null, [undefined, undefined, undefined])
tương đương với Array(undefined, undefined, undefined)
, nó tạo ra một mảng ba phần tử và gán undefined
cho từng phần tử.
Làm thế nào bạn có thể khái quát điều đó cho N yếu tố? Xem xét cách thức Array()
hoạt động, đi như thế này:
function Array() {
if ( arguments.length == 1 &&
'number' === typeof arguments[0] &&
arguments[0] >= 0 && arguments &&
arguments[0] < 1 << 32 ) {
return [ … ]; // array of length arguments[0], generated by native code
}
var a = [];
for (var i = 0; i < arguments.length; i++) {
a.push(arguments[i]);
}
return a;
}
Kể từ ECMAScript 5 , Function.prototype.apply(thisArg, argsArray)
cũng chấp nhận một đối tượng giống như mảng gõ vịt làm tham số thứ hai của nó. Nếu chúng ta gọi Array.apply(null, { length: N })
, nó sẽ thực thi
function Array() {
var a = [];
for (var i = 0; i < /* arguments.length = */ N; i++) {
a.push(/* arguments[i] = */ undefined);
}
return a;
}
Bây giờ chúng ta có một mảng N -element, với mỗi phần tử được đặt thành undefined
. Khi chúng ta gọi .map(callback, thisArg)
nó, mỗi phần tử sẽ được đặt thành kết quả của callback.call(thisArg, element, index, array)
. Do đó, [undefined, undefined, …, undefined].map(Number.call, Number)
sẽ ánh xạ từng phần tử tới (Number.call).call(Number, undefined, index, array)
, giống như Number.call(undefined, index, array)
, như chúng ta đã quan sát trước đó, đánh giá index
. Điều đó hoàn thành mảng có các phần tử giống như chỉ mục của chúng.
Tại sao phải trải qua những rắc rối Array.apply(null, {length: N})
thay vì chỉ Array(N)
? Rốt cuộc, cả hai biểu thức sẽ dẫn đến một mảng N -element của các phần tử không xác định. Sự khác biệt là trong biểu thức trước, mỗi phần tử được đặt rõ ràng thành không xác định, trong khi ở phần sau, mỗi phần tử không bao giờ được đặt. Theo tài liệu của .map()
:
callback
chỉ được gọi cho các chỉ mục của mảng có các giá trị được gán; nó không được gọi cho các chỉ mục đã bị xóa hoặc chưa bao giờ được gán giá trị.
Do đó, Array(N)
là không đủ; Array(N).map(Number.call, Number)
sẽ cho kết quả trong một mảng chưa được khởi tạo có độ dài N .
Khả năng tương thích
Vì kỹ thuật này dựa trên hành vi Function.prototype.apply()
được chỉ định trong ECMAScript 5, nên nó sẽ không hoạt động trong các trình duyệt tiền ECMAScript 5 như Chrome 14 và Internet Explorer 9.