X

曜彤.手记

随记,关于互联网技术、产品与创业

  1. 综合技术方面:
    1. 1. 网站和页面性能优化:
    2. 2. 字体大小常用单位:
    3. 3. CSS Reset:
    4. 4. 弹性布局、响应式、重构:
    5. 5. 什么叫优雅降级和渐进增强:
    6. 6. HTML5 主要增强了什么:
    7. 7. Node.js 主要解决了什么问题:
    8. 8. 提高 CSS 性能:
    9. 9. CSS 预处理:
    10. 10. 关于浮动的原理和工作方式:
    11. 11. 浮动会产生什么影响呢,要怎么处理?
    12. 12. 你了解哪些常用 CSS 选择器?以及这些选择器的使用场景?
    13. 13. 你知道这些选择器的权重怎么计算?
    14. 14. 你了解哪些布局?你平时有使用过什么布局实现?
    15. 15. 你常用的 JS 框架有哪些?
    16. 16. 你从 jQuery 学到了什么?
    17. 17. JS 有哪些数据类型?
    18. 18. JS 的数据类型中哪些是引用类型?
    19. 19. 原型链:
    20. 20. 函数表达式和函数声明的区别:
    21. 21. 什么是闭包,为什么要使用闭包?
    22. 22. DOM 中的 Property 和 Attribute 两者的区别:
    23. 23. JS 作用域链:
    24. 24. 你对前端有什么理解?
    25. 25. 你觉得前端体系应该是怎样的?
    26. 26. Hybrid App:
    27. 27. IFC、BFC、GFC 和 FFC:
    28. 28. JS 垃圾回收机制:
    29. 29. Ajax 完整流程:
    30. 30. Gulp 和 Grunt 的异同点?
    31. 31. 浏览器可以并行下载多少个资源?
    32. 32. 你觉得哪些网站前端技术比较好,这些网站的架构怎样?
    33. 33. 淘宝网上的商品项,如图片,滚动到了才加载,是怎么实现的?
    34. 34. 你了解后端技术么,前后端一般是怎么配合的?
    35. 35. 安卓上如何实现 1px 像素线?
    36. 36. 流应用是什么?
    37. 37. 移动设备浏览器的 click 事件300毫秒延迟?
    38. 38. touchstart 的点击穿透问题:

前端关键技术点杂烩

本篇文章主要总结一下 Web 前端面试的一些常见面试题,同时这些问题也是对一些基础的技术概念和思想的理解。对这些基本知识的掌握程度和深度决定了你的技术层级。高级工程师是必须掌握本文列出的这些知识点,资深工程师则要对这些基本概念的纵向深度进行挖掘,【问题解答全部原创,转载请注明来源】。

综合技术方面:

1. 网站和页面性能优化:

缓存:ETag、Expire、Last-Modified 三者合用,Expire 字段可以让浏览器完全不发起 HTTP 请求,若按 F5 键发起请求,也可以通过判断 ETag(对应浏览器字段 If-None-Match) 和 Last-Modified(对应浏览器字段 If-Modified-Since)字段来确认是否需要更新资源还是使用 304 (Not Modified) 缓存的本地资源;

静态资源:代码压缩合并、CSS 雪碧图、分析 FTTB 是否采用 CDN、服务器开启 GZIP 压缩、图片压缩、静态资源使用独立域名,防止域名污染(静态资源不需要携带 Cookie,又叫 Cookie 隔离);

页面结构:样式表放顶部,JS 脚本放底部,不让 JS 脚本阻碍页面 DOM 的加载;

代码优化:缩短原型链,减少属性和方法的查找时间;使用事件代理代替事件绑定;减少对 DOM 的直接操作,减少页面重绘;使用 H5 新方法 requestAnimationFrame 来执行 DOM 动画;使用 createElement 代替 innerHTML 进行 DOM 插入,因为它的速度更快;

其他方法:BigPipe 优化、BigRender 优化、Quickling 优化;

2. 字体大小常用单位:

绝对值:像素 px、点 pt = (DPI / 72) px;

相对值:一个字的大小 em(默认值 1em = 16px,16px 也为浏览器的默认字体大小,继承父元素的大小,为了计算通常设 html { font-size: 63%; },即 1em = 10px)相对于根节点的一个字大小 rem;

3. CSS Reset:

“CSS Reset” 就是由于各种浏览器解释 CSS 样式的初始值有所不同,导致设计师在没有定义某个 CSS 属性时,不同的浏览器会按照自己的默认值来为没有定义的样式赋值,所以我们要先定义好一些 CSS 样式,来让所有浏览器都按照同样的规则解释 CSS,这样就能避免发生这种问题。本质就是清除浏览器默认样式,并且进行全局样式定义,Reset 文件要在项目初期定好,这样才不会产生后期的回归测试问题。

