1、请实现一个 find 函数,功能等同于 document.getElementById


解析: 难点在于如何获取入口节点。 假如你知道入口节点,例如root节点,那递归就行了。

考察点: 因为平常绝大多数前端童鞋不是用React就是用Vue。 很少有人能对DOM的一些原生操作做到熟悉

// 方法1,手动写递归。
const nodes = document.body; // 万物起点,获取 body DOM

function getId(node,nodeIdMap){
    if(node){ 
        if(node.id) nodeIdMap[node.id] = node; // 如果 id 属性存在,则把该DOM存入 Map
        const children = node.children;
        for(let i = 0 ; i < children.length; i++){ // 循环
            getId(children[i],nodeIdMap) // + 递归
        }
    }
    return nodeIdMap
}

const ids = getId(nodes,{})

const findId = (id) => ids[id]
// 大家可以拿这段代码试一下。
// 方法2, 借助 document.createNodeIterator 可以去MDN上查看该API
const f =  (id)=> document.createNodeIterator(
    document.body,
    NodeFilter.SHOW_ALL,
    {
      acceptNode(node) {
        return node.id === id? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
      }
    }
);

f('anyId').nextNode(); // 即可获取 任意ID 的DOM

2、实现 一个 find

测试数据为:

var data = [
    {title: 't1', userId: '10086', name: 'Jay'},
    {title: 't2', userId: '10087', name: 'Tom1'},
    {title: 't3', userId: '10088', name: 'Tina2'},
]
复制代码

希望如此调用:

find(data).where({
name: /\d$/,
}).orderBy('userId','desc');
复制代码

得到结果是:

[
    {title: 't3', userId: '10088', name: 'Tina2'},
    {title: 't2', userId: '10087', name: 'Tom1'}
]
复制代码

考察点: 这其实是一条sql语句。 就像 select title, userId,name from 表名 where 条件 order by userId desc

分析: 咋看上去有点像链式调用? 但这是坑,面试官绝对不是想让你写个链式调用。(因为我就是这么干的,然后被怼了。)

// 先写个类

class FindData {

  constructor(data) {
    this.data = data;
  }

  where(regs) {
    const keys = Object.keys(regs);
    const d = this.data.filter((item) => {
      let r = true;
      for (let i = 0; i < keys.length; i++) {
        const current = item[keys[i]];
        if (!(current && regs[keys[i]].test(current))) {
          r = false;
        }
      }
      return r;
    })
    return new FindData(d);
  }

  orderBy(name, sort) {
    let fn;
    if(sort === 'desc'){
      fn = (a,b)=> b[name] - a[name]
    }else if(sort === 'asc'){
      fn = (a,b)=> a[name] - b[name]
    }
    return this.data.sort(fn)
  }
}

var find = (d) =>  new FindData(d);

find(data).where({name: /\d$/}).orderBy('userId','desc');
复制代码

 

3、将字符串转成千分位。例如 '12345678' 转化成千分位是 '12,345,678'.

考察点: 正则。 如果你写的不是正则,那也一定会让你用正则写。零宽断言了解一下

// 零宽断言
str.replace(/\d{1,3}(?=(\d{3})+$)/g,function(s){
    return s + ','
})