豆皮粉儿们,又见面了,今天这一期,由字节跳动数据平台的「相逢在雨季」给大家讲一道面试题,关于由于ES6综合运用。

本文作者:相逢在雨季

在面试的过程中,经常能看到候选人写熟练掌握或者精通ES6,那就拿一道题试一试你的掌握情况吧,题目其实非常简单,如下所示。

// 有以下数据结构
const data = [{key: 'name',value: '豆皮范er'
}, {key: 'age',value: 1,
}, {key: 'from',value: '数据平台'
}]
// 实现一个转换函数 processFn
// 根据对应的key,value生成对象
// 要求尽可能的多用一些es6的新特性,尽可能的少去声明变量,减少副作用。
const processFn = data => processData
{name: '豆皮范er',age: 1,from: '数据平台'
}

好多候选人一看题目,思路一下就有了,啪一下就写出来了,很快啊。先看下实现的最多的版本

const processFn = data => {const processData = {};for (let i = 0; i < data.length; i++) {const key = data[i].key;const value = data[i].value;processData[key] = value;}return processData;
}

很标准的实现,不是吗,问这里面用到了哪些 ES6的特性,可以看出,主要用到了三个,一个是箭头函数 =>,一个是块级声明 let,一个是常量声明 const

这里可以在顺手问一个拓展的考点,如何实现一个真正的const,因为这里的const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动, 那如何实现一个真正只能只读的对象呢,下面给出答案。

const constantize = (obj) => {Object.freeze(obj);Object.keys(obj).forEach( (key, i) => {if ( typeof obj[key] === 'object' ) {constantize( obj[key] );}});
};

着手ES6的改造

继续上面的题,其实如果单独问 ES6有哪些新特性,很多人都能答出来很多,但是一旦运用到真正的代码编写中,就还是使用回老一套,其实就这道题而言比如 箭头函数解构赋值扩展运算符使用表达式作为对象的属性名, 等等这些 ES6的特性都能运用其中,下面就把这些特性一一代入到这个题当中,来体验一下综合运用 ES6的感觉吧。首先,先加上 解构赋值解构赋值可以很方便的从一个对象中取值,这里可以在取得数组中每一个对象的 keyvalue时运用上。

const processFn = data => {const processData = {};for (let i = 0; i < data.length; i++) {const { key, value } = data[i];processData[key] = value;}return processData;
}

在这里还可以顺带的把 for循环改成 for...of, for...of可以遍历一个迭代器( iterator), Array本质上就是一个迭代器,因为它实现了迭代器接口。

这里又可以拓展的去问一个问题,标准三连,什么是迭代器?javascript都有哪些迭代器?如何实现一个迭代器?这个大家下来后自行回答

还是先继续改造代码。把解构的过程放在for...of上,代码就变得更简洁了一些。

const processFn = data => {const processData = {};for (let { key, value } of data) {processData[key] = value;}return processData;
}

然后,可以加上 扩展运算符了,对于一个对象来说, 扩展运算符的作用是可以合并一个对象,在 ES6的时代,也可以使用 Object.assign。这两个方法其实都可以。但无论用哪个方法,都会遇到一个问题,属性是一个动态的变量,在 ES5的时代,想把属性作为变量进行对象赋值,只能使用以下方式

const keyName = 'name';
const obj = {}
obj[keyName] = 'xxxx';

ES6允许我们使用字面量的形式来完成这个事情,只需要给属性表达式加上一个 []即可,现在组合使用 扩展运算符对象属性表达式来优化一下代码吧。

const processFn = data => {const processData = {};for (let { key, value } of data) {Object.assign(processData, {[key] : value})}return processData;
}

或者

const processFn = data => {let processData = {};for (let { key, value } of data) {processData = {...processData, [key]: value}}return processData;
}

这样就成功的把这些 ES6的特性综合的运用上了,现阶段总结一下用到的 ES6特性吧, constlet箭头函数扩展运算符for...of, 解构赋值对象属性表达式。算下来有 个了。

减少一些副作用

不过这还没有结束,题目中还有一个要求,尽可能的少去声明变量,减少副作用。除了函数声明所必须的声明 const,剩下的还有两处显式声明,那最少可以把这种显式的声明减少到几个呢,答案实际上是 0个,这时就需要去改动 for循环了,因为 for循环是肯定会有显示的 const或者 let声明的, for循环本身就是命令式的编程方式,如果使用的是声明式的方式,那就可能会把显式声明变成参数的隐式声明,可以进一步提高代码的可读性和简洁性,这一点其实卡住了很多候选人。解决的思路其实可以转化为,如何把一个数组进行所谓的折叠( fold),就是把数组的多项合并成一项,这里其实涉及到的是一个 ES5的数组函数, reduce,众所周知,对 reduce的经典使用当然就是累加了。

