面试题之抽象组合函数🤔🤔

JS编程题

函数组合基础

首先,我们拥有了一个基本的字符串处理函数toUpperCase,用于将输入的字符串转换为大写形式。此外,还有一个字符串拼接函数hellow,它接受一个字符串参数并返回"Hello World!"加上该字符串的结果。

js 复制代码
var toUpperCase = function(x) {
    return x.toUpperCase();
}


var hellow = function(x) {
    return "Hello World!"+x;
}

简单组合

思考如何组合toUpperCasehellow实现greet函数,能将输入的字符大写并且拼接上"Hello World!",这一步是不难想到的。

js 复制代码
 var greet = function(x) {
 return hellow(toUpperCase(x));
}

如何又出现一个toLowerCase函数,有着将字符转为小写的功能,我们是不是要向下面这样再写一次?

js 复制代码
var toLowerCase = function(x) {
    return x.toLowerCase();
}

var greet2=function(x){
    return hellow(toLowerCase(x));
}

这样我们才能将新的功能耦合起来,思考思考是不是有些许麻烦,我们能不能做到封装一个函数,它能够 组合抽象函数 C=A(B(x)),有了思路,代码自然就形成了。

手写compose 组合函数

js 复制代码
var compose = function(f,g) {
    // 闭包
    return function(x) {
        return f(g(x));
    }
}

var greet = compose(hellow,toUpperCase);
console.log(greet('kevin'));

通过 compose 函数,你可以轻松地将多个函数组合成一个新的函数,并按照从右到左的顺序依次应用这些函数。这种方式不仅提高了代码的可读性和复用性,还使得复杂的操作可以通过简单的函数组合来实现。

完成这一步,你是不是觉得面试题已经解完了呢?但是,若你深入思考,我们只解决了,两个函数的组合,如果存在三个四个,乃至更多,我们该如何解决呢?

最终成品

js 复制代码
var compose = function() {
    var args = arguments; // 获取所有传入的函数
    var start = args.length - 1; // 最右边的函数索引,即最先执行的函数

    return function(x) { // 返回一个新函数,该函数接受一个参数 x
        var i = start;
        var result = args[start].call(this, x); // 先执行最右边的函数

        while (i--) { // 从右向左依次调用其他函数
            result = args[i].call(this, result); // 将上一个结果作为参数传递给下一个函数
        }

        return result; // 返回最终的结果
    }
}

var greet = compose(hellow, toUpperCase); // 组合 hellow 和 toUpperCase 函数
console.log(greet('kevin')); // 输出: Hello World!KEVIN
  1. 定义 compose 函数

    • compose 函数不直接接受两个函数作为参数,而是使用 arguments 对象来接收任意数量的函数。
    • args 变量保存了所有传入的函数。
    • start 变量表示最右边(即最先执行)的函数在 args 数组中的索引。
  2. 返回一个新的匿名函数

    • 这个匿名函数接受一个参数 x,它将作为第一个输入值传递给最右边的函数。
    • i = start 初始化循环变量 i,使其指向最右边的函数。
    • result = args[start].call(this, x) 首先调用最右边的函数,并将结果存储在 result 中。
  3. 循环调用其他函数

    • 使用 while (i--) 循环从右向左依次调用每个函数。
    • 在每次迭代中,当前的 result 作为参数传递给下一个函数(即左边的函数),并将新的结果重新赋值给 result
    • args[i].call(this, result) 确保每个函数都能正确访问当前的执行上下文(即 this 值)。

若不了解call 的用法可以看看除了 call,JS 还有哪些强大的函数绑定方式?探索 JavaScript 函数绑定的多样世界 在我深入研究 setT - 掘金

this 在此处的作用:

  • 如果这些函数是普通函数(即没有依赖于 this),那么 this 的值不会影响函数的行为。
  • 如果这些函数是对象的方法,并且它们内部依赖于 this,那么通过 call(this, ...) 可以确保 this 正确指向调用上下文中的对象。

前序遍历二叉树的又一写法

补充点与抽象组合函数无关的面试题,想要编写二叉树的前序遍历,你第一想到的肯定是递归,代码也很简洁:

js 复制代码
function preorderTraversal(root) {
     if(!root) return 
     console.log(root.val)
     preorderTraversal(root.left)
     preorderTraversal(root.right)
}

如果面试官,让你不能用递归,使用迭代的写法,你是否还会觉得简单呢? 想到迭代实现二叉树,能否想到一个数据结构,栈的用法,先进后出,来模拟二叉树的遍历

js 复制代码
function preOrderTraversal(root){

    if(!root) return 
    //  栈模拟递归
    var stack = []
    stack.push(root)
    while(stack.length){
        var node = stack.pop()
        console.log(node.val)
      
  // 注意:先压入右子节点,再压入左子节点,以保证左子节点先被处理
        if(node.right) stack.push(node.right)
        if(node.left) stack.push(node.left)
    }
}

重点:

看到该题首先你有没有想到使用栈去实现,其次是:根据栈的先进后出,有没有先压入右子树,再压入左子树,为关键点。

相关推荐
查理零世15 分钟前
【蓝桥杯集训·每日一题2025】 AcWing 6134. 哞叫时间II python
python·算法·蓝桥杯
仟濹15 分钟前
【二分搜索 C/C++】洛谷 P1873 EKO / 砍树
c语言·c++·算法
紫雾凌寒24 分钟前
解锁机器学习核心算法|神经网络:AI 领域的 “超级引擎”
人工智能·python·神经网络·算法·机器学习·卷积神经网络
乐多_L37 分钟前
使用vue3框架vue-next-admin导出表格excel(带图片)
前端·javascript·vue.js
京东零售技术1 小时前
AI Agent实战:打造京东广告主的超级助手 | 京东零售技术实践
算法
南望无一1 小时前
React Native 0.70.x如何从本地安卓源码(ReactAndroid)构建
前端·react native
Mike_188702783511 小时前
1688代采下单API接口使用指南:实现商品采集与自动化下单
前端·python·自动化
鲨鱼辣椒️面1 小时前
HTML视口动画
前端·html
一小路一1 小时前
Go Web 开发基础:从入门到实战
服务器·前端·后端·面试·golang
堇舟1 小时前
HTML第一节
前端·html