1. 1. hover控制显隐的级联菜单
  2. 2. 获取股票价格
  3. 3. 实现轮播图
  4. 4. 排序算法
  5. 5. 几个标准
    1. 5.1. DOM
    2. 5.2. css3
  6. 6. 浏览器如何渲染css
  7. 7. es6新的数组遍历方法
  8. 8. 块级元素和内联元素有何不同

相比百度,美大的面试官似乎很关注标准方面的问题、同时也问了一些体现综合能力的题目。总结如下:

hover控制显隐的级联菜单

这个常见于导航条和电商网站的侧边栏,也可以用于实现自定义的右键菜单,最简单的一个思路就是用hover伪类+子菜单绝对定位来做,但感觉回答得挺勉强的,模拟大众点评的侧边栏形式再实现一遍吧:

See the Pen sidebar by levonlin (@levonlin) on CodePen.

获取股票价格

给定一个表格,每行的几个单元格分别放置股票代码、名称和待获取的股票价格以及一个按钮。要求点击一个按钮就获取改行的股票价格,数据交换格式自定。

核心思路就是通过点击事件发送请求,并显示回传数据而已。因为按钮可能很多,就想到了使用事件代理减少性能损耗。原生实现如下(用了新浪财经的数据):

See the Pen Get Stocks Price by levonlin (@levonlin) on CodePen.

实现轮播图

就是经典的带自动播放、进度显示、左右方向控制的轮播图啦,而且要求封装接口实现批量导入图片生成轮播图。

其实自己也实现过几次了,但是回答时还是思路很不清晰,说明还是没有学到位,构建的能力不足啊。重新研究了一下:

轮播图的主要有三个组件(图片、箭头、原点),而这三个组件又对应三个切换(自动切换、左右切换、任意切换)的操作。这里此采用了构造函数+原型对象来封装整个功能,构造函数主要做三件事:

  • 获取配置的属性(三个切换的开关)
  • 输出整个组件初始结构、获取UI属性
  • 初始化三个切换动作

构造函数中各种实例属性配置完后,接下来就只要在对象的原型里,把输出组件、切换动作这两类方法实现就好了。难点就是切换的实现,为简单起见,这里用了个_moveTo方法一步到位,没有过渡;同时原点状态的切换也是重新渲染后直接替换,减少了频繁琐碎的类名切换操作。

最后,只要new一下构造函数,把资源、配置传进去,一个轮播图就可以轻松生成:

See the Pen carousel by levonlin (@levonlin) on CodePen.

排序算法

记得最清楚的是冒泡,其他的就不太熟悉了,将常用的几种贴下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/* 冒泡 */
function bubbleSort(arr) {
var last = 0;
for (var i = arr.length - 1; i > 0; i = last) {
last = 0;
for (var j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j+1] = temp;
last = j;
}
}
}
return arr;
}
/* 选择 */
function selectSort(arr) {
for (var i = arr.length - 1; i > 0; i--) {
var maxIndex = i;
for (var j = 0; j < i; j++) {
if (arr[maxIndex] < arr[j]) {
maxIndex = j;
}
}
if (maxIndex !== i) {
var temp = arr[i];
arr[i] = arr[maxIndex];
arr[maxIndex] = temp;
}
}
return arr;
}
/* 插入 */
function insertSort(arr) {
for (var i = arr.length - 1; i > 0; i--) {
var temp = arr[i - 1];
for (var j = i; j < arr.length; j++) {
if (arr[j] < temp) {
arr[j - 1] = arr[j];
} else {
break;
}
}
arr[j - 1] = temp;
}
return arr;
}

几个标准

标准这东西,除非遇到实在不能解决的问题,自己平常是很少去深究的。而这次面试问了好多这方面的问题,让我感觉这方面的认知真的很匮乏。其实想想未来的职业发展,研究并掌握标准是一种保障,也是自己升值潜力的所在,毕竟前端界千变万化还是基于标准的,这就是所谓内功吧:

DOM

问了DOM0级别事件和DOM2级事件的不同,这个还好,DOM0级在元素上只能一个事件加一个处理函数,而DOM2可以添加多个嘛。然而接下来再问DOM3级的内容、有没有DOM4等我就懵了,印象中DOM3多了些xml方面的api,但具体也说不上了,翻了翻高程,大概有这么几个方面:

  • 引入用于比较节点的方法:isSameNode(DOM4已废弃)和isEqualNode,这两者间其实就是=====的区别。
  • 节点上数据的get和set操作:getUserDatasetUserData。(DOM4已废弃)
  • DOM3级新支持的事件:focusinfocusouttexInputmouseentermouseleavecompositionstartcompositioninupdatecompositionend。以及键盘事件的新属性:keycharlocationgetModifierState()等。
  • XML节点的几个命名空间方法:isDefaultNameSpace(nameSpace)、lookupNamespaceURI(prefix)、lookupPrefix(nameSpace)
  • 新增了Xpath的API。

要了解更多内容还是参见官网吧。至于DOM4,去年也已经发布了。

css3

问我css3的发布机制,平常也是只用不深究,故也不甚了解。查了下,为避免规范过于庞大,css3是将整个规范拆分为一个个模块的形式发布的。

有几个比较重要的模块:

选择器、颜色、背景和边框、数值和单位、文字特效、2D/3D转换、动画、多列布局、用户界面

浏览器如何渲染css

参见这篇文章可知大致流程如下:

  1. 解析HTML构建DOM树
  2. 结合css构建渲染树
  3. 渲染树布局(reflow,这一步产生了盒模型)
  4. 渲染树绘制(rasterizing)

由于每一步都要耗费时间进行计算,所以这也前端性能优化的重点,比如要避免触发浏览器重构、重绘等。

es6新的数组遍历方法

最窘的是把forEach当成es6的。。。,还说出了个for-of,但这不止适用于数组,还可用于字符串和MapSet等新类型的遍历。

事后想起来专门用于数组的还有mapfilter,但它们还是早在es5里就有了,只是自己长期没用,潜意识里就把它们划进“未来标准”里去了。查了下才知道,es6提供了三个用来遍历数组的新方法:entries()keys()values(),它们都将遍历结果保存于一个遍历器对象中返回。区别如下:

  • keys()是对数组的键名的遍历。
  • values()是对数组键值的遍历。
  • entries()方法是对数值的键值对的遍历。

顺便附上自己不常用的mapfilter

  • arr.map(callback[, thisArg]): callback以元素、索引、数组本身作参数,thisArg设置回调函数的this;返回一个处理后的新数组(这点和forEach只返回undefined不同,意味着该方法可以链式调用)。
  • arr.filter(callback[, thisArg]):callback以元素、索引、数组本身作参数,返回true则保留该元素,false则舍去,thisArg设置回调函数的this;返回一个处理后的新数组(也可链式调用)。

块级元素和内联元素有何不同

回答得不全,得考虑容纳性、换行、盒模型上的差别:

  • 块级元素:可容纳内联元素和其他块状元素;排斥其他元素与其位于同一行;拥有完整的盒模型特性。
  • 内联元素:只能容纳文本或内联元素;允许其他内联元素与其位于同一行;不设宽高(高度和行高有关)、上下margin无效、上下padding、border溢出。