[1,2,3].reduce((total, item) => total + item, 0)

其实以类比的思想,把对应的数字换成数组中的对象,把累加换成提取 keyvalue,进行合并,那数组的合并就是一种变相的累加了。有了 reduce,就可以更大的发挥 ES6的结合性了。

整合代码

const processFn = data => data.reduce((obj, {key, value}) => {return {...obj, [key]: value};
}, {})

最后的 return其实也可以去掉,让代码可以在一行的空间就可以实现了,在箭头函数返回对象的时候加一个括号即可。

const data => data.reduce((obj, {key, value}) => ({...obj, [key]: value}), {})

至此,我们对这个题的改造就结束了,综合使用了 ES6特性,以及减少了显式的声明。写出这样的代码,这道题的解答就可以毕业啦。

彩蛋时间

这就结束了吗,还没有,可以看出, ES6虽然很强大,但是要掌握它还是要学习各种特性,而且还要综合一些 ES5的特性结合在一起才能发挥出最好的功效,有没有本身就和谐统一的形式来做这个事情呢,其实是有的,坐稳了,我们要加速了。进入到声明式的世界,打开 函数式编程的大门吧。

说起函数式编程( FunctionalProgram),其实也是一项法则,入门的话,你们只需要记住下面几个公理和几个概念就可以了。类比小说《三体》的 黑暗森林法则就是这么解释的。

  • 函数是一等公民( functionfirst), FP的世界只有函数

  • 函数自身都有可组合的特性( composition),但函数本身是纯净( pure)的

想要继续了解函数式编程,还有两个很重要的概念,柯里化( curry)和 PointFree

针对 JS函数式编程有一个很重要的工具库,对,它不是 lodash而是 Ramda,使用 Ramda来做一下上面的题吧。

// 打开 http://ramda.cn/docs/ 在控制台粘贴下面代码
const data = [{key: 'name',value: '豆皮范er'
}, {key: 'age',value: 1,
}, {key: 'from',value: '数据平台'
}]
const processFn = R.reduce(R.useWith(R.merge, [R.identity,R.converge(R.objOf, [R.prop('key'),R.prop('value')])]), {})
console.log(processFn(data))

乍一看代码,我大意了啊,没看懂,就像面壁者罗辑的咒语一样晦涩难懂和不可理喻对吧,但在某种程度上,即使只从表面来看,它又充满了和谐简洁的美,拥有高度的秩序排列和统一性,而且完全符合上面的 两条公理两个重要概念,如果大家对什么是函数式编程,它主要有那些概念,具体的应用场景有哪些感兴趣的话,我会另写一篇详细的讲一讲 函数式编程。

福利时间

不识老尼,枉为前端攻城狮,其成名作《JS高级程序设计》曾名动江湖。深入理解ES6的特性对于所有JavaScript开发者而言至关重要,在可预见的未来,ES6中引入的语言特性会成为JavaScript应用程序的主流特性,这也是《深入理解ES6》的初衷。希望你通过阅读《深入理解ES6》可以了解ES6的新特性,并在需要时能够随时使用。

The  End

欢迎关注

扫描下方二维码,加”助理“好友,回复”前端“,进入“玄说-前端” 微信群,可以参加额外的群内红包抽奖赠书活动,与前端大咖一同讨论学习。