* {
  vertical-align: baseline;
  font-weight: inherit;
  font-family: inherit;
  font-style: inherit;
  font-size: 100%;
  outline: 0;
  padding: 0;
  margin: 0;
  border: 0;
}

4. 弹性布局、响应式、重构:

弹性布局:Flexbox 布局模式,适用于多行多列自适应布局。

响应式布局:媒体查询(Media Queries)和 Viewport(初始比例,最大比例,最大宽度,缩放控制)控制。

5. 什么叫优雅降级和渐进增强:

渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

两者区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带。

6. HTML5 主要增强了什么:

增加了很多利于网站 SEO 的语义化标签如 headerfooterarticlenav,功能性标签如 canvasvideoaudio 使得浏览器可以进一步摆脱插件。WebSocket、LocalStorage、WebSQL 等新功能特性,还有很多功能化的标签属性如 autocompleteautofocus 和很常用的 datalist 标签。

7. Node.js 主要解决了什么问题:

虽然单进程、单线程,但其事件环机制、非阻塞 IO,可以高效的处理高并发请求,并且与前端脚本语言统一。

8. 提高 CSS 性能:

加载性能:压缩样式表,不要使用 @import(诞生于 CSS2),@import 使用在低网速下会存在页面闪烁问题(link 标签是在加载页面前把 CSS 加载完毕,而 @import 则是读取到引用的文件之后再加载,会延长页面的留白期);

选择器性能:可忽略不计。

渲染性能:createDocumentFragment 对象在内存里操作 DOM、使用 class 类名替换来代替直接更改样式、开启 GPU 硬件加速;

Repaint(重绘):当在页面上修改了一些不需要改变定位的样式的时候(比如 background-colorborder-color 以及 visibility),浏览器只会将新的样式重新绘制给元素(这就叫一次“重绘”或者“重新定义样式”)。这时只需要屏幕的一部分要重画。

Reflow(回流重排):当页面上的改变影响了文档内容、结构或者元素定位时,就会发生重排(或称“重新布局”)。

其他:去除空规则;属性值为0时,不加单位;属性值为浮动小数“0.**”时,可以省略小数点之前的0;标准化各种浏览器前缀:带浏览器前缀的在前。标准属性在后;

9. CSS 预处理:

CSS 预处理器用一种专门的编程语言,在编写 CSS 的过程中可以使用变量、循环、递归等特性,然后再编译成正常的 CSS 文件,可以提高 CSS 编写效率,常用的预编译语言有 LESS、SESS 等。

10. 关于浮动的原理和工作方式:

浮动本质就是个带有方位的 display: inline-block 属性;会打破同一行的 inline-box 模型;

11. 浮动会产生什么影响呢,要怎么处理?

会产生高度塌陷,子元素均设置了浮动样式,父元素会失去高度。

解决方案:父级 div 层定义 overflow: hidden、结尾处加空 div 标签 clear:both、父级 div 定义伪类 :after(最后一个子元素的后边)和 zoom 属性。

.clearfix{zoom:1;}
.clearfix:after{display:block; content:"."; clear:both; line-height:0; visibility:hidden;}

12. 你了解哪些常用 CSS 选择器?以及这些选择器的使用场景?

ID 选择器、类选择器、伪类选择器、全局选择器 …(请跳至 W3School 查看更多)。

13. 你知道这些选择器的权重怎么计算?

权值为1000:代表内联样式,如 “style=”…””。

权值为100:代表ID选择器,如 “#content”。

权值为10:代表类,伪类和属性选择器,如 “.content”。

权值为1:代表类型选择器和伪元素选择器,如 “div p”。

通用选择器(),子选择器(>)和相邻同胞选择器(+)的权值都为0。

14. 你了解哪些布局?你平时有使用过什么布局实现?

弹性布局(与流体布局相似,大小单位使用 em)、固定布局、混合布局、绝对定位布局、流体布局(宽高以百分比计算,配合媒体查询完成) …

15. 你常用的 JS 框架有哪些?

jQuery、Knockout.js、Vue.js、AngularJs、EmberJs、React.js …(很多 MVVM 框架可以使用)

16. 你从 jQuery 学到了什么?

看了源码中一些“类型检测”函数的实现,jQuery 中的这些方法完成度非常高,实现很全面,性能也是很高的。例如如下所示代码:

class2type = {};

jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
  class2type["[object " + name + "]"] = name.toLowerCase();
}

type: function(obj) {
  return obj == null ? String(obj) : class2type[Object.prototype.toString.call(obj)] || "object";
}

isFunction: function(obj) {
  return jQuery.type(obj) === "function";
}

isArray: Array.isArray || function() {
  return jQuery.type(obj) === "array";
}

