高阶函数

132 阅读1分钟

如果一个函数接受另一个函数作为参数,那么我们称该函数为高阶函数

部分javascript的高阶函数

forEach和Map

let arr = [1, 2, 3];
Array.prototype.myForEach = function (callback) {
    let len = this.length;
    // 做一个健壮性的判断
    if (typeof callback !== 'function') {
        throw new Error('must be function');
    }
    for (let i = 0; i < len; i ++) {
        callback.call(this, this[i], i);
    }
}

Array.prototype.myMap = function (callback) {
    let len = this.length;
    let arr = [];
    // 做一个健壮性的判断
    if (typeof callback !== 'function') {
        throw new Error('must be function');
    }
    for (let i = 0; i < len; i ++) {
        arr.push(callback.call(this, this[i], i));
    }
    return arr;
}

reduce

reduce 方法使用场景

// 1. 累加
arr.reduce((pre, cur, index, arr) => {
    return pre + cur;
}, 10);

// 2. 改写对象数组
let routes = [
    {
        path: "/",
        components: "hello"
    },
    {
        path: "/test",
        components: "test"
    }
];
routes.reduce((pre, cur) => {
    pre[cur.path] = cur.components;
    return pre;
}, {});

// 3. 对象数组部分属性相加
let arr = [
    {
        type: "all",
        num: 1
    },
    {
        type: "no",
        num: 2
    },
    {
        type: "all",
        num: 3
    },
];
arr.reduce((pre, curr) => {
    if (curr.type === "all") {
        pre += curr.num;
    }
    return pre;
}, 0);

手写reduce方法

// 手写reduce方法
Array.prototype.myReduce = function (fn, init) {
    let i = 0;
    let len = this.length;
    let pre = init;
    if (init === undefined) {
        pre = this[0];
        i = 1;
    }
    for (i; i < len; i ++) {
        pre = fn.call(this, pre, this[i], i, this);
    }
    return pre;
}

filter

过滤

// 过滤返回为true的内容,以数组形式返回
let arr = [1, 2, 3, 4, 5, 6];
arr.filter((curr, index) => {
    return curr % 2 === 0;
});

手写filter函数

Array.prototype.myFilter = function(fn) {
    let _newArray = [];
    let len = this.length;
    for (let i = 0; i < len; i ++) {
        if (fn.call(this, this[i], i)) {
            // 如果值是对象,要解除与原对象的引用,克隆一个新的出来
            // 不是就直接加进去
            if (typeof this[i] === 'object') {
                _newArray.push(Object.create(this[i]));
            } else {
                _newArray.push(this[i]);
            }
        }
    }
    return _newArray;
}

手写自己的高阶函数

编写高阶函数要注意的点

  • 保持纯函数和减少函数副作用

  • 调用选择call还是apply

    当给回调函数的参数是指定数量的时候,选择call,不确定有多少个参数时选用apply,将arguments数组给它

call, apply, bind用法及对比

编写自己的高阶函数

  • 找出对象中符合要求的属性名
let obj = {
    num1: 1,
    num2: 2,
    num3: 3,
    num4: 4,
    num5: 5,
    num6: 6
};
// 筛选出对象中值能被二整除的属性名,接收两个参数,一个对象,一个对象的回调
function findProperty(obj, fn) {
    let _obj = Object.create(obj);
    let _propertyArr = [];
    for (let item in _obj) {
        // 这个方法的this指向window,看调用这个函数的方法,this指向哪里比较方便
        // 筛选出执行结果为true的
        if (fn.call(_obj, _obj[item], item)) {
            _propertyArr.push(item);
        }
    }
    return _propertyArr;
}

findProperty(obj, (value, name) => {
    return value % 2 === 0;
});