zoukankan      html  css  js  c++  java
  • Array方法实现(forEach, map, filter, some, every, indexOf, lastIndexOf, reduce)

    forEach

    const root = this;
    
    Array.prototype.myForEach = function(fn, context) {
        // 可选参数, 设置回调中的this指向
        context = context || root;
    
        if (typeof fn !== 'function') throw new TypeError('A function is expected on parameter 1');
    
        for (let i = 0, len = this.length; i < len; i++) {
            // 不对不存在或已经删除的属性(索引)执行函数 
            if (Object.prototype.hasOwnProperty.call(this, i)) {
                fn.call(context, this[i], i, this);
            }
        }
    }
    
    const names = ['Wango', 'Lily', 'Peter'];
    names.myForEach((val, idx, all) => {
        console.log(idx, val, all);
    });
    
    // 0 Wango [ 'Wango', 'Lily', 'Peter'  ]
    // 1 Lily [ 'Wango', 'Lily', 'Peter'  ]
    // 2 Peter [ 'Wango', 'Lily', 'Peter'  ]
    
    delete names[2];
    console.log(names.length);
    // 3
    
    names.myForEach((val, idx, all) => {
        console.log(idx, val, all);
    });
    // 0 Wango [ 'Wango', 'Lily', <1 empty item>  ]
    // 1 Lily [ 'Wango', 'Lily', <1 empty item> ]
    

    map

    Array.prototype.myMap = function(fn, context) {
        if (typeof fn !== 'function') throw new TypeError('A function is expected on parameter 1');
        
        const result = Array(this.length);
        // 类型判断, context默认值等交由forEach循环处理,
        // map只需要保存结果并返回
        this.forEach(function(val, idx, all) {
            result[idx] = fn.call(this, val, idx, all);
        }, context);
    
        return result;
    }
    
    const nums1 = [1, 2, 3, 4];
    
    const nums2 = nums1.myMap((val, idx, all) => {
        return val * val;
    });
    
    console.log(nums1);
    // [ 1, 2, 3, 4  ]
    console.log(nums2);
    // [ 1, 4, 9, 16  ]
    

    filter

    Array.prototype.myFilter = function(fn, context) {
        if (typeof fn !== 'function') throw new TypeError('A function is expected on parameter 1');
    
        const result = [];
        this.forEach(function(val, idx, all) {
            // 将满足条件的结果加入新数组
            fn.call(this, val, idx, all) && result.push(val);
        }, context);
    
        return result;
    }
    
    const num1 = [1, 5, 3, 6, 7, 2, 3, 6, 9, 0];
    const num2 = num1.myFilter(val => val > 5);
    
    console.log(num1);
    // [1, 5, 3, 6, 7, 2, 3, 6, 9, 0]
    console.log(num2);
    // [ 6, 7, 6, 9  ]
    

    some

    const root = this;
    
    Array.prototype.mySome = function(fn, context) {
        if (typeof fn !== 'function') throw new TypeError('A function is expected on parameter 1');
        
        context = context || root;
        // forEach无法正常中断循环, 使用for代替
        // 只要有一个满足条件即可返回true不需要全部遍历
        for (let i = 0, len = this.length; i < len; i++) {
            if (fn.call(context, this[i], i, this)) return true;
        }
        return false;
    }
    
    const nums1 = [1, -3, 2, 3, 4, -1];
    console.log(nums1.mySome(val => val < 0));
    // true
    console.log(nums1.mySome(val => val === undefined));
    // false
    
    delete nums1[1];
    console.log(nums1);
    // [ 1, <1 empty item>, 2, 3, 4, -1  ]
    
    console.log(nums1.mySome(val => val === undefined));
    // true
    

    every

    const root = this;
    
    Array.prototype.myEveny = function(fn, context) {
        if (typeof fn !== 'function') throw new TypeError('A function is expected on parameter 1');
    
        context = context || root;
        // forEach无法正常中断循环, 使用for代替
        // 只要有一个不满足条件即可返回false不需要全部遍历
        for (let i = 0, len = this.length; i < len; i++) {
            if (!fn.call(context, this[i], i, this)) return false;
        }
        return true;
    }
    
    const nums1 = [2, -1, 3, 5, 1, 0];
    console.log(nums1.myEveny(val => typeof val === 'number'));
    // true
    

    indexOf

    Array.prototype.myIndexOf = function(val, fromIndex) {
        // 只要是数字或者可以被自动转换为数字即为有效
        // 否则使用默认起始点0
        fromIndex = fromIndex * 1 || 0;
        // 索引从小到大顺序查找, 返回第一个查找到的索引
        for (let i = fromIndex, len = this.length; i < len; i++) {
            if (this[i] === val) return i;
        }
        return -1;
    }
    
    const names = ['Wango', 'Lily', 'Lily', 'Peter'];
    console.log(names.myIndexOf('Lily'));
    // 1
    console.log(names.myIndexOf('Anna'));
    // -1
    console.log(names.myIndexOf('Lily', 1));
    // 1
    console.log(names.myIndexOf('Lily', 2));
    // 2
    console.log(names.myIndexOf('Lily', '2'));
    // 2
    console.log(names.myIndexOf('Lily', -1));
    // 1
    

    lastIndexOf

    Array.prototype.myLastIndexOf = function(val, fromIndex) {
    	const len = this.length;
    	// 起始点为数组长度减一
        fromIndex = fromIndex * 1 || len - 1;
    	// 从大到小逆序查找,返回查找到的第一个元素的索引
        for (let i = fromIndex; i > 0; i--) {
            if (this[i] === val) return i;
        }
        return -1;
    }
    
    const names = ['Wango', 'Lily', 'Lily', 'Peter'];
    console.log(names.myLastIndexOf('Lily'));
    // 2
    console.log(names.myLastIndexOf('Anna'));
    // -1
    console.log(names.myLastIndexOf('Lily', 1));
    // 1
    console.log(names.myLastIndexOf('Lily', 2));
    // 2
    console.log(names.myLastIndexOf('Lily``', '2'));
    // 2
    console.log(names.myLastIndexOf('Lily', -1));
    // 1
    

    reduce

    Array.prototype.myReduce = function(fn, initVal) {
    
        if (typeof fn !== 'function') throw new TypeError('A function is expected on parameter 1');
        // 若initVal不是或不能自动转换为数字
        // 则初始值为第一个元素
        let pre = +initVal || this[0];
        // 有初始值时当前值从0开始
        // 没有初始值时当前值从1开始(0被上面pre拿走了)
        for (let i = +initVal ? -1 : 0, len = this.length; i < len; i++) {
            // 当下一个值不存在即数组循环完毕后, 返回累计结果
            if (!this[i + 1]) {
                return pre;
            }
            pre = fn.call(this, pre, this[i + 1], i, this);
        }
    }
    
    const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    
    console.log(nums.myReduce((a, b) => a + b));
    // 45
    console.log(nums.myReduce((a, b) => a + b, 10));
    // 55
    console.log(nums.myReduce((a, b) => a + b, 'aa'));
    // 45
    console.log(nums.myReduce((a, b) => a + b, '10'));
    // 55
    console.log([[1, 2, 3], [4, 5, 6]].myReduce((a, b) => a.concat(b)));
    // [ 1, 2, 3, 4, 5, 6 ]
    

    参考网址:ES5中新增的Array方法详细说明

  • 相关阅读:
    [十二省联考2019]字符串问题:后缀数组+主席树优化建图
    HAOI2018简要题解
    使用单调队列维护决策三元组实现决策单调性优化DP的一些细节
    杜教筛&min_25筛复习
    分治NTT:我 卷 我 自 己
    高级(并不)多项式算法总结
    导数与微分简单总结(updated)
    退役前的做题记录
    USACO2018DEC PLATINUM
    USACO2018DEC GOLD
  • 原文地址:https://www.cnblogs.com/hycstar/p/14367961.html
Copyright © 2011-2022 走看看