# 此页面贡献者:年轻的小铲、树

简单实现

function map (arr, func) {
  var result = []
  for(var i = 0, l = arr.length; i<l; i++) {
    result[i] = func(arr[i], i, arr)
  }
  return result
}

jQuery 实现

// 以下map函数中使用了jQuery其他方法的地方 这里做了修改(为了减少篇幅)
// 不影响原意和map的理解 可以直接在控制台跑
// arg is for internal usage only
function map ( elems, callback, arg ) {
  var value,
    length = elems.length,
    i = 0,
    ret = [],
    MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;

  // 如果是(类)数组:遍历数组,将每个项目转换为新值
  if ( typeof length == 'number' && length >= 0 && length % 1 == 0 && length <= MAX_ARRAY_INDEX ) {
    for ( ; i < length; i++ ) {
      value = callback( elems[ i ], i, arg );

      if ( value != null ) {
        ret.push( value );
      }
    }

  // 遍历对象上的可枚举属性
  } else {
    for ( i in elems ) {
      value = callback( elems[ i ], i, arg );

      if ( value != null ) {
        ret.push( value );
      }
    }
  }

  // 拍平嵌套数组
  return [].concat.apply( [], ret );
}

underscore 实现

// 通过对list里的每个元素调用转换函数(iteratee迭代器)生成一个与之相对应的数组。
// iteratee传递三个参数:value,index(如果list是个JavaScript对象是,则该参数为key),list
_.map = _.collect = function(obj, iteratee, context) {

  // iteratee参数可能是函数 || 对象 || 字符串,underscore 的内置函数 cb 将其统一处理为一个函数。
  // cb详细解析可以看 https://github.com/Akiq2016/underscore/blob/master/underscore.js#L91
  iteratee = cb(iteratee, context);

  // 表示给定对象的所有可枚举属性的字符串数组。 [ isArrayLike判断是否(类)数组,_.keys实现Object.keys ]
  var keys = !isArrayLike(obj) && _.keys(obj),
      length = (keys || obj).length,
      results = Array(length);

  // 遍历数组 || 遍历对象上的可枚举属性, 将每个项目转换为新值
  for (var index = 0; index < length; index++) {
    var currentKey = keys ? keys[index] : index;
    results[index] = iteratee(obj[currentKey], currentKey, obj);
  }

  return results;
};

ECMA 262 规范

1. Let O be ? ToObject(this value).
2. Let len be ? ToLength(? Get(O, "length")).
3. If IsCallable(callbackfn) is false, throw a TypeError exception.
4. If thisArg was supplied, let T be thisArg; else let T be undeᲪined.
5. Let A be ? ArraySpeciesCreate(O, len).
6. Let k be 0.
7. Repeat, while k < len
  a. Let Pk be ! ToString(k).
  b. Let kPresent be ? HasProperty(O, Pk).
  c. If kPresent is true, then
    i. Let kValue be ? Get(O, Pk).
    ii. Let mappedValue be ? Call(callbackfn, T, « kValue, k, O »).
    iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
  d. Increase k by 1.
8. Return A.

NOTE 2

The map function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method.
上次更新: 7/29/2018, 12:21:27 PM