Alibaba Written Test
原文链接 http://jasonliao.me/posts/2016-03-21-alibaba-written-test.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
3 月 16 日下午,我跟实验室另一个前端同学到广电科技大厦进行 UC 的笔试,虽然去的过程比较曲折,但我们最后还是准时到达了指定地点,准备笔试。
因为太多人原因,我们被安排到了 14 楼的 UC 员工餐厅中进行笔试,然后 3 点 10 分左右,我们就开始正式笔试了,笔试是分不同的方向的,下面我们就来看看 UC 的笔试题(题目只能凭记忆复原,不保证准确)
a
变量是一个数组,如果数组长度为 0,则增加一个值为 1,否则则按先进先出的原则去掉一个值(代码越简短越高分)个人感觉考察了三目运算符,和数组的方法
a.length === 0 ? a.push(1) : a.unshift();
写出下列代码的结果
var func = (function (a) { this.a = a; return function (a) { return a + this.a } }(function (a, b) { return a; }(1, 4))); console.log(func(4));
这道题考察了
this
和 IIFE我们先来看看最低下的这个匿名函数,
(function (a, b) { return a; }(1, 4))
这个返回 1 没有问题,那么就相当于最顶的那个匿名函数传入了 1,然后把 1 赋给了this.a
,this
指向的是window
,所以这时window
已经多了一个属性a
且值为 1,这时func
就是一个函数为function (a) { return a + this.a; }
。当我们再执行func(4)
的时候,就相当于 4 + 1,答案就等于 5 啦一个
<ul></ul>
里插入 10 行<li>第 1 行</li>
~<li>第 10 行</li>
,考虑性能这道题考的应该是
Fragment
,我当时也知道,使用Fragment
可以避免逐个添加列表项,导致浏览器反复渲染,可以使用一个文档片段来保存它们,最后再一次性添加到文档中但是我却忘记了创建
Fragment
的方法,document.createElement('fragment')
看着不像,所以后来放弃了它,选择了innerHTML
,先来看看我的原来的答案var ul = document.createElement('ul'), innerHTML = '', i; for (i = 1; i++; i<=10) { innerHTML += '<li>第' + i + '行</li>'; } ul.innerHTML = innerHTML; document.body.appendChild(ul);
一般来说,在插入大量新 HTML 标记的时,使用
innerHTML
属性与通过多次 DOM 操作先创建节点再指定它们之间的关系相比,效率要高得多。这是因为在设置innerHTML
或outerHTML
时,就会创建一个 HTML 解析器。这个解析器是在浏览器级别的代码(通过是 C++ 编写的)基础上运行的,因此比执行 JavaScript 快得多。不可避免地,创建和销毁 HTML 解析器也会带来性能的损失,所以最好能够设置innerHTML
或outerHTML
的次数控制在合理的范围内这句话是 JavaScript 高级程序设计的引用,但其实通过 jsperf 的 测试,循环
appndChild
都比innerHTML
快所以正确答案还是应该使用
Fragment
,因为不断地使用appendChild
会使 页面不断地重新计算,重新布局和重绘。所以下面的可能才是正确答案var ul = document.createElement('ul'), fragment = document.createDocumentFragment(), i; for (i = 1; i++; i<=10) { var li = document.createElement('li'); li.innerText = '第' + i + '行'; fragment.appendChild(li); } ul.appendChild(fragment); document.body.appendChild(ul);
生成一个长度为 100 的数组
array
,值为其下标考察数组方法,但不仅仅是
map
先来看看我写在试卷上的答案
var arrObj = new Array(100); var array = arrObj.map(function (arr, i) { return i; });
我一开始认为,
new Array(100)
会产生一个长度为 100,值都为undefined
的数组,但其实不然,它只是一个length
为 100 的 空数组,数组,组...没错,它还考察了
join
和split
,可能还有一点 ES6var array = new Array(101).join(0).split('').map(function (arr, i) { return i; }); // or ES6 `Array.fill()` var array = new Array(100).fill(0).map((arr, i) => i);
这里要注意的是,我们使用
join
方法的时候,要新建一个长度为 101 的数组,因为join
是填在数组元素中间的,101 的元素中间才有 100 的空隙,然后再用空字符串来split
它们把
array
乱序排列这道题考察的就是
sort
方法,如果返回负数,则第一个参数在第二个参数前,返回正数,则第一个参数在第二个参数后,相等返回 0。我在试卷上的答案是,只要让返回值随机等于 -1 0 1 就可以了array.sort(function () { return Math.floor(Math.random() * 3 - 1); });
当然还有其他的方法,我们展宇大大想到的方法是,
Math.random()
返回 [0, 1),所以 0.5 的两边概率相等array.sort(function () { return Math.random() > 0.5 ? 1 : -1; });
用优雅的方式求出
array
的前十个数的和reduce
!var sum = array.slice(0, 10).reduce(function (pre, cur) { return pre + cur; });
累了吗?来点主观题?
你了解 JavaScript 中的继承吗?请列举一些,并说出你推荐哪种
Q: When is classical inheritance an appropriate choice?
A: NEVER
In JavaScript, prototypal inheritance is simpler & more flexible than classical inheritance. - 10 Interview Questions Every JavaScript Developer Should Know
网页上线之前,根据雅虎军规,要做哪些优化
怎么进一步地对上面的优化进行自动化
我母鸡呀,然后我就写了 Webpack,Gulp bala balala 小魔仙
- 写正则,匹配 http://*.9game.cn/*
Online Regexp Tester have fun :)
- 如果上面的正则很重要,要考虑性能,要考虑安全,要考虑对全局的影响,那要怎么做
我环系母鸡呀,我就说要不断地优化,把它独立存放,修改方便之类的
- 你平时怎么定位错误,使用什么开发工具
- 如果你本地测试完全没有问题,但是一上线就出现问题,怎么处理
线上 debug 呀,本地不要只做单元测试呀,我在讲什么呀
- 回调会导致 callback hell,要怎么处理,用一句话概括
Promise,简单清晰且 ES6 支持
Summary
嗯嗯,大概就是这么多,大概就是这么个意思,大概就是这么个顺序
总结下来之后,深刻地认识到,把小红书读透很重要(不是买东西那个!),大家也可以把题的答案写在评论里,我们一起讨论一下呀
如有错误,欢迎指正 :)