前端面试题一

132 阅读2分钟

记一道面试题

题目如下:

var foo=function (){…}
foo(1)(2)(3).getVal();//返回6
foo(1,2,3).getVal();//返回6
foo(1,8)(2).getVal();//返回11

实现思路:

  1. 每次函数执行都返回一个函数可以再次执行。
  2. 每次执行的参数都会存到内存中等待getVal方法的执行。
  3. 这个函数拥有一个getVal的内置方法。

第一步实现"每次函数执行都返回一个函数可以再次执行":

var foo = function () {
  function fn() {
    return foo();
  }
  return fn;
};

现在拿到题目中的参数测试:
foo(1)(2)(3)
foo(1,2,3)
foo(1,8)(2)
发现函数执行结果都会返回一个函数,如下图:

image.png

第二步实现"每次执行的参数都会存到内存中等待getVal方法的执行",其实就是在函数体内保存函数参数,以备getVal方式求取总数时使用:

var foo = function (...args) {
  function fn() {
    let arg = Array.from(arguments);//把fn函数的参数arguments由类数组改为数组
    args = args.concat(arg);// 在这里缓存所有函数中的参数,确保参数没有遗漏
    console.log(args);
    return foo(...args);
  }
  return fn;
};

现在拿到题目中的参数测试:
foo(1)(2)(3)
发现函数无论执行多少次,都在内部保存了对应的参数,如下图:

image.png

第三步实现"这个函数拥有一个getVal的内置方法",函数其实也是一个对象可以给它添加方法:

var foo = function (...args) {
  function fn() {
    let arg1 = Array.from(arguments);
    arg1 = arg1.concat(args);
    return foo(...arg1);
  }
  fn.getVal = function () {
    return args.reduce((pre, next) => {
      return pre + next;
    }, 0);
  };
  return fn;
};

现在拿到题目中的参数测试:
foo(1)(2)(3).getVal()
foo(1,2,3).getVal()
foo(1,8)(2).getVal()
执行结果如下图:

image.png

相关思考

在实际开发过程中树状结构数据根据唯一value查找数据并返回对应的层级链,现在我们有如下数据结构,根据value为1.1.1.1返回从它的父级到它本身层级的名称“选项一/子选项一/子子选项一/子子子选项一”这样的结构:

let treeData = [
  {
    label: "选项一",
    value: "1",
    children: [
      {
        label: "子选项一",
        value: "1.1",
        children: [
          {
            label: "子子选项一",
            value: "1.1.1",
            children: [
              {
                label: "子子子选项一",
                value: "1.1.1.1",
              },
            ],
          },
        ],
      },
      {
        label: "子选项二",
        value: "1.2",
        children: [
          {
            label: "子子选项一",
            value: "1.2.1",
          },
        ],
      },
      {
        label: "子选项三",
        value: "1.3",
      },
    ],
  },
  {
    label: "选项二",
    value: "2",
    children: [
      {
        label: "子选项一",
        value: "2.1",
      },
      {
        label: "子选项二",
        value: "2.2",
      },
    ],
  },
];

实现思路:

1.同样需要闭包实现,找到匹配的value值的时候开始从最后一层return,然后不断把数据放在数组中最后返回。

function getNodePathByValue(treeData, value) {
   
  function traverse(treeData, value) {
   for(let i=0,z=treeData.length;i<z;i++){
     let item = treeData[i]; 
     if(item.value===value){
       return [item];// 这里返回数组
     }
     if(item.children){
       let result = traverse(item.children, value); 
       if(result){
         return [item, ...result];
       }
     }
   }
  }
  let pathItem=traverse(treeData, value)
  return pathItem;
}

测试代码如下:

let list=getNodePathByValue(treeData, "1.1.1.1"); 
let labels=list.map((item)=>{
return item.label
})
console.log('当前label层级',labels);// 输出为:['选项一', '子选项一', '子子选项一', '子子子选项一']