(其他知识点还有很多,异步队列,数据缓存,事件系统,异步请求等)。

17. JS 有哪些数据类型?

null、undefined、数字、字符串、数组、对象、布尔。

18. JS 的数据类型中哪些是引用类型?

数组、对象。

19. 原型链:

(内容太多,请自行 Google)

20. 函数表达式和函数声明的区别:

函数表达式只有函数定义的提升,函数声明则可以将函数定义和声明同时提升;函数表达式可以放在任何地方,函数声明则只能放到全局环境中。

21. 什么是闭包,为什么要使用闭包?

可以简单理解为“函数中的函数”。两个常见作用:一可以读取函数内部的变量、二让这些变量的值始终保持在内存中。父函数定义的变量在子函数的作用域链中,子函数没有被销毁,其作用域链中所有变量和函数就会被维护,不会被销毁。

// 此处在绑定函数时的 i 是没有问题的,从 0 到 “elements.length - 1”;
// 只是在子函数中的 i 是一直保持对父环境对象中的 i 的引用的,所以在调用时一直会输出 “elements.length”;
for (var i = 0; i < elements.length; i++) {
  elements[i].onclick = function() {
    console.log(i);
  }
}
// 用 IIFE 隔离外部环境对象,使父环境对象可以及时释放;
// IIFE 中定义的任何变量和函数,都会在执行结束时被销毁;
for (var i = 0; i < elements.length; i++) {
  (function(n) {
    elements[n].onclick = function() {
      console.log(n);
    }
  })(i);
}

22. DOM 中的 Property 和 Attribute 两者的区别:

Attribute 就是 DOM 节点自带的属性,例如 div 中常用的 id、class 等;Property 是这个 DOM 元素作为对象,其附加的内容,例如 childNodesfirstChild 等;

自定义的 Attribute 不会附加到 Property 上,对于属性 Property 的赋值在 IE 中可能会引起循环引用,内存泄漏。

操作 Attribute 时使用 setAttributegetAttribute 两个方法来操作,由于 getAttribute 可能会有浏览器兼容性问题,所以在 jQuery 中,在使用之前会对该方法进行测试:

div.className = "a";
var judge = div.getAttribute("className") === "a";

*对于 “style” 和 “onclick” 两个属性,它们的 Property 和 Attribute 分别是对象和字符串,与其他有所区别。

23. JS 作用域链:

在一些类 C 的语言中有“块级作用域”,即花括号的每一段代码都有自己的独立作用域,而 JS 只有函数级作用域;JS 作用域链的第一个对象始终是当前执行代码所在环境的变量对象(VO),声明函数在全局作用域,此时作用域链只有一个环境对象;运行函数时作用域链顶端加入了函数内的环境对象,运行完毕时顶端环境对象被销毁,以此类推。

JS 在查找变量时会从链的顶端(就近原则)一直向下查找。如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用。全局变量总是存在于运行期上下文作用域链的最末端,因此在标识符解析的时候,查找全局变量是最慢的。(最好和闭包一起理解)

24. 你对前端有什么理解?

前端工程化、组件化 …

25. 你觉得前端体系应该是怎样的?

  • 开发工具;
  • 代码质量;
  • 前端框架;
  • 前端开发标准;
  • 部署流程;
  • 代码组织;
  • 代码安全;
  • 移动 Web 开发;
  • 前沿技术社区;
  • 计算机网络体系;
  • 软件工程;
  • 可视化;
  • 浏览器;
  • 编程语言;

26. Hybrid App:

“Hybrid App” 底层依赖于 Native 提供的容器(UIWebview),上层使用传统前端技术做业务开发,底层透明化、上层多样化,这种场景非常有利于前端介入,非常适合业务快速迭代。(详情需深入研究,笔者这方面研究不多)

27. IFC、BFC、GFC 和 FFC:

IFC:内联 display: inline 格式化上下文,容器里面的子元素不会影响到外面的元素,表示盒子从左到右的水平排列方式;

BFC:块级 display: block 格式化上下文,表示盒子从上到下的垂直排列方式;

GFC:网格 display: grid 布局格式化上下文;

FFC:自适应 display: flex 格式化上下文;

Box: CSS 布局的基本单位:

Box 是 CSS 布局的对象和基本单位。直观点来说,就是一个页面是由很多个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不同类型的 Box,会参与不同的 Formatting Context(一个决定如何渲染文档的容器),因此 Box 内的元素会以不同的方式渲染。

Formatting Context:

“Formatting Context” 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。最常见的 Formatting Context 有 “Block Fomatting Context”(简称 BFC)和 “Inline Formatting Context”(简称 IFC)。

