LinDaiDai的 2019 面试准备
前言
最近在掘金上刷到jsliang小伙的一篇文章jsliang 的 2019 面试准备,深受启发,恰巧自己最近也在准备面试,所以趁着此黄金时期写下此文章,做一些前端方面的总结,巩固知识的同时也希望对行走在路上的你们有所帮助。
1.HTML
1. 什么是HTML5?
首先,我们知道HTML5其实就是对HTML标准的第五次修改,我们广义上说的HTML5,实际是包过HTML,CSS,JavaScript在内的一套技术组合.
它的主要目标呢就是将互联网语义话,以便更好的被人类还有机器阅读,同时能够更好地支持各种媒体的嵌入,比如图片,链接,音乐等非文字元素.
我认为,它有俩大特点:首先,强化了web网页的表现性能.其次,追加了本地数据库等web应用的功能,提供了更多能支持网络应用的标准集.
拓展:
web数据库?
web数据库呢实际上就是以web查询接口方式访问的数据库资源,它将数据库技术和web技术融合在一起,使数据库成为了web的重要有机组成部分.
它的工作过程可以简单的描述成:用户通过浏览器的操作界面以交互的方式经由web服务器来访问数据库.
web?
万维网的简称web,
Web的工作步骤如下。
(1)用户打开客户端计算机中的浏览器软件(例如Internet Explorer)。
(2)用户输入要启动的Web主页的URL地址,浏览器将生成一个HTTP请求。
(3)浏览器连接到指定的Web服务器,并发送HTTP请求。
(4)Web服务器接到HTTP请求,根据请求的内容不同作相应的处理,再将网页以HTML文件格式发回给浏览器。
(5)浏览器将网页显示到屏幕上。
HTML语言?
超文本标记语言,就是创建网页的计算机语言 HTML(Hyper Text Markup Language)
我们所说的网页其实就是一个HTML文档,文档内容由文本和HTML标记组成,扩展名是.html或.htm
HTML标记:它的作用是告诉浏览器我们页面的结构和格式.如果将特定的英文单词放入标记中就是标签
HTML程序:放在<html></html>中,由文件头<head></head>和文件体<body></body>组成.
HTML规范:也就是HTML标准,是由W3C(万维网联盟)制定的.
HTML程序的编辑环境:任何文本编辑器.
HTML程序的运行环境:任何的浏览器
XML语言?
可拓展标记语言,是用来定义其它语言的一种元语言.
XML文档,由字符数据和标记组成.它的语义约束是DTD
DTD?
文档类型定义,基本格式:<!DOCTYPE 根元素[……规则……]>
我们知道浏览器解析css的俩种模式是: 标准模式和怪异模式
标准模式是指按w3c的标准解析执行代码,而怪异模式是指浏览器按它自己的方式解析执行.
而浏览器以哪种模式解释就是与你网页中的DTD声明有关.
若没有写DTD的话会使页面进入怪异模式.
HTML5不需要DTD?
因为HTML5没有使用SGML或者XHTML,是一个全新的东西,所以不需要参考DTD
HTML和XML区别?
结构上大致相同,本质上不同:
1.语法要求不同,html中不区分大小写,xml中更严格.
2.标记不同,html使用固有的标记,xml没有固有的标记.
3.作用不同,html显示数据,xml描述数据,盛放数据.
注:
XML不是HTML的替代品,因为它们是俩种不同用途的语言.
XHTML和HTML?
XHTML是更严格更纯净的 HTML 版本,但现在已经不再使用XHTML。
.html? .htm?
.htm与.html没有本质上的区别,表示的是同一种文件,只是适用于不同的环境之下.DOS(磁盘操作系统)只能识别8 + 3的文件名,所以只能识别.htm而不能识别.html
2. HTML5与HTML4或更早的HTML的区别
1.文档声明上:html4比较复杂,而html5只有一小段<!DOCTYPE html>
2.结构语义上:html4没有体现语义化的标签,而html5有
3.同时h5又新添了很多表单元素的属性和类型
4.功能上HTML5更加强大,比如可以利用canvas标签配合js来实现绘图功能,也比如新增的视频标签video,以及新增的表单元素类型,像email,number,range,data等
H5新特性?
1.新的文档类型
2.脚本和链接无需type
3.语义标签Header和Footer
4.Hgroup标签,对h1~h6进行分组。
5.标记元素mark高亮标签
6.图形元素figure和figcaption
7.新的表单控件,比如data,number,range,color等等
8.新的表单属性,比如autofocus、autocomplete、multiple、 placeholder、pattern等等
9.新的功能性标签:audio、vidio
10.强大的绘图标签canvas
11.离线存储localstorage和sessionstorage
css3新特性?
- CSS3实现圆角(border-radius),阴影(box-shadow),
- 对文字加特效(text-shadow、),线性渐变(gradient),旋转(transform)
- transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);// 旋转,缩放,定位,倾斜
- 增加了更多的CSS选择器 多背景 rgba
- 在CSS3中唯一引入的伪元素是 ::selection.
- 媒体查询,多栏布局
- border-image
ES6新特性?
1.默认参数
2.字符串模板
3.多行字符串
4.拆包表达式
5.改进的对象表达式
6.箭头函数
H5的离线储存?
离线存储表示的是用户没有与因特网链接时,可以正常访问站点或应用.
原理是基于一个新建的.appcache文件的缓存机制,通过这个文件上的解析清单离线存储资源,这些资源就会像cookie一样被保存下来,当在没有网络的情况下,浏览器就会通过被离线存储的数据进行页面展示.
在我们H5中提供了俩种在客户端存储数据的新方法:
localStorage和sessionStorage
而在这之前呢,这些功能都是由cookie完成的,只不过cookie的存储量太小了最多也才4k,所以不适合大量数据的存储.
cookie
设置cookie
document.cookie = "user=wangxiansheng"
alert(document.cookie)
设置过期时间
//expires:过期时间, 接受一个日期对象
var d = new Date()
d.setTime(d.getTime() + 2 * 24 * 60 * 60 * 1000)
var expires = d.toUTCString();
//一个条目包含保存的键值对和过期时间
document.cookie = `demo=wangpei;expires=${expires}`;
console.log(document.cookie);
localStorage和sessionStorage?
它们俩都是H5新添的离线存储方法,并且两种方式保存的数据都仅限于该页面的协议,但不同之处在于:
localStorage它的存储没有时间限制,一周或者一个月一年,数据仍然存在.
而sessionStorage里面存储的数据会在浏览器会话结束时被清除
在兼容性上,各浏览器支持localStorage和sessionStorage的容量上限不同.在ie8以上是支持的,不包过ie8.
chrome4支持localStorage,chrome5支持sessionStorage.
cookie与它俩的区别?
第一点,在存储量上,cookie太小了,最多只能存储4K.
第二点,cookie可以设置过期时间,如果没有设置则默认是在关闭窗口或者回话窗过期,但localStorage和sessionStorage没有提供设置过期时间的功能,但我们可以在存储的时候加上时间,以后在取值的时候判断一下localStorage是否过期就可以了.
浏览器对离线存储的管理和加载?
在线状态下,浏览器要是发现html头部有manifast属性的话,它会请求manifast文件,若是第一次访问app,那么浏览器就会根据mainfest文件的内容下载对应的资源进行离线存储
离线状态下,已经访问过app并且资源已经离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的manifest文件与旧的manifest文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,那么就会重新下载文件中的资源并进行离线存储.
userData?
ie支持userData存储数据.但是基本已经很少使用了,除非有很强的浏览器兼容需求.
浏览器对H5的支持性?
在几个主流的浏览器中,比如ie浏览器,ie8以下是不支持的,ie9支持部分,比如video标签是支持的.ie10以上支持
还有像Chrome这样的高级浏览器,它的3-5支持大部分,在6以上就全部支持了.
H5中的form如何关闭自动完成功能?
我们知道,表单元素的自动完成功能就是输入框输入内容的时候,浏览器会从你以前的同名输入框的历史记录中查找出类似的内容并列举在输入框下面,当有时我们希望使用AJAX技术从数据库搜索并列举而不是根据浏览器的历史记录搜索,所以此时我们就需要将form的自动完成功能给关闭.
在ie浏览器下,我们可以在浏览器的设置中的internet选项菜单内容中将自动完成功能中的设置.
也可以在form标签中通过设置autocomplete为"on"或者"off"来开启或关闭自动完成功能.
3. a标签的四个伪类是什么?
a标签的四个伪类分别是未访问link,已访问visited,鼠标悬停hover,鼠标点击瞬间active
四个伪类的顺序是:分别是link,visited,hover,active.
其实link和visited的顺序其实是无所谓的,因为不可能同时触发未访问和已访问.
但是link是一定要在hover或者active之前.
visited要在hover之前.
而hover要在active之前.
关于兼容性的话,必须要在ie8包含ie8以上才有用.
4. HTML中文乱码
乱码原因?
第一点可能是因为没有设置HTML编码,也就是没有在meta标签中设置charset属性.
第二点也可能是使用了记事本编辑html,直接使用记事本编辑很容易造成html编码乱码
怎么解决?
可以在meta标签中设置charset属性为"utf-8",另外尽量使用sublime等编辑器编辑代码,而不是用记事本.
5. input属性有哪些?
input的属性目前在w3c上发布的是有23种,像比较常见的有定义输入字段的初始值value,规定输入字段为只读的readonly,还有规定字段禁用的disabled.
另外还有一些给input限制的标签,比如像size规定字段的尺寸,maxlength规定输入字段允许的最大长度
在我们H5中有给input添加了很多的属性,比如规定form自动完成功能的autocomplete,自动获取焦点的autofocus.
还有max和min规定元素的最大最小值等等.
input中readonly和disabled的区别
俩个都是表单的属性,都能做到使用户不能更改表单域中的内容.但他们也有一些差别.
第一点:readonly只针对type为text,password,textarea有效,而disabled对所有的表单元素都有效.
第二点:readonly可以进行表单提交,而disabled不能.
input的兼容性问题
首先在样式上,当type为text的时候,在ie浏览器下和在火狐等浏览器下高度不同,ie下为24px,火狐下为22px
type为submit也会不同.
同时在低版本的ie浏览器(ie8以下)下,input中的文本内容都会偏上一点.解决方案是给其添加padding-top.也可以给其设置高度和行高相等,但是在火狐下不行.
type为button时,value不能为空,否则它就不会和其他的表单元素头部对其,而是向上一些.解决方案:最后不要给value为空.
6.内联块元素有哪些?
常用的内联块元素有img标签,input标签
内联块元素有哪些特征?
首先内联块元素是和块元素一样可以设置宽高的,但是却可以像内联元素一样放在同一行显示,代码空格换行也会被解析.
内联块元素之间为什么会有小间隙?
那是因为内联元素的空格和换行会被解析
解决方案可以手动将回车空格给去除,但是这样会影响代码的美观,所以如果是像img这种不需要文本内容的内联块元素可以给它的父级的font-size设为0,也可以将它的宽高都设为100%.
7. 如何优化网页
对于我们前端的网页优化来说,一方面是提高我们页面的加载速度,还一方面可能就是提高我们页面的表现性.
对于提高页面加载速度可以有这么几种方式:
1.减小Http请求的数量.
2.还可以运用css sprites技术将多个图片融合在一张大图上,另外也可以对图片进行压缩,比如png图片在www.tinypng.com上面进行压缩,然后在webpack进行转base64,只有图片大小不超过10k才会转.
3.使用CDN;
4.添加Expires头;
5.将样式表放在头部,减少页面首屏出现的时间,使内容逐步呈现,提高用户体验,可以防止"白屏"
6.将脚本放在底部,也是和样式表放在头部一样.因为js的下载会中断DOM的更新,所以script标签要是放在首屏范围内的HTML代码里是会截断首屏的内容的.另外也是为了保证脚本能按顺序执行.
7.避免css表达式
8.使用外部的javascript和css,因为当脚本或者css是从外部引用进来的时候,浏览器就有可能缓存它,在以后加载的时候就可以直接使用缓存.
9.减少DNS查找.
10.精简代码.
11.避免重定向.因为当页面发生了重定向的时候,就会影响整个HTML文档的传输.
12.使AJAX可缓存,也就是多用get而少用post,因为get是会在客户端进行缓存的,而post不会.
CDN?
CDN实际就是一组分布在不同地理位置的Web服务器,可以更加有效的像用户发布内容.
CDN还可以进行数据备份,扩展存储能力,进行缓存.
同时也是有一些缺点的,比如响应时间是会受到其他网站流量的影响,并且如果CDN服务质量下降了,你的工作质量也会下降,同时它也无法控制组件服务器.
Expires头?
当我们初次访问一个页面的时候,是会进行很多HTTP请求的,但是通过使用一个长久的Epires头,就可以使这些组件被缓存下来,下次访问的时候就可以减少不必要的HTTP请求.
重定向与打开新页面
相同点:
都实现了根据自己的条件实现的页面的跳转
区别:
重定向导致浏览器发出了新的请求,在重定向之前存储为请求属性的任何对象都会消失,所以跳转到应用内的某个页面,没有浏览记录,而打开新页面不会这也是两者最大的区别.
所以使用重定向后,返回按钮会失效,除非在设置返回按钮时给它一个指定的路径.
为了提高网页的性能,应该避免重定向.
重定向?
重定向是用户从一个URL重新路由到另一个URL.常用的重定向的类型有永久重定向,临时重定向.
永久重定向用于当网站的域名发生变更后,应该告诉搜索引擎域名已经变更了,从而不影响网站的排行.
而临时重定向主要是实现post请求之后告知浏览器转移到新的url,
应用的场景主要是
1.跟踪内部流量
2.跟踪出站流量
重定向如何损失性能的?
因为我们知道重定向其实就是用户从一个URL重新路由到另一个URL,所以就使浏览器发出了一个新的请求,这样是会延迟整个HTML文档的传输
8. 'data-'属性的作用是什么?
在介绍data-
属性的作用之前我想先介绍一下data-
,
data-属性是H5才新增的一种自定义属性,这些属性集可以通过对象的dataset属性获取,不支持该属性的浏览器可以通过 getAttribute方法获取
在兼容性上
,dataset属性只有在IE11以上,Chrome8+浏览器中实现,所以在此期间最好用的getAttribute和setAttribute来操作。
为什么使用它呢,我们知道HTML标签是可以通过自定义属性来存储和操作数据的,但是这样在写法上就不太符合Html的规范,所以H5新添了这个自定义属性data
js中获取设置data-属性:
<div id = "user" data-uid = "12345" data-uname = "王先生" > </div>
<script>
var user = document.getElementById('user');
// 1. data属性能够直接用getAttribute获取,但那样就失去了它的意义,所以不推荐使用
var userName = user.getAttribute('data-uname');
var userId = user.getAttribute('data-uid');
console.log(userName); // "王先生"
// 设置的话可以用setAttribute();
user.setAttribute('data-site', 'www.baidu.com');
console.log(user.dataset.site); // www.baidu.com
// 2. 定义了data-的属性应该用dataset来获取,获取的是整个含有data属性的对象
var dataSet = user.dataset
console.log(dataSet);// {uid:"12345",uname:"王先生"}
// 这样我们就可以用dataset来获取里面需要的data属性
console.log(dataSet.uid); // "12345"
// 要修改的话就直接修改
dataSet.uname = "我是帅帅的王先生";
console.log(dataSet.uname);
// 使用in来判断一个属性是不是dataset中的属性
console.log('someDataAtrr' in user.dataset); // false
console.log('uname' in user.dataset); // true
// // 删除data属性
delete user.dataset.uname; // 或者 user.dataset.user = null
console.log(user.dataset.uname);
// 选择所有包含 'data-uid' 属性的元素
var dataUids = document.querySelectorAll ('[data-uid]') ;
console.log(dataUids); // [div#user.users, div.users]
console.log(dataUids[0]); // <div class="users" id = "user" data-uid = "12345" data-uname = "王先生" >我是王先生</div>
</script>
CSS中获取data-
<style>
.users[data-uid="12345"]{
color: red;
}
</style>
<div class="users" id = "user" data-uid = "12345" data-uname = "王先生" >我是王先生</div>
<div class="users" id = "user" data-uid = "54321" data-uname = "李先生" >我是李先生</div>
// 只有王先生变红
9. 怪异模式?
在模式上,主要是有标准模式,和怪异模式。首先怪异模式ie下独有的一种模式。它和我们的标准模式主要是在布局,样式解析和脚本的执行上有一些差异吧。就比如在怪异模式下,盒模型是按照怪异盒模型解析的,我们知道怪异盒模型和我们普通盒模型的差别还是很大的,另外,还有比如像在怪异模式下,我们常用的margin:0 auto;这种居中方式就没用了。
标准模式和怪异模式的转换
在css
中设置属性
div {
box-sizing: border-box;/*怪异*/
box-sizing: content-box;/*标准*/
}
怎样查看浏览器进入哪种模式
使用 window.top.document.compatMode
可显示为什么模式
10. 你如何理解HTML结构的语义化?
当页面样式加载失败的时候能够让页面呈现出清晰的结构
有利于seo优化,利于被搜索引擎收录(更便于搜索引擎的爬虫程序来识别)
便于项目的开发及维护,使html代码更具有可读性,便于其他设备解析。
11. BFC?
什么是BFC
BFC是块级格式化上下文,是指在浏览器中创建了一个独立的渲染区域,这个区域内的元素布局不会影响到外面的元素,并且这个渲染区域只对块级元素起作用,然后利用这些规则我们可以达到一定的布局效果。
BFC的生成
float的值不为none;
display为inline-block table-ceil table-caption
overflow的值不为visible
position的值为absolute fixed
BFC的应用
防止margin重叠
解决了浮动的相关问题,因为创建了BFC的元素,子浮动元素也会参与其高度的计算,这样就不会产生高度塌陷问题。
实现多栏布局的一种方式,因为创建了BFC的元素,与浮动元素相邻也不会和它互相覆盖。比如可以设置俩侧宽度固定,中间元素随页面的宽度自适应。
12. 标签嵌套问题
a标签不能嵌套a标签(链接嵌套浏览器解析为兄弟级关系)
p标签不能嵌套块级标签 浏览器解析为兄弟级关系
如若需要进行链接嵌套,可以推荐使用area标签
2. css
1. css代码压缩?
在以前是使用一些压缩工具进行手动压缩,但是现在我们都是直接使用webpack打包工具.
2.三层嵌套?
在ie6是不支持border-radius的,当我们要在ie6下想做一个圆角就可以使用三层嵌套.但是在我们实际的开发中,要是只是为了达到一个圆角的效果而使用各种图片之类的有些太牵强了,所以在以前的开发中,我一般就是直接使用border-radius.
3.页面可见性(Page Visibility)?
Page Visibility是H5新增的API
主要是用来判断用户是不是在与页面进行交互,也就是比如页面最小化了或者隐藏在其它标签页后面了,那么此时就可以用上我们的这个页面可见性.
这个API主要由三个部分组成:
第一个是document的hidden属性,表示页面是否隐藏的布尔值.
第二个是document的visibilityState属性,它有四个可能状态的值.
第三个是visibilitychange事件,当页面的可见性发生改变时会触发.
我们可以监听document的visibilitychange事件,当该事件触发时,获取document.hidden的值来对页面进行一些操作.比如隐藏页面时让播放的歌曲暂停等等.
什么是页面隐藏?
页面的隐藏包过页面在后台标签页中或者浏览器最小化,
而页面被其他软件遮盖不算是隐藏
visibilityState?
visibilityState是判断页面状态的一个属性,有一下四个状态的值:
- hidden:页面在后台标签页中或者浏览器最小化
- visible:页面在前台标签页中
- prerender:页面在屏幕外执行预渲染处理 document.hidden 的值为 true
- unloaded:页面正在从内存中卸载
H5之前如何获取页面隐藏?
在H5之前,我们是靠监听document获取焦点和失去焦点来简单的认为页面是隐藏还是显示的.
4. hack?
在css中,hack是指一种兼容css在不同浏览器中正确显示的技巧.因为在不同的浏览器中,对css的解析认识不同,因此会导致生成的页面效果不同.这时候我们就需要针对不同的浏览器取写对应的css样式.一些常见的特殊符号的应用.
IE6认识的hacker 是下划线 _ 和星号 *****
IE7能识别星号" * ",但不能识别下划线"_",而firefox两个都不能认识。
5.解决display:inline-block;在ie6/7中不能正常显示
如果是块元素的话给它设置inline-block没有效果的,解决方案:
直接让块元素设置为内联对象呈现,也就是设置display: inline,然后在触发块元素的layout,比如设置zoom为1等.
其他的内联元素比如a标签,span标签是可以正常显示的.
layout?
layout是ie的一个私有概念,它决定了一个元素如何显示以及约束其包含的内容等等.一个元素是否具有"layot"属性可能会导致很多问题,比如ie中很多常见的浮动bug,容器与它子孙元素的边距重叠问题等等.
如何触发layout?
给元素设置浮动,设置绝对定位,设置宽高,设置zoom,以及转换为inline-block,或者设置overflow等等都可以触发layout.
zomm?
是ie中网页缩放的比例
ie6/7下通过它来触发元素的hasLayout,解决大部分ie浏览器下的兼容问题.比如可以用来清除浮动,避免容器高度塌陷.
不过对于现在浏览器一般没必要用它了,因为它只在ie浏览器下有用.
6.清除浮动?
给父级float:left; 会影响后面的元素
给父级height:500px; 子级高度改变父级也要改变
给父级overflow:hidden;不同浏览器会有兼容性问题
给父级display:inline-block; 内联块的一堆问题还在 比如对齐之类的问题
给父级设置定位;
当然最好的办法就是在浮动元素的父级元素上使用伪类:after在其后面加上一个空元素并清除它的浮动就可以解决.
7.png图片有几种格式?
分别有3种不同深度的格式:png8,png24,png32
png8表示的是8位索引色位图.png24就是24位索引色位图
在使用场景上
,因为png8最多只能显示256种颜色,就更适合那些颜色比较单一的图片,比如纯色,logo,图标等等.
而png24能显示的颜色要比png8多的多,大概能有1600万.
显示效果上:
png8支持索引透明和alpha透明,而png24不支持透明,png32都支持.
在兼容性上
:我们经常说的ie6下不支持PNG透明,指的是不支持png24的透明,但是支持png8的透明,就像支持gif一样的透明一样.也就是在ie6下png24的图片的透明部分会被蒙上一层灰色.(解决方案
索引色位图
计算机显示的图片中所使用的颜色,均有一个颜色体系,每一个颜色与一个颜色表对应出来,索引色常使用16色.32色等,最多不超过256色.
切图是保存为什么样的格式
1.色彩丰富的,大的图片切为gif;
2.尺寸小,而且色彩不是很丰富和背景透明的切成gif或者png8;
3.而半透明的切为png24
8.两栏自适应布局,右侧div宽高不定
比如左侧图片大小固定,右侧随父级宽度改变而改变
1.使用定位.
2.父级设定高度,子级高度100%,左侧图片大小固定并给左浮,右侧元素宽度给100%,因为左侧浮动了是压得住属性压不住内容的,所以如果有什么文字内容的是会环绕在图片周围,但是最好还是加一个margin-left,以避免右侧有背景图会被覆盖.
3.利用弹性布局,父级设定display: flex;左侧图片大小固定,右侧元素设定flex为1.
9. 如何垂直居中一个浮动元素?
第一种情况:已知元素的宽高
将元素设置定位absolute或者fixed,top和left为50%,margin-left和margin-top为负的宽高的一半。
将元素设置定位absolute或者fixed,top和left为50%,transform: translate()为负的宽高的一半或者-50%。
第二种情况:不知元素的宽高
将元素设置定位,四个方向定位都为0,然后设定margin: auto;
如果子元素是内联元素或者内联块元素也可以将父元素设定:(使图片居中最快的方式)
display: table-ceil;
text-align: center;
vertical-align: middle;
第三种情况:一个浏览器页面中,只有一个div模块,让其上下左右居中
将元素设置定位absolute或者fixed,top和left为50%,margin为auto。
10.响应式布局是什么?
响应式布局就是界面能够适应不同的设备,不同的屏幕大小,让同一个页面在在不同的大小比例里看上去还是舒适的,不同分辨率上看上去还是合理的,不同的操作方式体验应该是统一的.
3. JS
1.同步和异步
用自己的话描述一下对“异步“和”同步“的理解
对“异步”和“同步”我是这样理解的,首先,我们知道JS是一门单线程语言,也就是不能同时进行很多的事。
所有的任务都得排队,要前一个任务完成之后才能执行下一个任务。但如果我们的任务列表中有像定时器,ajax请求这一类耗时程序的时候,不得不等结果出来之后再往下执行。所以这时候我们的JS就想到可以将这些耗时耗性能的任务提取出来然后先不管它们让他们处于等待状态,等那些不耗时的任务执行完之后再来执行这些耗时的任务。
所以像前面我说的那些不耗时的任务的就是==同步任务==,盛放他们的列表就是==主线程==。而另一些就是==异步任务==,它们自然是不在主线程中的,而是在==任务队列==。所以只要主线程空了,就会去读取"任务队列"。
异步编程的四种方式
第一种是异步编程最基本的方法,采用==回调函数==的方式,将不耗时的任务或者说是函数作为耗时的函数的回调函数,这种方式的优点是简单,容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合,流程会很混乱,并且每个任务只能指定一个回调函数。
另一种思路是采用==事件驱动==的方式,任务的执行不是取决于代码的顺序,而是取决于某个事件是否发生,这种方法的优点是比较容易理解,可以绑定多个事件,并且每个事件都可以指定多个回调函数,去除了耦合,有利于实现模块化。缺点是整个程序都变成了事件驱动,运行流程会变得不清晰。
第三种可以采用==发布/订阅==的方式,或者说是观察者模式,这种方法的性质与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。
最后一种就是我们ES6的==promise==对象,它是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。简单说,它的思想是,每一个异步请求都会返回一个Promise对象,该对象会有一个then方法,允许指定回调函数。它的优点在于回调函数变成了链式写法,程序的流程可以看到很清楚,并且也有一整套配套的方法,实现很多强大的功能,比如指定多个回调函数,指定发生错误时候的回调函数fail等等。并且它也有其他三个方法没有的一点就是如果一个任务已经 完成了,再添加回调函数,这个回调函数是会立即执行的,这样就不用担心是否错过了某个事件或信号。它的缺点就是有些难理解。
2. HTTP
http协议
首先http是一个基于请求与响应模式的、无状态的、应用层的协议
我们的http协议主要包括了2部分,一部分是==请求协议==,也就是浏览器向服务器端发送请求的时候,还有一个是==响应协议==,也就是服务器向浏览器响应的时候。
同源
嗯,同源策略是浏览器的一个安全机制,为了保护用户的信息安全,防止恶意的网站窃取数据,也就是一个url的协议,域名,端口号三个都相同情况下,才被判断为同源。
它最初也就是使用在不同源的情况下不能读取其他网站的Cookie,但是随着互联网的发展,同源策略也变得越来越严格,目前的话,如果非同源的情况下,不仅像Cookie、Localstorage这种本地储存不能获取,连DOM也不能获取,同时也不能发Ajax请求。
跨域
虽然它有它的好处能够保护用户信息安全,但有时也是挺不方便的。
第一种:
比如我们知道cookie是服务器写入浏览器的一小段信息,只有同源的网页才能共享,但是当俩个网页一级域名相同,只是二级域名不同的情况下,我们也想共享这个cookie。这时就可以通过设置相同的document.domain来共享cookie,也可以在服务器设置cookie的时候,指定cookie的所属域名为一级域名(Set-Cookie: domain=.example.com),这样二级,三级域名不用做任何的处理也能读取到这个cookie。
第二种:
还有一些请求是像iframe窗口和window.open方法打开新窗口的时候,如果打开的这个窗口与父窗口不同源的时候,是不能与父窗口进行通讯。也就是对于完全不同源的网站,想解决这种跨域的窗口通讯问题,该怎么办。
目前其实也是有三种解决方案的。
1.第一种是利用片段标识符,我们知道片段标识符指的就是URL的#后面的部分,改变这个片段标识符是不会重新刷新的,这样父窗口就可以把信息写入子窗口的片段标识符中。
2.第二种是利用window.name属性,因为我们知道这个属性最大的特点就是无论是否同源,只要在同一个窗口,前一个页面设置了这个属性,后面一个网页也能读取到它。它的优点就是window.name容量很大,可以存储非常常的字符串,缺点是要监听子窗口的window.name,这样就影响了网页的性能。
3.当然,我们H5为了解决这个问题,就引入了一个全新的跨文本通信的API.这个API为window对象新增了一个window.postMessage方法,允许俩窗口通信,无论这俩个窗口是否同源。这样就也可以获取LocalStorage和cookie了。
但是在有src属性的标签是不受同源策略的影响的,比如我们的img、script、ifame、link标签。
jsonp
原理:
jsonp的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制,同时兼容性也更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或者ActiveX的支持,并且在请求完毕之后可以通过一个回调函数callback的方式回传结果。
同时它也有一些缺点,首先它只支持get请求而不支持post等其他类型的HTTP请求,另外它只支持跨域HTTP请求这种情况,不能解决不同域的俩个页面之间如何进行JavaScript调用的问题。
http状态码
http状态码由三位数字组成,第一位表示的是一个大状态,后面两个数字表示该大状态的一个子状态。
比如200就是请求成功,3开头的表示重定向,4开头的状态码客户端出错,5开头的是服务器错误。
又比如常见的404资源未找到,403被请求的页面禁止访问等等。
互联网的分层
实体链接网络传输应用
TCP协议
首先,TCP协议是以太网协议和IP协议的上层协议,也是应用层的下层协议。
它的作用呢,简单来说就是为了保证数据通信的完整性和可靠性,防止丢包。
其他协议
以太网协议
最底层的以太网协议(Ethernet)规定了电子信号如何组成数据包(packet),解决了子网内部的点对点通信。
IP协议
IP协议的作用有两个:
1·为每台计算机分配IP地址,
2.确定哪些地址是在同一个子网络。
解决的就是多个局域网互相通信,比如路由器就是基于IP协议的。
ARP协议
IP数据包是放在以太网数据包中的,所以我们必须知道俩个地址,一个是对方的IP地址,一个是MAC地址。
获取MAC地址的俩种情况:
1、俩台主机不在一个子网络,将数据包交给“网关”,让“网关”处理。
2、俩台主机在一个子网络中,利用==ARP协议==获取同一个子网络中的主机的MAC地址。
3.AJAX
ajax的原理简单来说其实就是通过==XMLHttpRequest==对象来向服务器发异步请求,从服务器获取数据。而这个XMLHttpRequest就是我们Ajax的核心机制,它是在ie5中首先引入的,是一种支持异步请求的技术,简单来说,就是javascript能够及时向服务器请求和处理响应,而不阻塞用户,达到无刷新的效果。
大致流程就是创建一个==XMLHttpRequest对象==,然后调用这个对象的==open==方法来指向请求的类型,有get方式或者是post方式来连接服务器,接着可以使用==send==来发送请求,同时可以用==onreadystatuschange==来监听请求的状态。若是成功获取到数据的话再用回调函数拿到数据。
可以看到Ajax的==优点==也很明显,最大的一点就是页面无刷新,给用户的体验非常好,同时也可以使用异步的方式,提高响应能力,减轻了服务器的负担,进一步促进页面和数据的分离。
但同时它也是有一些缺点的,而且这些缺点也是它先天产生的。首先它干掉了==back==按钮,即对浏览器后退机制的破坏。还有一点就是==安全问题==,可能开发者在不经意间就暴露了比以前更多的数据和服务器逻辑。另外他它对==搜索引擎==的支持也比较弱
首先,我们知道同源策略规定了,Ajax的请求只能发给同源的网址,否则就会报错。
除了设置==代理服务器==,还有三种方式来规避这种限制。
第一种也就是我们常用的方法==jsonp==,它最大的优点就是简单适用,老式的浏览器也全都能用。
第二种呢就是可以利用==WebSocket==这种通信协议。
第三种可以使用==CORS==,它比jsonp要更强大一些,因为jsonp是只支持GET请求的,而它却支持所有类型的HTTP请求。但是我们知道CORS他的兼容性不是很好,一些老牌浏览器像IE10以下的它就不支持。
1.ajax的事件?
ajaxComplete(callback)
ajaxError(callback)
ajaxSend(callback)
ajaxStart(callback)
ajaxStop(callback)
ajaxSuccess(callback)
4.模板引擎
是最早期为了取代ajax把数据拿来然后渲染到页面上,在性能上也没有做任何的优化,经常看到的模板引擎比如==Mustache、Underscore、 Templates==等等。但随着像React Angular 以及最近比较火的Vue的出现,可以说完全的被取代了。而且这些前端框架做到的不仅仅是它能做到的,同时在性能上优化了很多,功能上也更加的强大。
5. 常用的webapk打包工具
老点的有phoneGap
app和webapp区别
app是可以点击安装的,是基于操作系统,webapp是基于浏览器的
6.闭包
我们知道,在我们JS中是没有块级作用域的,js文件与js文件之间定义的变量也是可以互相访问的,这样在我们开发中就很容易造成命名冲突从而引起我们程序的一系列异常。
但要知道如果在函数内部定义一个变量的话这个变量就只有在其内部能访问到也就是我们常说的局部变量了,那么OK,如果我们用一个外部的函数将一个内部函数包裹起来,那么现在如果在外部函数里定义一个变量,这个变量就只有这个外部函数和它里面的内部函数能够访问到。
主要是为了设计私有的方法和变量。它的优点也很明显,可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
所以它主要是有这三个特性:
1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收
7. 继承?
首先我们js里是没有真正像其它面向对象语言一样概念的继承,js中的继承都是模拟继承。
像我们常见的继承方式有:
第一种,可以采用构造函数绑定的方式,就是使用apply、call来借调要继承的那个父对象的构造函数。
第二种,可以利用prototype属性来实现继承,可以将要继承的那个子构造函数的原型对象指向父构造函数创建出来的实例对象。但是这种方式会导致继承链的紊乱。
第三种,第三种方式是第二种方式的一种改进吧,就是直接将要继承的那个子构造函数的原型对象指向父构造函数
的原型对象。它相比于第二种效率要高点,但是由于现在俩个构造函数的原型对象指向的都是同一个,所以如果更改任意一个原型对象中的属性的话都会映射到另一个函数中。
所以可以有第四种改进方案,利用一个空对象来作为中介。创建一个空对象然后这空对象中是一个函数,我们将这个空对象的原型对象指向父构造函数的原型对象,接下来用这个空的构造函数创建一个实例对象,再将子构造函数的原型对象指向它,实现了继承。
第五种我们可以采用拷贝的方式来实现继承。拷贝的话又分深拷贝和浅拷贝。
深拷贝浅拷贝
- 深浅拷贝概念
我们知道js中数据类型是分为基本数据类型和引用数据类型,这些基本数据类型是可以直接访问的,它们是存放在我们栈内存中,而我们的引用数据就是那些存储在堆内存中的对象。
所以其实当我们进行将一个对象赋值给另一个对象的过程实际只是将整个对象的地址传递给了,此时它们俩指向的都是同一个地址,这样如果我改变其中一个对象中的属性的话是也会影响另一个对象的,这也就是我们说的浅拷贝。
那么深拷贝呢,它就是解决了上面那种情况,是将父对象拷贝到子对象中,而且俩者的内存和以后的操作都互不干扰。
- 有哪些是浅拷贝?
- 简单的赋值语句
- ES6的新函数
Object.assign()
- 对象的解构:
{ ...object }
- 有哪些深拷贝的方法?
- 进行浅拷贝的递归
function deepClone(obj) {
let objClone = Array.isArray(obj) ? [] : {};
if(obj && typeof obj === "object") {
for(key in obj) {
if(obj.hasOwnProperty(key)) {
// 判断 obj 子元素是否为对象,如果是,递归复制
if(obj[key] && typeof obj[key] === "object") {
objClone[key] = deepClone(obj[key]);
} else {
// 如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a = [1, 2, 3, 4];
let b = deepClone(a);
a[0] = 2;
console.log(a, b);
// Console
// a = [2, 2, 3, 4];
// b = [1, 2, 3, 4];
该方法实际就是通过typeof
判断以下对象中属性的类型是不是object
,如果是的话则在进行接下去的判断。(这里就直接借鉴jsliang小伙的写法了)
- JSON.parse(JSON.stringify(obj))
当然你也可以采用JSON.parse(JSON.stringify(obj))
的方式来进行拷贝,但是这种拷贝是存在兼容问题的,因为我们只这俩种方法是只有在ie8以上才支持的,并且它不支持拷贝值为function
、symbol
和undefined
的属性。
8. null
console.log(Number(null));
console.log(parseInt(null));
console.log(typeof null);
console.log(Number(undefined));
console.log(parseInt(undefined));
console.log(typeof undefined);
demo.html:14 0
demo.html:15 NaN
demo.html:16 object
demo.html:18 NaN
demo.html:19 NaN
demo.html:20 undefined
9.TypeScript和JavaScript的对比
TypeScript 与JavaScript两者的特性对比,主要表现为以下几点:
- TypeScript是一个应用程序级的JavaScript开发语言。(这也表示TypeScript比较牛逼,可以开发大型应用,或者说更适合开发大型应用)
- TypeScript是JavaScript的超集,可以编译成纯JavaScript。这个和我们CSS离的Less或者Sass是很像的,我们用更好的代码编写方式来进行编写,最后还是有好生成原生的JavaScript语言。
- TypeScript跨浏览器、跨操作系统、跨主机、且开源。由于最后他编译成了JavaScript所以只要能运行JS的地方,都可以运行我们写的程序,设置在node.js里。
- TypeScript始于JavaScript,终于JavaScript。遵循JavaScript的语法和语义,所以对于我们前端从业者来说,学习前来得心应手,并没有太大的难度。
- TypeScript可以重用JavaScript代码,调用流行的JavaScript库。
- TypeScript提供了类、模块和接口,更易于构建组件和维护。
10. Async/await相比于Promise好在哪里?
- 写法上更加简洁干净,对于代码量的节省很明显。避免了嵌套,提升可读性。
- 错误处理更强大,Async/await使得处理同步+异步错误成为现实。
- 可以允许中间值。
- Promise链中返回的错误栈没有给出错误发生的位置的线索,而Async/await中的错误栈会指向错误所在的函数。这样在我们分析生产环境的错误日志时非常有用。
- Async/await能够使得代码调试更简单。2个理由使得调试Promise变得非常痛苦:1.不能在返回表达式的箭头函数中设置断点;2.在
.then
代码块中设置断点,点击下一步调试器不会跳到下一个.then
而是直接跳过异步代码。
想了解具体区别的小伙可以移步:async/await比promise好的原因
4. Canvas
1.canvas基本写法
var drawing = document.querySelector('#drawing');
if (drawing.getContext) {
var context = drawing.getContext("2d");
context.beginPath();
}
2. canvas绘制钟表
var drawing = document.querySelector('#drawing');
if (drawing.getContext) {
var context = drawing.getContext("2d");
// 绘制外圆
context.beginPath();
context.arc(100, 100, 99, 0, 2 * Math.PI, false);
// 内圆
context.moveTo(194, 100);
context.arc(100, 100, 94, 0, 2 * Math.PI, false);
// 变换原点
context.translate(100, 100);
// 旋转表针
context.rotate(1);
context.moveTo(0, 0);
context.lineTo(0, -85);
context.moveTo(0, 0);
context.lineTo(-65, 0);
context.stroke();
}
3. canvas获取像素点
let imageData = context.getImageData(0, 0, image.width, image.height);
5. vue
1.生命周期
- 什么是vue的生命周期
我理解的生命周期是,每一个vue实例被创建之前都要经过一系列 的初始化过程。比如需要设置数据监听,编译模板,还有数据变化时更新DOM等等。同时在这个过程中,就会运行一些就叫做生命周期钩子的函数,用来给予用户在一些特定的场景下添加代码。
- Vue的生命周期分为哪几种?
主要分为以下8种:
创建前/后:在 beforeCreated 阶段,Vue 实例的挂载元素
$el
和数据对象 data 以及事件还未初始化。在 created 阶段,Vue 实例的数据对象 data 以及方法的运算有了,$el
还没有。载入前/后:在 beforeMount 阶段,
render
函数首次被调用,Vue 实例的 $el 和 data 都初始化了,但还是挂载在虚拟的 DOM 节点上。在 mounted 阶段,Vue 实例挂载到实际的 DOM 操作完成,一般在该过程进行 Ajax 交互。更新前/后:在数据更新之前调用,即发生在虚拟 DOM 重新渲染和打补丁之前,调用 beforeUpdate。在虚拟 DOM 重新渲染和打补丁之后,会触发 updated 方法。
销毁前/后:在执行实例销毁之前调用 beforeDestory,此时实例仍然可以调用。在执行 destroy 方法后,对 data 的改变不会再触发周期函数,说明此时 Vue 实例已经解除了事件监听以及和 DOM 的绑定,但是 DOM 结构依然存在。
- 第一次页面加载会触发 Vue 哪几个钩子?
会触发 4 个生命钩子:创建前/创建后、挂载前/挂载后。
2.slot
我对slot的理解就是当组件中的某一项需要单独定义的时候,那么就应该使用slot。
比如说在一个模态框中,付款成功和付款失败,这个模态框仅仅是差了一个字或者是图片不一样,
那么这个时候利用slot就会是不错的选择。
单个的slot都没有问题,如果组件中想要使用多个slot的时候就应该使用具名slot。具名slot呢也就是使用一个特殊的特性name来进一步配置如何分发内容。我们可以在组件中定义slot的时候给一个name属性,然后在调用组件时候在匹配内容内用slot属性来匹配对应的name。同时它也允许有一个匿名的slot,也就是默认插槽,它是作为找不到匹配内容片段的备用插槽,若是没有这个默认插槽的话,那么这些内容片段就会被抛弃。
3.vue中的双向数据绑定原理
vue是通过数据劫持的方式来进行双向数据绑定的,最核心的方法就是ES5的Object.defineProperty()方法,使用getter/setter监测对数据的操作。
它的操作呢大致可以分为三步:
第一步:利用get实现一个数据监听器,对数据对象的所有属性进行监听。
第二步:实现一个指令解析器,对所有元素的节点指令进行解析。
第三步:实现一个观察者,能够订阅并收到每个属性变化的通知,然后执行相应的回调函数,从而更新视图。
4. Angular和vue的区别
相同点:
- 都支持指令:内置指令和自定义指令。
- 都支持过滤器:内置过滤器和自定义过滤器。
- 都支持双向数据绑定。
- 都不支持低端浏览器。
不同点:
实现双向数据绑定的原理不同:Angular实现双向数据绑定主要是依赖于脏值监测,也就是存储旧数值,然后在检测时把当前时刻的新值和旧值进行比对来达到是否更新视图的效果;而在vue中,采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
vue需要提供一个el对象进行实例化,后续的所有作用范围也是在el对象之下,而angular而是整个html页面。一个页面,可以有多个vue实例,而angular好像不是这么玩的。
后语
知识产权无价,支持原创。
内容也会同步更新自我的个人博客:https://lindaidai.wang
参考文章: