一、HTML、Javascript、CSS 基础
#### 能力定义
* 熟悉:常用的HTML标签和编写;了解Javascript语法;了解常用CSS属性和功能
* 掌握:能使用语义化标签;javascript代码可读性高;CSS 结构清晰
* 精通:深入理解HTML标签(如:video、svg、canvas等);Javascript掌握闭包作用域,掌握Javascript内存分配和使用;CSS优化精练
* 综合应用:能合理组织HTML、CSS、Javascript实现页面,具备页面整体架构能力
1、浏览器中的事件循环机制(event loop)
- 同步任何都在主线程上执行,形成了一个执行栈。
- 主线程之外,还存在一个任务队列。只要异步任务有了运行结果,就在任务队列之中放置一个事件。
- 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,将队列中的事件放到执行栈中依次执行。
- 主线程从任务队列中读取事件,这个过程是循环不断的
整个的这种运行机制又称为 Event Loop(事件循环)
2、宏任务和微任务
有哪些宏任务,哪些微任务?
- macro-task(宏任务)
- script(主代码块)、setTimeout、setInterval、setImmediate、I/O、UI render
- MessageChannel
- postMessage
- micro-task(微任务)
- process.nextTick(Nodejs)
- 原生Promise
- MutationObserver
同步代码先执行,执行是在栈中执行的,微任务大于宏任务,微任务会先执行(栈),宏任务后执行(队列)
3、事件的捕获冒泡机制
addEventListener 的第三个参数默认是 false(事件冒泡)
DOM事件流(event flow)存在三个阶段:事件捕获阶段、目标阶段、事件冒泡阶段
- 事件捕获:通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。
- 事件冒泡:与事件捕获恰恰相反,事件冒泡的顺序是由内到外进行事件传播,直到根节点
DOM标准事件流的触发先后顺序为:先捕获再冒泡,即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。
<div id="parent">
<div id="child"></div>
</div>
var parent = document.getElementById('parent')
var child = document.getElementById('child')
// 设置为 true 就是事件捕获:点击child后,输出为: parent child
parent.addEventListener('click', function(){
console.log('parent')
}, true)
child.addEventListener('click', function(){
console.log('child')
}, true)
// 如果不想冒泡,则加入 e.stopPropagation()
child.addEventListener('click', function(e){
console.log('child')
e.stopPropagation()
}, false)
3、谈谈 doctype 的作用
DOCTYPE是document type(文档类型)的缩写。<!DOCTYPE>声明位于文档的最前面,处于标签之前,他不是html标签。主要作用是告诉浏览器的解析器使用哪种HTML规范或者XHTML规范来解析页面。
4、谈谈BFC。哪些方式会触发BFC?
概念:块级格式化上下文(Block Formatting Context,BFC)是Web页面的可视化CSS渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。
- BFC是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定的规则进行物品摆放,并且不会影响其他环境中的物品。
- 如果一个元素符合触发BFC的条件,则BFC中的元素布局不受外部影响。
- 浮动元素会创建BFC,则浮动元素内部子元素主要受该浮动元素影响,所以两个浮动元素之间互不影响。
创建BFC
- 根元素或包含根元素的元素
- 浮动元素 float = left | right | inherit(不等于none)
- 绝对定位元素 position = absolute | fixed
- display = inline-block | flex | inline-flex | table-cell | table-caotion
- overflow = hidden | auto | scroll (不等于visible)
BFC的特性
- BFC是一个独立的容器,容器内子元素不会影响容器外的元素。反之亦然。
- 盒子从顶端开始垂直地一个接一个排列,盒子之间地垂直间距是由margin决定的。
- 在同一个BFC中,相邻的块级盒子的垂直外边距会发生重叠。
- BFC区域不会和 float box 发生重叠。
- BFC能够识别并包含浮动元素,当计算其高度时,浮动元素也可以参与计算了。
BFC的作用
- 清浮动
- 浮动元素会脱离文档流(绝对定位元素也会脱离文档流),导致无法计算准确的高度,这种问题称为高度坍塌。
- 解决高度坍塌问题的前提是能够识别并包含浮动元素,也就是清除浮动。
- 通过 overflow: hidden 创建BFC,固然可以解决高度坍塌的问题,但是大范围应用在布局上肯定不是最合适的,毕竟 overflow: hidden 会造成溢出隐藏的问题,尤其是与JS的交互效果会有影响。
- 我们可以使用clearfix实现清除浮动。
.clearfix:after{
content: "";
display: block;
clear: both;
}
- 避免外边距折叠
- 外边距折叠只会发生在同一BFC的块级元素之间。如果它们属于不同的BFC,它们之间的外边距则不会折叠。所以通过创建不同的BFC,就可以避免外边距折叠。
5、谈谈script标签的 defer 和 async 属性。
直接使用script脚本的话,html会按照顺序来加载并执行脚本,在脚本加载&执行的过程中,会阻塞后续的DOM渲染。现在大家习惯于在页面中引入各种第三方脚本,如果第三方服务商出现了一点小问题,比如延迟之类的,就会使得页面白屏。
script提供了两种方式来解决上述问题,async 和 defer,这两个属性使得script不会阻塞DOM的渲染。
defer
- 如果script标签设置了该属性,则浏览器会异步的下载该文件并且不会影响到后续DOM的渲染;
- 如果有多个设置了defer的script标签存在,则会按照顺序执行所有的script;
- defer脚本会在文档渲染完毕后,DOMContentLoaded事件调用前执行;
async
- async的设置,会使得script脚本异步的加载并在允许的情况下执行。
- async的执行,并不会按着script在页面中的顺序来执行,而是谁先加载完谁执行。
- DOMContentLoaded事件的触发并不受async脚本加载的影响,在脚本加载完成之前,就已经触发了DOMContentLoaded
普通的script
文档解析 --> 脚本加载 --> 脚本执行 --> DOMContentLoaded
文档在解析的过程中,如果遇到script脚本,就会停止页面的解析进行下载。资源的下载是在解析过程中进行的,虽说 script1 脚本很快加载完毕,但是它前面的 script2 并没有加载&执行,所以它只能处于一个挂起的状态,等待 script2 执行完毕后再执行。
当这两个脚本都执行完毕后,才会继续解析页面。
defer
文档解析时,遇到设置了defer的脚本,就会在后台进行下载,但是并不会阻止文档的渲染,当页面解析&渲染完毕后,就会等到所有的defer脚本加载完毕并按照顺序执行,执行完毕后会触发DOMContentLoaded事件。
async
async脚本会在加载完毕后执行。
async脚本的加载不计入DOMContentLoaded事件统计。
推荐的应用场景
defer:如果你的脚本代码依赖于页面中的DOM元素(文档是否解析完毕),或者被其他脚本文件依赖。例如:评论框、代码语法高亮、polyfill.js
async:如果你的脚本并不关心页面中的DOM元素(文档是否解析完毕),并且也不会产生其他脚本需要的数据。例如:百度统计。
如果不太能确定的话,用defer总是会比async稳定。
6、JS有哪些基础类型?
基本数据类型:Undefined、Null、Boolean、Number、String、Symbol(es6新增)
复杂数据类型:Object
7、原生JS点击 url 下面的 li 显示其索引值。
采用事件委托实现:利用 Array.prototype.slice.call(nodeList)的作用将具有 length 属性的元素转为数组,这样可以利用 indexOf 方法获取 li 的索引值。
var nodeList = document.getElementsByTagName('li');
var arrNodes = Array.prototype.slice.call(nodeList);
var nodeULs = document.getElementsByTagName('ul');
nodeULs[0].addEventListener('click', function(e){
var target = e.target;
alert(arrNodes.indexOf(target));
}, false)
8、如何计算input框中内容的实际宽度?
思路:定一个span标签,span中的内容和input中的内容一致,通过获取span的宽度就是input内容的宽度。
<style>
input{
width: 200px;
}
span{
visibility: hidden;
position: absolute;
}
</style>
<body>
<input type="text" id="inp">
<span id="content"></span>
<button id="btn">打印contentWidth</button>
<script>
var input = document.getElementById("inp");
var content = document.getElementById("content");
var btn = document.getElementById("btn");
input.addEventListener('input', function(e){
content.innerHTML = e.target.value;
})
btn.addEventListener('click', function(e){
console.log(content.offsetWidth);
})
</script>
</body>
9、const定义的 object 和 array 类型数据为什么还能修改?
因为对象和数组是引用类型的,const参数中保存的仅仅是对象的指针,这就意味着,const仅能保证指针不发生改变。修改对象的属性不会改变对象的指针,所以是被允许的。
也就是说,const定义的引用类型只要指针不发生改变,其他的不论如何改变都是允许的。
二、HTTP、TCP/IP 等网络协议
#### 能力定义
* 熟悉:了解常用的 HTTP 状态码,HTTP Request Method,熟练使用AJAX
* 掌握:理解各个状态码和Request Method作用,理解 restful架构设计,理解session,cookie; 深入理解AJAX、WebSocket通信
* 精通:理解 HTTP 缓存、HTTP2等新特性,理解JWT、oAuth2等授权相关知识,灵活使用AJAX
* 综合应用:善于解决各个状态,能充分使用HTTP特性,掌握网络通信原理,善于解决前后端通信异常
三、Git 代码管理工具
#### 能力定义
* 熟悉:能使用常用的Git命令和客户端工具管理代码
* 掌握:熟练使用Git命令,理解 Git flow
* 精通:擅长 Git 合并、回退、Tag 等相关的Git flow 操作命令
* 综合应用:能配合CI/CD工具开发自动脚本
四、VUE、React等前端框架
#### 能力定义
* 熟悉:了解常用语法、生命周期
* 掌握:能灵活使用生命周期,能熟练使用配套组件
* 精通:理解实现原理,能解读源码,能编写高质量组件
* 综合应用:能结合配套工具编写质量代码来实现页面架构
五、前端工程化开发(Webpack)等
#### 能力定义
* 熟悉:能使用 nodejs安装工程环境,了解webpack 配置功能项
* 掌握:理解webpack 工程原理
* 精通:善于优化webpack 打包性能
* 综合应用:能编写工程自动化脚本,熟练使用测试框架
1、webpack中loader和plugin有什么区别?
什么是loader?
loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中。
- 处理一个文件可以使用多个loader,loader的执行顺序和配置中的顺序是相反的,即最后一个loader最先执行,第一个loader最后执行。
- 第一个执行的loader接收源文件内容作为参数,其他loader接收前一个执行的loader的返回值作为参数,最后执行的loader会返回此模块的Javascript源码。
什么是plugin?
在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果。
loader和plugin的区别
对于loader,它是一个转换器,将A文件进行编译成B文件,这里操作的是文件,比如将A.scss转换为A.css,单纯的文件转换过程。
plugin是一个扩展器,它丰富了webpack本身,针对的是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,进行广泛的任务。
六、Javascript 对象化、模块化编程能力
#### 能力定义
* 熟悉:了解OOP,AMD,CMD
* 掌握:能封装高质量工具类
* 精通:理解和善于使用设计模式,掌握常用数据算法和数据结构
* 综合应用:灵活使用设计模式、数据算法、数据结构,提供高性能的程序架构
七、浏览器渲染原理和页面性能优化
#### 能力定义
* 熟悉:了解页面渲染原理
* 掌握:理解浏览器中页面代码执行流程
* 精通:理解页面重排/重绘、页面阻塞,并有效避免
* 综合应用:善于优化页面性能,提供高性能页面架构
1、浏览器的渲染过程
- 解析HTML文件,创建DOM树
- 解析CSS,生成CSS Rule Tree
- 将CSS与DOM合并,构建渲染树(render),render树中不包含定位和几何信息
- 构建布局树,布局树含有元素的定位和几何信息(计算渲染树节点大小)
- 绘制(paint)
2、重绘、回流
浏览器的重绘指的是改变每个元素外观时所触发的浏览器行为。比如颜色、背景等样式发生了改变而进行的重写构造新外观的过程。重绘不会引发页面的重新布局,不一定伴随着回流。
回流指的是浏览器为了重新渲染页面的需要,而进行的重新技术元素的集合大小和位置。它的开销是非常大的,回流可以理解为渲染树需要重新进行计算。
每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的,因为要构建render tree。在回流的时候,浏览器会使渲染数中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。
一般最好触发元素的重绘,避免元素的回流。比如通过添加类来添加css样式,而不是直接在DOM上设置。当需要操作某一块元素的时候,最好使其脱离文档流,这样就不会引起回流了,比如设置position:absolute 或者 fixed,或者display: none 。等操作结束后再显示。
前端有哪些缓存
http缓存:
- 强缓存:Cache-Control、Expires
- 协商缓存:Last-modified、ETag
浏览器缓存:cookie、localStorage、sessionStorage、ApplicationCache
三级缓存原理
1、先去内存看,如果有,直接加载。
2、如果内存没有,则去硬盘获取,如果有就直接加载。
3、如果硬盘也没有,那么就进行网络请求。
4、加载到的资源缓存到硬盘和内存。
八、WEB服务打包、部署
#### 能力定义
* 熟悉:了解常用的WEB服务软件(nginx、apache等),了解 npm script
* 掌握:善于编写 npm 打包发布脚本;能部署使用nginx,了解pm2 等发布工具
* 精通:熟练使用 bash 脚本;熟练配置 nginx 反向代理,理解负载均衡
* 综合应用:熟练使用linux,善于解决和部署 WEB服务,能提供高效 WEB 应用系统CI/CD方案
九、互联网WEB应用系统架构
#### 能力定义
* 熟悉:理解WEB应用系统原理,了解常用前后端开发语言
* 掌握:善于优化WEB服务,理解web性能优化原理,熟悉常用缓存服务(如CDN,Redis等)
* 精通:理解web程序设计,擅长高性能WEB应用系统架构设计,熟练掌握常用的数据库(Mysql、Mongodb等),熟练使用1、2种后端语言
* 综合应用:精通 1、2种后端语言,能主导架构设计WEB应用系统