Làm thế nào để các hàm bậc cao hơn, như .map (), hoạt động nội bộ trong JavaScript?


17

Ngày nay mọi người đều cố gắng sử dụng các loại hàm bậc cao hơn này để có được kết quả đầy hứa hẹn với việc viết ít mã hơn. Nhưng tôi tự hỏi làm thế nào các chức năng này hoạt động trong nội bộ.

Giả sử nếu tôi viết một cái gì đó như

var numbers = [16, 25, 36];
var results = numbers.map(Math.sqrt);
console.log(results); // [4, 5, 6]

Tôi biết rằng mỗi phần tử của mảng 'số' đang lặp lại từng phần một, nhưng bằng cách nào ?

Tôi đã cố gắng tìm kiếm nó, nhưng tôi chưa nhận được câu trả lời thỏa đáng nào.


10
Hãy xem qua polyfil của Array.map
AZ_

Đó là một hàm được gọi là mapđã được thêm vào kiểu Array. Hàm này lấy một hàm làm tham số sau đó được gọi trong khi lặp qua mảng. Các giá trị trả về của các lệnh gọi hàm sau đó được trả về trong một mảng.
ssc-hrep3

ánh xạ về cơ bản hoạt động giống như foreach để lặp lại mảng có nghĩa là nó sẽ lấy tất cả các phần tử của từng mảng một và sau đó áp dụng lệnh / thao tác đã cho trên mỗi phần tử và sau đó đẩy nó vào mảng mới.
Adnan Tariq

Câu trả lời:


23

.mapchỉ là một phương thức chấp nhận một cuộc gọi lại, gọi lại cuộc gọi cho mọi mục của mảng và gán giá trị cho một mảng mới. Không có gì đặc biệt về nó. Bạn thậm chí có thể tự thực hiện nó khá dễ dàng:

Array.prototype.myMap = function(callback) {
  const newArr = [];
  for (let i = 0; i < this.length; i++) {
    newArr.push(callback(this[i], i, this));
  }
  return newArr;
}

var numbers = [16, 25, 36];
var results = numbers.myMap(Math.sqrt);
console.log(results); // [4, 5, 6]

Để tuân thủ đầy đủ thông số kỹ thuật, bạn cũng cần kiểm tra, trong số những thứ khác, đó có phải thislà một đối tượng, có callbackthể gọi được không, và .callgọi lại với tham số thứ hai được truyền cho myMapnếu có, nhưng đó là những chi tiết không quan trọng đối với sự hiểu biết bắt đầu của các chức năng bậc cao.


8
Điều này nhắc nhở tôi về một số câu trả lời khác ...
Bergi

7

Tôi đoán mỗi nhà cung cấp có nghĩa vụ phải thực hiện nó theo thông số kỹ thuật

Việc triển khai thực tế, ví dụ V8 có thể hơi phức tạp, hãy tham khảo câu trả lời này để bắt đầu. Bạn cũng có thể tham khảo nguồn v8 trong github nhưng có thể không dễ hiểu chỉ một phần trong sự cô lập.

Trích dẫn từ câu trả lời trên:

Nhà phát triển V8 tại đây. Chúng tôi có một số kỹ thuật triển khai khác nhau cho "nội dung": một số được viết bằng C ++, một số bằng Torque, một số trong cái mà chúng tôi gọi là CodeStubAssembler và một số trực tiếp trong phần lắp ráp. Trong các phiên bản trước của V8, một số đã được triển khai bằng JavaScript. Mỗi chiến lược này có những điểm mạnh riêng (giao dịch về độ phức tạp của mã, khả năng sửa lỗi, hiệu suất trong các tình huống khác nhau, kích thước nhị phân và mức tiêu thụ bộ nhớ); cộng với luôn có lý do lịch sử rằng mã đã phát triển theo thời gian.

Thông số kỹ thuật ES2015:

  1. Đặt O là ToObject ( giá trị này ).
  2. Trả về IfAbrupt ( O ).
  3. Đặt len là ToLdrops (Get ( O , "length")).
  4. Trả về IfAbrupt ( len ).
  5. Nếu IsCallable ( callbackfn ) sai , hãy ném ngoại lệ TypeError .
  6. Nếu thisArg được cung cấp, hãy để TthisArg ; khác để cho T được undefined .
  7. Đặt A là ArraySpeciesCreate ( O , len ).
  8. Trả về IfAbrupt ( A ).
  9. Đặt k là 0.
  10. Lặp lại, trong khi k < len
    1. Đặt LOL là ToString ( k ).
    2. Đặt kPftime là HasProperty ( O , Pk ).
    3. Return IfAbrupt ( kPftime ).
    4. Nếu kPftimeđúng , thì
      1. Đặt kValue là Get ( O , Pk ).
      2. Trả về IfAbrupt ( kValue ).
      3. Đặt mappedValue là Call ( callbackfn , T , « kValue , k , O »).
      4. Return IfAbrupt ( mappedValue ).
      5. Đặt trạng thái là CreateDataPropertyOrThrow ( A , Pk , mappedValue ).
      6. Return IfAbrupt ( trạng thái ).
    5. Tăng k thêm 1.
  11. Return Một .

2
Tôi tò mò, thông số kỹ thuật <li> list-style-typekhông thể sao chép trong Chrome cũng như FF. Bạn đã viết các số bằng tay, hoặc có một phương pháp tốt hơn tôi đang thiếu?
SurePerformance

5
@CertainPerformance lol. Sao chép HTML từ nguồn, HTML sang công cụ đánh dấu trực tuyến.
sabithpocker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.