从一道面试题掌握ES6的综合运用(有彩蛋)相关推荐

  1. (转)从一道面试题彻底搞懂hashCode与equals的作用与区别及应当注意的细节

    背景:学习java的基础知识,每次回顾,总会有不同的认识.该文系转载 最近去面试了几家公司,被问到hashCode的作用,虽然回答出来了,但是自己还是对hashCode和equals的作用一知半解的, ...

  2. PHP递归创建多级目录(一道面试题的解题过程)

    今天看到一道面试题,要写出一个可以创建多级目录的函数: 我的第一个感觉就是用递归创建,具体思路如下: function Directory($dir){ if(is_dir($dir) || @mkd ...

  3. 从一道笔试题谈算法优化(上)

    因为受到经济危机的影响,我在 bokee.com 的博客可能随时出现无法访问的情况:因此将2005年到2006年间在 bokee.com 撰写的博客文章全部迁移到 csdn 博客中来,本文正是其中一篇 ...

  4. 从一道面试题谈谈一线大厂码农应该具备的基本能力

    作者:Yura Shevchenko 来源:skypixel.com 关于一线码农的面试,我想说 求职面试在绝大部分人来说都是必不可少的,自己作为求职者也参与了不少面试(无论成功或者失败),作为技术面 ...

  5. 有的线程它死了,于是它变成一道面试题

    来自:why不止技术 有些线程它活着,但它躺在池中碌碌无为: 有的线程它死了,于是它变成一道面试题. 这次的文章,要从一次阿里巴巴的面试说起. 我记得那天是周一,刚刚经历过周末过的放松,干劲十足的我正 ...

  6. 每日一道面试题(第7期)---Android补间动画与属性动画的区别

    零零碎碎的东西总是记不长久,仅仅学习别人的文章也只是他人咀嚼后留下的残渣.无意中发现了这个每日一道面试题,想了想如果只是简单地去思考,那么不仅会收效甚微,甚至难一点的题目自己可能都懒得去想,坚持不下来 ...

  7. 最近刷爆朋友圈的一道面试题

    前言: 最近在网上有一道面试题掀起了劲爆的浪潮,好多家公司都模仿提问了这么一道面试题,而且好多人也都在讨论这道面试题要是自己回答的话该怎么回答!这道题也是在个网站上刷爆了. 面试题 如果不用Sprin ...

  8. js经典试题之ES6

    js经典试题之ES6 1:在ECMAScript6 中,Promise的状态 答案:pending  resolved(fulfilled) rejected 解析: Promise对象只有三种状态: ...

  9. 从一道面试题,到“我可能看了假源码[2]

    上一篇从一道面试题,到"我可能看了假源码"中,由浅入深介绍了关于一篇经典面试题的解法. 最后在皆大欢喜的结尾中,突生变化,悬念又起.这一篇,就是为了解开这个悬念. 如果你还没有看过 ...

  10. 从一道面试题谈起,大厂到底看重程序员的什么能力?

    唐磊,他谦逊的自我介绍,是"在阿里云打工的清华学渣". 上周的一篇<字符串比较,居然暗藏玄机>,我最早是在唐磊<这10行比较字符串相等的代码给我整懵了>里看 ...

最新文章

  1. 深入理解Java Class文件格式
  2. Android 3.0 r1 API中文文档(113) ——SlidingDrawer
  3. 论记笔记的重要性:以三个电影为例
  4. 机器学习中用到的概率知识_机器学习中有关概率论知识的小结
  5. java并发AtomicIntegerArray
  6. igmp是哪个层协议_【干货】IGMPv1协议闲聊
  7. 一文读懂Xgboost
  8. 简单了解几种常见的网络通信协议
  9. 蛙跳算法优化VMD参数,惩罚系数,分解层数,matlab语言 ,最小包络熵为适应度函数。
  10. mysql查询去除重复记录
  11. EPUB文档格式简单总结
  12. OSChina 周四乱弹 —— 大光头与地中海并行,格子衫共沙滩裤一色
  13. xlsm java 读取_使用POI读/写XLSM
  14. 日系插画学习笔记(五):日系角色脸部画法-1头部
  15. Eclipse开发工具--使用JDT开发java程序
  16. 个人邮箱怎么注册,商业人士用哪个邮箱,邮箱使用全攻略!
  17. 什么是CPU?什么是计算机?
  18. P6578 魔法少女网站
  19. Bloom Filter 和 Count-Min Sketch 介绍
  20. 地下管线探测仪的原理与性能——TFN T-6000地下管线探测仪

热门文章

  1. 猫哥教你写爬虫 045--协程
  2. 短信网关在短信信息服务中的作用(转)
  3. 一个简单的订单生成器 ---- 20160920
  4. 大型医院叫号管理系统源码
  5. 解决Can not add resource (com.android.aaptcompiler.ParsedResource@a980fbb) to table
  6. Caffe2 - (二十四) Detectron 之 utils 函数(2)
  7. Beta冲刺第二周王者荣耀交流协会第五次会议
  8. CISCO路由器、交换机设备破解密码
  9. 【实战】疾病-基因与图神经网络和图自动编码器的相互作用
  10. The bean sellergoods.FeignClientSpecification could not be registered. A bean with that name has a