美文网首页
Javascript Array 的 map 与 forEach

Javascript Array 的 map 与 forEach

作者: 尤小小 | 来源:发表于2019-03-02 21:35 被阅读0次

    map 方法和 forEach 方法是数组的两个常用方法;都是对数组的所有元素进行callback处理; map会返回一个新数组, 但是forEach 的返回值是undefined。

    map的语法是:

    var new_array = arr.map(function callback(currentValue[, index[, array]]) {
     // Return element for new_array }[, 
    thisArg])
    

    forEach的语法是:

    arr.forEach(callback[, thisArg]);
    

    map的实现

    Array.prototype.myMap = function (callback, thisArg) {
    
        // thisArg 执行函数时使用的的this
    
        // 3.如果callback不是函数,则抛出TypeError异常.
        if (Object.prototype.toString.call(callback) != "[object Function]") { // typeof callback == function 
            throw new TypeError(callback + " is not a function");
        }
    
        if (this == null) {
            throw new TypeError(" this is null or not defined");
        }
    
        // 1. 将O赋值为调用map方法的数组.
        var O = Object(this);
    
        // 2.将len赋值为数组O的长度.
        var len = O.length >>> 0;
    
    
        // 4. 如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined.
        var T 
        if (thisArg) {
            T = thisArg; // 执行callback函数时使用的this值
        }
    
        // 5. 创建新数组A,长度为原数组O长度len
        var A = new Array(len);
    
        // 6. 将k赋值为0
        var k = 0;
    
        // 7. 当 k < len 时,执行循环. 尽量不用for循环
        while (k < len) {
    
            var kValue, mappedValue;
    
            //遍历O,k为原数组索引
            if (k in O) {
    
                //kValue为索引k对应的值.
                kValue = O[k];
    
                // 执行callback,this指向T,参数有三个.分别是kValue:值,k:索引,O:原数组.
                mappedValue = callback.call(T, kValue, k, O);
    
                // 返回值添加到新数组A中.
                A[k] = mappedValue;
            }
            // k自增1
            k++;
        }
    
        // 8. 返回新数组A
        return A;
    };   
    
    

    myMap的测试用例

    var array1 = [1, 4, 9, 16];
    
    // pass a function to map
    const map1 = array1.myMap(x => x * 2);
    
    console.log(map1);
    // expected output: Array [2, 8, 18, 32]
    

    forEach的实现

    Array.prototype.myForEach = function (callback, thisArg) {
    
        var T, k;
    
        if (this == null) {
            throw new TypeError(' this is null or not defined');
        }
    
        // 如果callback 不是函数 抛出异常
        if (typeof callback !== "function") {
            throw new TypeError(callback + ' is not a function');
        }
    
        // 1. Let O be the result of calling toObject() passing the
        // |this| value as the argument.
        var O = Object(this);
    
        // 2. Let lenValue be the result of calling the Get() internal
        // method of O with the argument "length".
        // 3. Let len be toUint32(lenValue).
        var len = O.length >>> 0;
    
        // 4. If isCallable(callback) is false, throw a TypeError exception. 
        // See: http://es5.github.com/#x9.11
        
    
        // 5. If thisArg was supplied, let T be thisArg; else let
        // T be undefined.
        //  既可以 thisArg存在就赋值 或者arguments.length > 1 或者 arguments.length >= 2
        if (arguments.length > 1) { 
            T = thisArg;
        }
    
        // 6. Let k be 0
        k = 0;
    
        // 7. Repeat, while k < len
        while (k < len) {
    
            var kValue;
    
            // a. Let Pk be ToString(k).
            //    This is implicit for LHS operands of the in operator
            // b. Let kPresent be the result of calling the HasProperty
            //    internal method of O with argument Pk.
            //    This step can be combined with c
            // c. If kPresent is true, then
            if (k in O) {
    
                // i. Let kValue be the result of calling the Get internal
                // method of O with argument Pk.
                kValue = O[k];
    
                // ii. Call the Call internal method of callback with T as
                // the this value and argument list containing kValue, k, and O.
                callback.call(T, kValue, k, O);
            }
            // d. Increase k by 1.
            k++;
        }
        // 8. return undefined
    };
    
    if (!Array.prototype.reduce) {
        Object.defineProperty(Array.prototype, 'reduce', {
            value: function (callback /*, initialValue*/) {
                if (this === null) {
                    throw new TypeError('Array.prototype.reduce ' +
                        'called on null or undefined');
                }
                if (typeof callback !== 'function') {
                    throw new TypeError(callback +
                        ' is not a function');
                }
    
                // 1. Let O be ? ToObject(this value).
                var o = Object(this);
    
                // 2. Let len be ? ToLength(? Get(O, "length")).
                var len = o.length >>> 0;
    
                // Steps 3, 4, 5, 6, 7      
                var k = 0;
                var value;
    
                if (arguments.length >= 2) {
                    value = arguments[1];
                } else {
                    while (k < len && !(k in o)) {
                        k++;
                    }
    
                    // 3. If len is 0 and initialValue is not present,
                    //    throw a TypeError exception.
                    if (k >= len) {
                        throw new TypeError('Reduce of empty array ' +
                            'with no initial value');
                    }
                    value = o[k++];
                }
    
                // 8. Repeat, while k < len
                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 accumulator be ? Call(
                    //          callbackfn, undefined,
                    //          « accumulator, kValue, k, O »).
                    if (k in o) {
                        value = callback(value, o[k], k, o);
                    }
    
                    // d. Increase k by 1.      
                    k++;
                }
    
                // 9. Return accumulator.
                return value;
            }
        });
    }
    

    myForEach的测试用例:

    var array1 = ['a', 'b', 'c'];
    
    array1.myForEach(function(element) {
      console.log(element);
    });
    
    // expected output: "a"
    // expected output: "b"
    // expected output: "c"
    

    相关文章

      网友评论

          本文标题:Javascript Array 的 map 与 forEach

          本文链接:https://www.haomeiwen.com/subject/ysgyuqtx.html