BFC布局规则:

  • 内部的 Box 会在垂直方向,一个接一个地放置。
  • Box 垂直方向的距离由 margin 样式决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠。
  • 每个元素的 “margin box” 的左边, 与包含块 “border box” 的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  • BFC 的区域不会与 “float box” 重叠。
  • BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  • 计算 BFC 的高度时,浮动元素也参与计算。

哪些元素会生成 BFC?

  • 根元素;
  • float 属性不为 “none”;
  • position 为 “absolute” 或 “fixed”;
  • display 为 “inline-block”、“table-cell”、“ table-caption”、“flex”、“inline-flex”;
  • overflow 不为 “visible”;

28. JS 垃圾回收机制:

标记清除:跟踪环境对象,即跟踪作用域链,GC 会把那些没有作用域影响的内存清除掉;

引用计数:即跟踪记录每个值被引用的次数,但可能会有“循环引用”的问题;

29. Ajax 完整流程:

// 获取 XHR 对象;
// 设置回调函数;
xmlHTTP.onreadystatechange = callback;

// 打开一个 XHR 链接;
xmlHTTP.open("GET", url, true);

// POST 请求要设置编码类型;
// xmlHTTP.setRequestHeader("Content-type", "application/x-www-form-urlencoded");  
// 发送请求;
xmlHTTP.send(null);

function callback() {
  if (xmlHTTP.readyState == 4) {
    if (xmlHTTP.status == 200) {
      console.log(xmlHTTP.responseText);
    }
  }
}

30. Gulp 和 Grunt 的异同点?

Gulp 基于“流”的概念,只有一次 IO 过程,类似于 Linux 里的管道,又像 jQuery 的链式调用;Gulp 更易用;

31. 浏览器可以并行下载多少个资源?

在 HTTP/1.1 协议下一般是6个,最多不超过8个;

32. 你觉得哪些网站前端技术比较好,这些网站的架构怎样?

举例:淘宝网,用来很多 H5 的语义化标签;降级兼容做的很好,对禁用脚本的浏览器提供友好的选项;云客服使用 WS ,来代替 Ajax 轮询等;

33. 淘宝网上的商品项,如图片,滚动到了才加载,是怎么实现的?

应该是 PipeRender 技术的一种,BigRender 的原理是通过某种方式,将首屏不需要的 HTML 代码先存放起来。渲染好首屏后,再将存储好的 HTML 代码逐步渲染出来。

34. 你了解后端技术么,前后端一般是怎么配合的?

笔者公司用的是 CakePHP 和 Laravel 两套 PHP 框架,Laravel 本身有自己的模板引擎,同时可以与 Gulp 进行无缝衔接;模板会预留出需要替换的变量位置,前后端分离处理;前端模板可以进行模板的继承与嵌套;

35. 安卓上如何实现 1px 像素线?

因为 Retine 屏的分辨率始终是普通屏幕的2倍,导致原本 1px 的细线在手机上显示为 2px;

IOS8 及以上可以直接使用 border-width: 0.5px; 来设置 1px 的线段,其他平台可以用 transform 将细线高度缩小一半:

.hairlines li:after {     
  content: "";     
  position: absolute;     
  left: 0;     
  background: #000;     
  width: 100%;     
  height: 1px;     
  -webkit-transform: scaleY(0.5);             
  transform: scaleY(0.5);     
  -webkit-transform-origin: 0 0;             
  transform-origin: 0 0; 
}

36. 流应用是什么?

“流应用”结合了原生 App 和 Web App 的优势,又消除了各自的缺点。流应用建立在 “H5+” 这一突破性技术之上,通过强化 HTML5 使其达到原生 App 的功能和体验,并辅以类似流媒体的边用边下发行技术,这2项技术是流应用诞生的关键。

37. 移动设备浏览器的 click 事件300毫秒延迟?

来源于最初的 Safari 浏览器在用户点击屏幕时会等待300毫秒,以判断用户是想进行单击还是进行双击缩放。其他浏览器也借鉴 Safari 的特性,导致了这一问题。

基本解决:修改 viewport 来禁用缩放 <meta name="viewport" content="width=device-width, user-scalable=no"> 并同时设置 CSS 属性 touch-action: none;

完美方案:FastClick 的实现原理是在检测到 touchend 事件的时候,会通过 DOM 自定义事件立即出发模拟一个 click 事件,并把浏览器在 300ms 之后的 click 事件阻止掉。

38. touchstart 的点击穿透问题:

因为在移动端浏览器,事件执行的顺序是 touchstart > touchend > click,而 click 事件有 300ms 的延迟,当 touchstart 事件把 B 元素隐藏之后,隔了 300ms,浏览器触发了 click 事件,但是此时 B 元素不见了,所以该事件被派发到了 A 元素身上。如果 A 元素是一个链接,那此时页面就会意外地跳转。




评论 | Comments


Loading ...