简体   繁体   English

像 .map() 这样的高阶函数如何在 JavaScript 内部工作?

[英]How do higher-order functions, like .map(), work internally in JavaScript?

Everyone nowadays tries to use these kind of higher-order functions to get promising result with writing less code.现在每个人都试图使用这些高阶函数来通过编写更少的代码来获得有希望的结果。 But I wonder how these functions works internally.但我想知道这些功能在内部是如何工作的。

Suppose if I write something like假设我写了类似的东西

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

I know that each element of 'number' array is iterating one by one, but how ?我知道 'number' 数组的每个元素都在一个一个地迭代,但是如何

I tried to search for it, but I didn't get any satisfactory answer yet.我试图搜索它,但我还没有得到任何满意的答案。

.map is just a method that accepts a callback, invokes the callback for every item of the array, and assigns the value to a new array. .map只是一个方法,它接受一个回调,为数组的每一项调用回调,并将值分配给一个新数组。 There's nothing very special about it.没有什么特别之处。 You can even implement it yourself quite easily:你甚至可以很容易地自己实现它:

 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]

To be fully spec-compliant, you'd also need to check, among other things, that the this is an object, that the callback is callable, and to .call the callback with the second parameter passed to myMap if there is one, but those are details not important to a beginning understanding of higher-order functions.为了完全规范兼容的,你还需要检查,除其他事项外, this是一个对象,该callback是可调用,并.call与传递给第二个参数回调myMap如果有,但这些细节对于开始理解高阶函数并不重要。

I guess every vendor is supposed to implement it as per the spec我想每个供应商都应该按照规范来实现它

The actual implementation, for example V8 can be a bit complex, refer this answer for a start.实际实现,例如 V8 可能有点复杂,请参考这个答案开始。 You can also refer v8 source in github but it may not be easy to understand only one part in isolation.也可以参考github中的v8源码,但是单独看一部分可能不太好理解。

Quoted from above answer:引自上面的回答:

V8 developer here. V8 开发人员在这里。 We have several different implementation techniques for "builtins": some are written in C++, some in Torque, some in what we call CodeStubAssembler, and a few directly in assembly.我们有几种不同的“内置”实现技术:有些是用 C++ 编写的,有些是用 Torque 编写的,有些是我们称之为 CodeStubAssembler 的,还有一些是直接用汇编编写的。 In earlier versions of V8, some were implemented in JavaScript.在 V8 的早期版本中,有些是用 JavaScript 实现的。 Each of these strategies has its own strengths (trading off code complexity, debuggability, performance in various situations, binary size, and memory consumption);这些策略中的每一个都有自己的优势(权衡代码复杂性、可调试性、各种情况下的性能、二进制大小和内存消耗); plus there is always the historical reason that code has evolved over time.此外,代码随着时间的推移而发展总是有历史原因的。

ES2015 spec: ES2015 规范:

  1. Let O be ToObject( this value).O成为 ToObject(这个值)。
  2. ReturnIfAbrupt( O ). ReturnIfAbrupt( O )。
  3. Let len be ToLength(Get( O , "length" )).len为 ToLength(Get( O , "length" ))。
  4. ReturnIfAbrupt( len ). ReturnIfAbrupt( len )。
  5. If IsCallable( callbackfn ) is false , throw a TypeError exception.如果 IsCallable( callbackfn ) 为false ,则抛出TypeError异常。
  6. If thisArg was supplied, let T be thisArg ;如果提供了thisArg ,则设TthisArg else let T be undefined .否则让Tundefined
  7. Let A be ArraySpeciesCreate( O , len ).A为 ArraySpeciesCreate( O , len )。
  8. ReturnIfAbrupt( A ). ReturnIfAbrupt( A )。
  9. Let k be 0.k为 0。
  10. Repeat, while k < len重复,而k < len
    1. Let Pk be ToString( k ).Pk为 ToString( k )。
    2. Let kPresent be HasProperty( O , Pk ).kPresentHasProperty ( O , Pk )。
    3. ReturnIfAbrupt( kPresent ). ReturnIfAbrupt( kPresent )。
    4. If kPresent is true , then如果kPresenttrue ,则
      1. Let kValue be Get( O , Pk ).kValue为 Get( O , Pk )。
      2. ReturnIfAbrupt( kValue ). ReturnIfAbrupt( kValue )。
      3. Let mappedValue be Call( callbackfn , T , « kValue , k , O »).映射值是调用(回调函数T ,« kValue , k , O »)。
      4. ReturnIfAbrupt( mappedValue ). ReturnIfAbrupt( mappedValue )。
      5. Let status be CreateDataPropertyOrThrow ( A , Pk , mappedValue ).status为 CreateDataPropertyOrThrow ( A , Pk , mapsValue )。
      6. ReturnIfAbrupt( status ). ReturnIfAbrupt(状态)。
    5. Increase k by 1.k增加 1。
  11. Return A .返回A

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM