环境:阿里的在线编程系统容许面试官在线考察面试者的编程能力.javascript
考点:编程和理论.java
编程:分为技术自驱力、异步操做、编程风格(颗粒小)、变量做用域、DOM操做等.es6
理论:性能优化,浏览器运行机制,协议/标准等web
本文侧重于编程,在编程中对函数的运用是写好程序的基础。(参考开发者技能修炼的五个等级中“第二阶梯:Developer,开发工程师”“知道了变量、逻辑与函数的意义”)面试
如何写一个信号灯?(参考一道关于Promise应用的面试题)编程
那么如何写好一个信号灯?segmentfault
咱们首先发散一下思惟:promise,yield,async/await(ES7)。好的,技术点有了,那接下来该选择哪一个方式呢?设计模式
不妨就选择Promise,和其余方式作个对比。数组
唉,一上来就看到async/await是ES7的特性,新生代的佼佼者,Promise已无用武之地?(参考Async/Await替代Promise的6个理由)promise
那咱们仍是先来看看有没有挽回余地(对promise多少有些感情了)?
2.错误处理
文中错误处理一点说到“Async/Await让try/catch能够同时处理同步和异步错误。在下面的promise示例中,try/catch不能处理JSON.parse的错误,由于它在Promise中。咱们须要使用.catch,这样错误处理代码很是冗余。而且,在咱们的实际生产代码会更加复杂。”
咱们想一想问题根源应该是每步都须要catch
,那将then中的函数统一放入数组,而后递归运行能够解决这个问题。(另外,参考Toxicity:这些关键字有毒里面有说到eval with try/catch
对性能有必定的影响)
3.条件语句
文中说到“须要获取数据,而后根据返回数据决定是直接返回,仍是继续获取更多的数据。”
咱们能够适当经过reject('')解决的,记得最后必定要有一个catch((err) => console.log(''))。等等那是和上面冲突了(每步catch)。这样使用装饰者模式对函数再wrapper。
4.中间值
文中提到“你极可能遇到过这样的场景,调用promise1,使用promise1返回的结果去调用promise2,而后使用二者的结果去调用promise3。”
咱们使用观察者模式解决。
6.调试
文中提到“最后一点,也是很是重要的一点在于,async/await可以使得代码调试更简单。2个理由使得调试Promise变得很是痛苦”
咱们也经过递归和 将要执行的函数放入一个数组解决。
对Promise几个主要缺点找到了补偿措施,就能够进行编码实现了。(固然咱们仍是要拥抱新特性的)
export function singalLamp(singalArr) { }
你们都知道对比typeScript,JS是动态+弱类型(动弱无关)。那么变量命名就须要在表达清逻辑的同时携带变量类型。好的代码是尽可能经过命名让用户理解和使用。(毕竟同时维护大量文档和代码是个难事)
总结一句就是:驼峰+逻辑+类型。
var doSomething = function(obj) { var _adapter = { name : 'xioaming', titile : 'xiaoming', age : 24, color : 'pink', size : 100 } for (var i in _adapter) { _adapter[i] = obj[i] || _adapter[i]; } //dosomething }
export function signalLight(data) { const sign = data.slice(); }
对传入的参数应该尽可能拆卸,以避免用户传参属性变动。(属性较多时,考虑使用适配器模式)
变量的使用应尽力保证函数是纯函数。对传参deepClone/slice,不修改外部变量。
export function singalLamp(singalArr) { function tic(singal, time) { return () => new Promise((res) => setTimeout(() => { console.log(singal); res(); }, time)); } const rawArr = singalArr.slice(); }
函数的声明/定义有A:function test() {} ; B:const test = function() {}; C:const test = () => {}
,那么他们有神么区别?
A方式:函数会提高,提高意味着在该做用域(scope)任何位置均可以使用。知道了这些,咱们能够得出一个结论:使用该方式函数必须是纯函数。
B/C方式:函数不会提高,此种方式通常定义一个非纯函数,非纯函数(这里指依赖于外部的变量)提高了也没有意义。由于它要依赖于上下文,即调用变量的初始化。
C方式:C方式中是一个箭头函数,难免让咱们思考为何箭头函数没有function test() {}
这种会提高的定义方式呢? 答案是箭头函数自身的特性(this指向依赖词法/静态做用域),这使得箭头函数的提高没有意义。
export function singalLamp(singalArr) { function tic(singal, time) { return () => new Promise((res) => setTimeout(() => { console.log(singal); res(); }, time)); } const rawArr = singalArr.slice(); const lampArr = rawArr.reduce(function(prev, item) { return prev.concat([tic(item, 1000)]); }, []); const step = function(iterator) { if (iterator === lampArr.length) { return step(0); } else { return () => lampArr[iterator]().then(step(++iterator)); } } step(0)(); } singalLamp(['red', 'green', 'yellow']);
函数的使用主要有两种:
闭包
闭包的本质是(对共享变量的操做,典型运用是观察者模式/备忘录模式)
普通
封装,复用。(当我门对一段逻辑不须要复用时,咱们仍将它写成函数的动机是:细颗粒化逻辑)
在Web开发过程当中,能够进行性能优化的方面多如牛毛,笔者在这里介绍几处切合本文主题的优化方式。即js的高性能代码书写(参考编写高性能的JS代码),这里简单说几个:
i++与++i
使用前缀自增表达式,也能带来小小的性能提高。(++i代替i++)
闭包
虽然上文介绍了闭包的实用性,可是仍是应该尽可能避免使用闭包,它就和remove dom
同样让人诟病。(垃圾回收问题,内存)
const与let
就 let 而言,他的使用场景应该是相对较少的,咱们只会在 loop(for,while 循环)及少许必须重定义的变量上用到他。
猜测:就执行效率而言,const 因为不能够从新赋值的特性,因此能够作更多语法静态分析方面的优化,从而有更高的执行效率。(参考阿里FED博客ES6 你可能不知道的事 - 基础篇)
要写好一个项目须要兼容,性能,安全等。写好一个功能须要设计模式和解耦需求。写好一个函数须要考虑['对比技术点','变量命名','参数使用','函数声明','函数使用'].join('+')
;
我的博客欢迎交流共勉成长