fezaoduke / fe-practice-hard

晚练课
69 stars 6 forks source link

第 42 期(算法-搜索):获取多层嵌套对象的目标属性值 #45

Open wingmeng opened 5 years ago

wingmeng commented 5 years ago

题目:

已知后端某接口可能返回的数据结构如下:

// 正常情况:
{
  "status": 200,
  "msg": "ok",
  "response": {
    "data": {
      "total": 2,
      "pageSize": 10,
      "lists": [
        { "id": 1, "name": "hello" },
        { "id": 2, "name": "world" }
      ]
    },
    "keyword": "hello world"
  }
}

// 请求异常:
{
  "status": 400,
  "msg": "bad request",
  "response": null
}

// 空数据:
{
  "status": 200,
  "msg": "ok",
  "response": {
    "data": {
      "total": 0,
      "pageSize": 10,
      "lists": null
    },
    "keyword": "hack"
  }
}

前端需要获取返回数据中的 response.data.lists 来渲染业务页面(伪代码如下),请编写一个通用函数来改善逐级判断属性值的问题。

axios.get('/list?keyword=xxx')
  .then(function(res) {
    // 为了防止报错,而不得不逐级判断属性值的有效性
    if (res.response && res.response.data && res.response.data.lists) {
      render(res.response.data.lists);
    }
  });
/**
 * @param {object | array} data - 源数据
 * @param {string} fieldRoute - 字段名路径,如 a.b.c 
 */
function getDataBy(data, fieldRoute) {
  // 你的代码
}

测试数据:

// 正常情况:
getDataBy(res, 'response.data.lists');  // [{"id": 1, "name": "hello"}, {"id": 2, "name": "world"}]

// 请求异常:
getDataBy(res, 'response.data.lists');  // null

// 空数据:
getDataBy(res, 'response.data.lists');  // null

getDataBy(null, 'response.data.lists');  // null
getDataBy([{id: 1}, {id: 2}, {id: 3}, {id: 4}], 1);  // {id: 2}

参考答案:

function getDataBy(data, fieldRoute) {
  if (fieldRoute == undefined) {  // undefined | null
    return data
  }

  var fields = String(fieldRoute).split('.');

  return fields.reduce(function(obj, field) {
    if (obj) {
      return obj[field]
    } else {
      return null
    }
  }, data);
}