1. 1. 1.js中 ?? 和 || 的区别?
  2. 2. 2.URI和URL的区别
  3. 3. 3.Http中的301,302,303,307,308相应状态码
  4. 4. 4.link和@import引入css的区别?
  5. 5. 5.圣杯布局和双飞翼布局
  6. 6. 6.用递归算法实现,数组长度为5且元素的随机整数数在2-32间不重复的值
  7. 7. 7. html的元素有哪些(包含h5)?
  8. 8. 8.css3新特效有哪些?
  9. 9. 9.写一个方法去掉字符串中的空格,要求传入不同的类型分别能去掉前、后、前后、中间的空格
  10. 10. 10.HTML全局属性(global attribute)有哪些?
  11. 11. 11.页面上隐藏元素的方法有哪些?
  12. 12. 12.去除字符串中最后一个指定的字符
  13. 13. 13.HTML5离线存储方式有哪些,怎么使用,原理是什么?
  14. 14. 14.css选择器有哪些?哪些属性可继承?
  15. 15. 15.写一个方法把下划线命名转成大驼峰命名
  16. 16. 16.简述超链接target属性的取值和作用
  17. 17. 17.CSS3新增伪类有哪些并简要描述?
  18. 18. 18.写一个把字符串大小写切换的方法?
  19. 19. 19.label都有哪些作用?
  20. 20. 20. 用css创建一个三角形,并简述原理
  21. 21. 21.写一个去除制表符和换行符的方法
  22. 22. 22.iframe框架都有哪些优缺点?
  23. 23. 23.简述你对BFC规范的理解
  24. 24. 24.统计某一字符或字符串在另一个字符串中出现的次数
  25. 25. 25.清除浮动的方式有哪些及优缺点
  26. 26. 26.写一个加密字符串的方法
  27. 27. 27.浏览器内多个标签页之间的通信方式有哪些?
  28. 28. 28.简述下你理解的优雅降级和渐进增强
  29. 29. 29.写一个判断数据类型的方法
  30. 30. 30.viewport常见设置都有哪些?
  31. 31. 31.对比下px、em、rem有什么不同?
  32. 32. 32.简要描述下什么是回调函数并写一个例子出来
  33. 33. 33.你对标签语义化的理解是什么?
  34. 34. 34.css常用的布局方式有哪些?
  35. 35. 35.简要描述下JS有哪些内置的对象
  36. 36. 36.常见的浏览器内核都有哪些?并介绍下你对内核的理解
  37. 37. 37.说说你对css盒子模型的理解
  38. 38. 38.写一个获取当前url查询字符串中的参数的方法
  39. 39. 39.网页应用从服务器主动推送到客户端有那些方式?
  40. 40. 40.html5中的form怎么关闭自动完成?
  41. 41. 41.::before和:after中单冒号和双冒号的区别是什么,这两个伪元素有什么作用?
  42. 42. 43.http都有哪些状态码?
  43. 43. 44.为什么HTML5只需要写就可以?
  44. 44. 45.什么是闭包?优缺点分别是什么?
  45. 45. 46.title与h1的区别、b与strong的区别、i与em的区别?
  46. 46. 47.style标签写在body前和body后的区别是什么?
  47. 47. 48.写一个数组去重的方法(支持多维数组)
  48. 48. 49.元素的alt和title有什么区别?
  49. 49. 50.请描述margin边界叠加是什么及解决方案
  50. 50. 51.返回到顶部的方法有哪些?
  51. 51. 52.解释下 CSS sprites的原理和优缺点分别是什么?
  52. 52. 53.typeof(‘abc’)和typeof ‘abc’都是string, 那么typeof是操作符还是函数?
  53. 53. 54.说说你对SVN和GIT的理解和区别
  54. 54. 55.怎样在页面上实现一个圆形的可点击区域?
  55. 55. 56.什么是FOUC?你是如何避免FOUC的?
  56. 56. 57.你理解的”use strict”;是什么?使用它有什么优缺点?
  57. 57. 58.可替换元素
  58. 58. 59.css重的content属性有什么作用?有哪些场景可以用到?
  59. 59. 60.“attribute”和“property”有什么不同?
  60. 60. 61.请描述HTML元素的显示优先级
  61. 61. 62.要让Chrome支持小于12px的文字怎么做?
  62. 62. 63.身份证号校验的方法
  63. 63. 64.谈谈你对input元素中readonly和disabled属性的理解
  64. 64. 65.说说你对line-height是如何理解的
  65. 65. 66.写一个方法验证是否是中文?
  66. 66. 67.来说说你对重绘和重排的理解,以及如何优化?
  67. 67. 68.js放在html的<body>和<head>有什么区别?
  68. 68. 69.说说浏览器解析CSS选择器的过程?
  69. 69. 70.你对new 运算符的理解是什么?手动实现一个new方法
  70. 70. 71.关于<form>标签的enctype属性你有哪些了解?
  71. 71. 72.说说CSS的优先级是如何计算的?
  72. 72. 73.0.1 + 0.2、0.1 + 0.3和0.1 * 0.2分别等于多少?并解释下为什么?
  73. 73. 74.对属性data-的理解
  74. 74. 75.如何快速让一个数组乱序
  75. 75. 76.请说说<script>、<script async>和<script defer>的区别?
  76. 76. 77.写一个判断设备来源的方法
  77. 77. 78.解释下你对GBK和UTF-8的理解?并说说页面上产生乱码的可能原因
  78. 78. 79.说说你对z-index的理解
  79. 79. 80.说说bind、call、apply的区别?并手写实现一个bind的方法
  80. 80. 81.git branch
  81. 81. 82.说说你对影子(Shadow)DOM的了解
  82. 82. 83.怎样修改chrome记住密码后自动填充表单的黄色背景?
  83. 83. 84.说说你对arguments的理解,它是数组吗?
  84. 84. 85.说说你对<meta>标签的理解
  85. 85. 87.rgba()和opacity这两个的透明效果有什么区别呢?
  86. 86. 88.解释代码意思
  87. 87. 89.在浏览器中输入url到页面显示出来的过程发生了什么?
  88. 88. 90.写一个获取数组的最大值、最小值的方法?
  89. 89. 91.网页上的验证码是为了解决什么问题?说说你了解的验证码种类有哪些
  90. 90. 92.描述下你所了解的图片格式及使用场景
  91. 91. 93.写一个方法判断字符串是否为回文字符串
  92. 92. 94.CRLF是什么?
  93. 93. 95.DOM和BOM有什么区别?
  94. 94. 96.让网页的字体变得清晰,变细用CSS怎么做?
  95. 95. 97.写一个方法把0和1互转(0置1,1置0)
  96. 96. 98.line-height3种设置方式的区别
  97. 97. 99.造成内存泄漏的操作有哪些?
  98. 98. 100.html和html5有什么区别呢?
  99. 99. 102.说说你对this的理解
  100. 100. 103.Standards模式和Quirks模式有什么区别?
  101. 101. 104.浏览器是怎样判断元素是否和某个CSS选择器匹配?
  102. 102. 105.用一个div模拟textarea的实现
  103. 103. 106.使用flex实现三栏布局,两边固定,中间自适应
  104. 104. 107.请你解释一个为什么10.toFixed(10)会报错?
  105. 105. 108.谈一谈你知道的前端性能优化方案有哪些?
  106. 106. 109.HTML和XHTM有什么不同?
  107. 107. 110.写出主流浏览器内核私有属性的css前缀
  108. 108. 111.手写幻灯片效果
  109. 109. 112.对于前端安全,你了解多少?说说你对XSS和CSRF的理解
    1. 109.1. Cross-site scripting 跨站脚本攻击XSS
    2. 109.2. 跨站请求伪造CSRF
  110. 110. 113.html5哪些标签可以优化SEO?
  111. 111. 114.不使用border画出1px高的线,在不同浏览器的标准和怪异模式下都能保持效果一样
  112. 112. 115.找到字符串中最长的单词,并返回它的长度
  113. 113. 116.说说你对cookie和session的理解
    1. 113.1. 什么是Cookie?
    2. 113.2. 什么是Session?
    3. 113.3. cookie和session的区别?
  114. 114. 117.实现单行文本居中和多行文本左对齐并超出显示”…”
  115. 115. 118.说说你对eval的理解
  116. 116. 119.写出你知道的CSS水平和垂直居中的方法
  117. 117. 120.说说你对模块化的理解
  118. 118. 121.公钥加密和私钥加密是什么?
  119. 119. 122.html5都有哪些新的特性?移除了哪些元素?
  120. 120. 123.怎么才能让图文不可复制?
  121. 121. 124.为什么会有跨域问题?怎么解决跨域?
  122. 122. 125.怎么让英文单词的首字母大写?
  123. 123. 126.说说你对IIFE的理解
  124. 124. 127.window对象和document对象有什么区别?
    1. 124.1. window对象
    2. 124.2. document对象
  125. 125. 128.重置(初始化)css的作用是什么?
  126. 126. 129.如何让元素固定在页面底部?有哪些比较好的实践?
  127. 127. 130.span与span之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
  128. 128. 131.说说video标签中预加载视频用到的属性是什么?
  129. 129. 132.手写一个满屏品字布局的方案
  130. 130. 133.深度克隆对象的方法有哪些?
  131. 131. 134.使用js库的download来下载资源
  132. 132. 135.JavaScript 实现复制功能
  133. 133. 136.http,https,http2的了解
  134. 134. 137.xml和html有什么区别?
  135. 135. 138.写出几种创建对象的方式,并说说他们的区别是什么?
  136. 136. 139.页面中怎么嵌入Flash?有哪些方法?写出来
  137. 137. 140.说说你对媒体查询的理解
  138. 138. 141.写一个使两个整数进行交换的方法(不能使用临时变量)
  139. 139. 142.HTML5如何使用音频和视频?
  140. 140. 143.请说说你对事件冒泡机制的理解?
  141. 141. 144.说说你对WEB标准和W3C的理解与认识?
  142. 142. 145.你知道全屏滚动的原理是什么吗?它用到了CSS的哪些属性?
  143. 143. 146.你对事件循环有了解吗?说说看
  144. 144. 147.说说你对target=”_blank”的理解?有啥安全性问题?如何防范?
  145. 145. 148.写个还剩下多少天过年的倒计时
  146. 146. 149.列举CSS优化、提高性能的方法
  147. 147. 150.请写出一个函数求出N的阶乘(即N!)
  148. 148. 151.如何实现换肤功能?
  149. 149. 152.如何取消promise
  150. 150. 153.如何捕获 setTimeout 异常
  151. 151. 154.fetch 和 ajax 区别
  152. 152. 155.form表单是怎么上传文件的?你了解它的原理吗?
  153. 153. 156.字符串相连有哪些方式?哪种最好?为什么?
  154. 154. 157.说说你对CDN的理解,使用过程中有没有遇到过问题?
  155. 155. 158.web workers有用过吗?能帮我们解决哪些问题?
  156. 156. 159.怎么使用自定义字体?有什么注意事项?
  157. 157. 160.window的load 和ready有什么区别?
  158. 158. 161.你有了解HTML5的地理定位吗?怎么使用?
  159. 159. 162.css3的:nth-child和:nth-of-type的区别是什么?
  160. 160. 163.写一个函数找出给定数组中的最大差值
  161. 161. 164.HTML5中新添加的表单属性有哪些?
  162. 162. 165.写出4个使用this的典型例子
  163. 163. 166.网站被劫持植入广告该怎么办?如何防止?
  164. 164. 167.渐进式渲染是什么?
  165. 165. 168.JSONP的原理是什么?解决什么问题?
  166. 166. 169.说说你对域名收敛和域名发散的理解?分别在什么场景下使用?
  167. 167. 170.有使用过vue吗?说说你对vue的理解
  168. 168. 171.什么是双向绑定?原理是什么?
  169. 169. 172.什么是虚拟DOM?
  170. 170. 173.vue组件之间的通信都有哪些?
  171. 171. 174.请描述下vue的生命周期是什么?
  172. 172. 175.说下你对指令的理解?
  173. 173. 176.v-show和v-if有什么区别?使用场景分别是什么?
  174. 174. 177.说说你对MVC、MVP、MVVM模式的理解
  175. 175. 178.inline、block、inline-block这三个属性值有什么区别?
  176. 176. 179.写一个方法,使得sum(x)(y)和sum(x,y)返回的结果相同
  177. 177. 180.说你对浏览器的关键渲染路径(CRP)的理解
  178. 178. 181.box-sizing常用的属性有哪些?分别有什么作用?
  179. 179. 182.请说下你对__proto__和prototype的理解
  180. 180. 183.写一个格式化金额的方法
  181. 181. 184.src、href、link的区别是什么?
  182. 182. 185.请实现一个flattenDeep函数,把多维数组扁平化
  183. 183. 186.写一个方法获取图片的原始宽高
  184. 184. 187.知道IPV6是什么吗?说说它和IPV4的区别是什么?
  185. 185. 188.怎么使css样式只在当前组件中生效?
  186. 186. 189.keep-alive
  187. 187. 190.v-for循环中key有什么作用?
  188. 188. 191.vue如何监听键盘事件?
  189. 189. 192.watch和computed有什么区别?
  190. 190. 193.watch监听
  191. 191. 194.为什么data属性必须声明为返回一个初始数据对应的函数呢?
  192. 192. 195.$nextTick有什么作用?
  193. 193. 196.分别说说vue能监听到数组或对象变化的场景,还有哪些场景是监听不到的?无法监听时有什么解决方案?
  194. 194. 197.v-if和v-for的优先级是什么?如果这两个同时出现时,那应该怎么优化才能得到更好的性能?
  195. 195. 198.vue实例挂载的过程是什么?
  196. 196. 199.说说你对选项el,template,render的理解
  197. 197. 200.说说你对同构和SSR的理解
  198. 198. 201.什么是html的字符实体?版权符号代码怎么写?
  199. 199. 202.说说position的absolute和fixed共同与不同点分别是什么?
  200. 200. 203.举例子说明javascript的变量声明提升和函数声明提升
  201. 201. 204.组件与插件的区别
  202. 202. 205.动态给vue的data添加一个新的属性时会发生什么?怎样解决?
  203. 203. 206.删除数组用delete和Vue.delete有什么区别?
  204. 204. 207.说说你对vue的mixin的理解,有什么应用场景?
  205. 205. 208.v-model是什么?有什么用呢?
  206. 206. 209.vue常用的修饰符有哪些?列举并说明
  207. 207. 210.v-on可以绑定多个方法吗?
  208. 208. 211.说说你对vue的template编译的理解?
  209. 209. 212.写出html提供的几种空格实体(5种以上)
  210. 210. 213.举例说明css中颜色的表示方法有几种
  211. 211. 214.如何让(a==1 && a==2 && a==3)的值为true,把”==”换成”===”后还能为true吗?
  212. 212. 215
  213. 213. 216
  214. 214. 217
  215. 215. 218
  216. 216. 219
  217. 217. 220
  218. 218. 221
  219. 219. 222
  220. 220. 223
  221. 221. 224
  222. 222. 225
  223. 223. 226
  224. 224. 227
  225. 225. 228
  226. 226. 229
  227. 227. 230
  228. 228. 231
  229. 229. 232

每日一题

1.js中 ?? 和 || 的区别?

1
2
value1  ??  value2
value1 || value2

相同点:

用法相同,都是符号前后是值,中间是符号。根据前面的值判断返回value1还是value2。

不同点:

1.使用??时,只有当value1的值为null或undefined时才返回value2,否则返回value1
2.使用||时,value1会转换为bool值,为true时返回value1, false时返回value2

??更适合不知道变量是否有值时使用

2.URI和URL的区别

1.URI:统一资源标识符(Uniform Resource Identifier,URI)是一个标识某个互联网资源的字符串。表示Web上可用的每种资源-html文档、图像、视频片段、程序等由一个URI进行标识。

URI格式:[协议名]://[用户名]:[密码]@[服务器地址]:[端口号]/[路径]?[查询字符串]#[片段id]

2.URL:统一资源定位符(Uniform Resource Locator),采用URL可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。URL是URI概念的一种实现方式。

URL下列三部分组成:第一部分是协议(或称为服务方式);第二部分是存有该资源的主机IP地址(有时也包括端口号);第三部分是主机资源的具体地址。

3.URI和URL之间的区别

URI和URL都定义了资源是什么,但URL还定义了该如何访问资源。URL是一种具体的URI,它是URI的一个子集,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI 是一种语义上的抽象概念,可以是绝对的,也可以是相对的,而URL则必须提供足够的信息来定位,是绝对的。

3.Http中的301,302,303,307,308相应状态码

1、301 Move Permanently

表明资源永久的移动到了一个新的URI,任何未来对这个资源的引用都应该使用新的URI

2、302 Found

表明资源临时的移动到了一个新的URI,由于重定向是临时的,所以之后的请求还应该使用原本的URI
服务器会在响应头的Location字段放上这个不同的URI,浏览器可以使用这个URI进行自动重定向
注:由于历史原因,用户代理可能会在重定向后把请求的post改为get方法。

3、303 See Other

303 状态码表示服务器要将浏览器重定向到另一个资源,这个资源的 URI 会被写在响应 Header 的 Location 字段。从语义上讲,重定向到的资源并不是你所请求的资源,而是对你所请求资源的一些描述。
303 常用于将 POST 请求重定向到 GET 请求,比如你上传了一份个人信息,服务器发回一个 303 响应,将你导向一个“上传成功”页面。
不管原请求是什么方法,重定向请求的方法都是 GET(或 HEAD,不常用)

4、307 Temporary Redirect

307 的定义实际上和 302 是一致的,唯一的区别在于,307 状态码不允许浏览器将原本为 POST 的请求重定向到 GET 请求上

5、308 Permanent Redirect

308 的定义实际上和 301 是一致的,唯一的区别在于,308 状态码不允许浏览器将原本为 POST 的请求重定向到 GET 请求上

6、302和303、307的关系

302允许各种各样的重定向,一般情况下都会重定向到get,但不能确保post重定向到post
303只允许任意请求重定向到get
307和302一样,但不允许post到get的重定向

4.link和@import引入css的区别?

1、link是HTML的的标签,除了链接样式表还可以设置RSS,rel等属性,@import只能加载css
2、link会在页面加载时同时加载,@import会在页面加载完成后再加载
3、link无兼容性问题,@import是在css2.1提出,低版本浏览器不支持
4、可以通过js操作dom将link样式表插入文档改变样式,@import不支持

5.圣杯布局和双飞翼布局

三栏布局,两边固宽

圣杯布局:三栏利用float和负margin并列,利用父容器的padding给两边空出空间

1
2
3
4
5
6
7
8
<div class="container">
<div class="main">
<p>圣杯布局</p>
<p>hahahhaha</p>
</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
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
* {
padding: 0;
margin: 0;
}
.container {
padding: 0 60px 0 30px;
height: 150px;

}
.main {
float: left;
width: 100%;
height: 150px;
background-color: aquamarine;
}
.left {
float: left;
width: 30px;
height: 100px;
background-color: darkkhaki;
margin-left: calc(-100% - 30px);
}
.right {
float: left;
width: 60px;
height: 100px;
background-color: firebrick;
/* margin-left: -60px;
position: relative;
left: 60px; */
margin-right: -60px;
}

双飞翼布局:三栏利用float和负margin并列,中间栏加一层容器,利用margin给两栏空出空间

1
2
3
4
5
6
7
8
9
10
11
<div class="container1">
<div class="main1">
<div class="content">
<p>双飞翼布局</p>
<p>hahahhaha</p>
</div>
</div>
<div class="left1">left1</div>
<div class="right1">right1</div>
</div>
</div>
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
* {
padding: 0;
margin: 0;
}
.container1 {
width: 100%;
height: 150px;
border-top: 1px solid;
}
.container1 .main1 {
float: left;
width: 100%;
}
.content {
height: 150px;
background-color: aquamarine;
margin: 0 60px 0 30px;
}
.left1 {
float: left;
width: 30px;
height: 100px;
margin-left: -100%;
background-color: darkkhaki;
}
.right1 {
float: left;
width: 60px;
height: 100px;
margin-left: -60px;
background-color: firebrick;
}

flex布局也可实现三栏布局

1
2
3
4
5
6
7
<div class="container2">
<div class="left2">left2</div>
<div class="main2">
flex
</div>
<div class="right2">right2</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.container2 {
width: 100%;
height: 150px;
border-top: 1px solid;
display: flex;
flex: 1 1 auto;
}
.main2 {
height: 150px;
background-color: aquamarine;
width: 100%;
}
.left2 {
width: 30px;
height: 100px;
background-color: darkkhaki;
}
.right2 {
width: 60px;
height: 100px;
background-color: firebrick;
flex-shrink: 0;
}

image

圣杯和双飞翼中间栏放首位可保证首先渲染,但是中间栏宽度小于左栏会页面错乱

6.用递归算法实现,数组长度为5且元素的随机整数数在2-32间不重复的值

1
2
3
4
5
6
7
8
function randomArr5(arr) {
arr = arr || []
if (arr.length === 5) return arr
let num = 2 + Math.floor(Math.random() * 31)
if (!arr.includes(num)) arr.push(num)
return randomArr5(arr)
}
randomArr5() // [30, 19, 28, 3, 11]

随机数2-32,数组长度5且元素不重复,递归

7. html的元素有哪些(包含h5)?

块元素:
html、body、head、header、nav、section、main、aside、footer页面结构
article、h1-h6、p 文章
div
ul、ol、li、dl、dt、dd 列表
table、tr、td、thead、tbody表格
form表单

行内元素:
a(inline)
span(inline)
img(inline)
strong(inline)、i(inline)、em(inline)文本内容
label(inline)
canvas(inline)
audio(inline,无controls值为none)、video(inline)媒体

行内块元素:
input(inline-block)
select(inline-block)
button(inline-block)

8.css3新特效有哪些?

1.边框属性
border-image(边框图片)、border-radius(边框圆角)、box-shadow(边框阴影)

2.背景属性
backgrou-image: url(),url();多背景图片
background-clip: border-box/padding-box/content-box;背景图片绘制区域,默认border-box图片被剪裁到边框盒
background-origin: padding-box/border-box/content-box;图片相对于什么位置定位,默认值padding-box
background-size: auto/cover/contain/length/%;景图像的尺寸

3.文本属性
text-shadow文本阴影
word-wrap: normal/break-word; 允许长单词或URL换行
word-break: normal/keep-all(只允许在半角空格或连字符处换行)/break-all(允许在单词内换行)

4.transform属性
2D或3D变换,允许元素进行旋转、移动、缩放、倾斜
transform:

  • none:不进行任何转换
  • matrix(n,n,n,n,n,n):定义2D转换,使用六个值的矩阵
  • matrix3d(n,…n):定义3D转换,使用16个值的矩阵
  • translate(x,y):定义2D转换
  • translate3d(x,y,z): 定义3D转换
  • translateX(x): 定义转换,只是用 X 轴的值。
  • translateY(y): 定义转换,只是用 Y 轴的值。
  • translateZ(z): 定义转换,只是用 Z 轴的值。
  • scale(x,y): 定义2D缩放转换
  • scale3d(x,y,z): 定义3D缩放转换
  • scaleX(x): 通过设置 X 轴的值来定义缩放转换。
  • scaleY(y): 通过设置 Y 轴的值来定义缩放转换。
  • scaleZ(z): 通过设置 Z 轴的值来定义缩放转换。
  • rotate(angle): 定义 2D 旋转,在参数中规定角度
  • rotate(x,y,angle): 定义3D旋转
  • rotateX(angle): 定义沿着 X 轴的 3D 旋转
  • rotatezY(angle): 定义沿着 Y 轴的 3D 旋转
  • rotateZ(angle): 定义沿着 Z 轴的 3D 旋转
  • skew(x-angle,y-angle): 定义沿着x轴和y轴倾斜转换
  • skewX(angle): 定义沿着X轴的2D倾斜转换
  • skewY(angle):定义沿着y轴的2D倾斜转换

5.过渡动画transition
transition: property duration timing-function delay;

1
2
3
4
transion: width 2s;
div:hover {
width: 30px;
}

6.animation动画

1
2
3
4
5
6
7
8
9
10
11
div{
animation: myFirst 5s;
}
@keyframes myFirst{
from {
background-color: red;
}
to {
background-color: yellow;
}
}

7.弹性盒子flexbox

8.多媒体查询@media

9.渐变
linear-gradient 线性渐变
radial-gradient 径向渐变

9.写一个方法去掉字符串中的空格,要求传入不同的类型分别能去掉前、后、前后、中间的空格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function trim(str, type = 'all') {
const Type = {
left: /^\s+/g,
right: /\s+$/g,
all: /\s+/g,
both: /^\s+|\s+$/g
}
if (type === 'center') {
let leftStr = str.match(/^\s+/g)[0]
let rightStr = str.match(/\s+$/g)[0]
return leftStr + str.replace(/\s+/g,'') + rightStr
}
return str.replace(Type[type], '')
}
let strs = ' 12 3 4 56 '
trim(strs) // all '123456'
trim(strs, 'left') // left '12 3 4 56 '
trim(strs, 'right') // right ' 12 3 4 56'
trim(strs, 'both') // both '12 3 4 56'
trim(strs, 'center') // center ' 123456 '

10.HTML全局属性(global attribute)有哪些?

全局属性是所有HTML元素共有的属性,它们可以用于所有元素,即使属性对某些元素不起作用。

1.accesskey提供了为当前元素生成键盘快捷键的提示。

1
<input type="text" accesskey="n">

windows系统使用alt+n快捷键可快速选择对应元素
mac系统使用crtl+option+n快捷键

2.autocapitalize控制用户输入如何自动大写

3.class

4.contenteditable元素是否可以被编辑

5.data-* 自定义数据属性

6.dir指示元素中文本方向的枚举属性(ltr、rtl、auto)

7.draggable,枚举属性,指示是否可以使用Drog盒Drop API拖动元素

8.hidden隐藏元素

9.id唯一标识符

10.lang:定义元素的语言,xml:lang优先于它

11.spellcheck:是否启动拼写和语法检查

12.slot插槽,具有slot属性的元素被分配给由<slot>元素创建的沟槽,其name属性的值与slot属性的值匹配。

13.style内联样式

14.tabindex规定元素的tab键控制次序

15.title

16.translate页面本地化时是否转换元素的属性值及其Text 节点子节点的值

17.还有事件处理程序属性:onabort, onautocomplete, onautocompleteerror, onblur, oncancel, oncanplay, oncanplaythrough, onchange, onclick, onclose, oncontextmenu, oncuechange, ondblclick, ondrag, ondragend, ondragenter, ondragexit, ondragleave, ondragover, ondragstart, ondrop, ondurationchange, onemptied, onended, onerror, onfocus, oninput, oninvalid, onkeydown, onkeypress, onkeyup, onload, onloadeddata, onloadedmetadata, onloadstart, onmousedown, onmouseenter, onmouseleave, onmousemove, onmouseout, onmouseover, onmouseup, onmousewheel, onpause, onplay, onplaying, onprogress, onratechange, onreset, onresize, onscroll, onseeked, onseeking, onselect, onshow, onsort, onstalled, onsubmit, onsuspend, ontimeupdate, ontoggle, onvolumechange, onwaiting

11.页面上隐藏元素的方法有哪些?

1.给元素设置hidden属性,不占位
2.display:none;不占位
6.width:0;height:0;transform:scale(0);不占位;有些元素有border值依然会占位,有宽高
3.visibility:hidden;占位
4.opacity: 0;/filter: opacity(0);占位
5.filter: opacity(0);占位
7.width:0;height:0;overflow:hidden;不占位;有些元素有border值依然会占位,有宽高
8.position:absolute;left/margin-left:-1000%;脱离文档流不占位
9.position:absolute;z-index: -1;脱离文档流不占位,但是后面元素只是盖在该元素上面,如果后面元素比该元素小只会隐藏一部分
10.font-size:0;不占位仅对文本内容有效

12.去除字符串中最后一个指定的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function delChar(str, char){
if(typeof str !== 'string') {
console.log('not string')
return
} else {
let lastIndex = str.lastIndexOf(char)
if (lastIndex != -1) {
return str.substring(0, lastIndex) + str.substring(lastIndex + char.length)
}
console.log('not find ',char)
}
}
delChar('abniok9866dasd%fnad#fv%vvv', 'd#') // 'abniok9866dasd%fnafv%vvv'

// 正则
function delLastAnyChar(str, char) {
// [^]表示任意字符 .查找单个字符除换行和行结束符,单行模式下,[^]就是.,但是多行模式下,[^]可以匹配到\n
// [^]*表示任意长度字符 ()表示元组,$1表示匹配到的第一个()内容
let reg = new Reg(`(^[^]*)(${char})([^]*$)`)
return str.replace(reg, '$1$3')
}
delLastAnyChar('acdabdbde', 'bd') // acdabde

13.HTML5离线存储方式有哪些,怎么使用,原理是什么?

浏览器检测是否在线 navigator.onLine 返回true/false

查看HTML5存储方式

14.css选择器有哪些?哪些属性可继承?

选择器:

  • 通用选择器 * 匹配文档内所有元素
  • 元素选择其 elementName
  • 类选择器 .className
  • id选择器 #idName
  • 组合选择器
    • element,element h1,h2 {}
    • element element body h1 {} 嵌套选择器或后代选择器
    • element > element div > p, ul > li
    • element + element div + p 相邻同级选择器
    • element1~element2 p~ul p和ul具有相同的父元素, ul在p后面,不必紧跟
  • 属性选择器
    • [attr] a[class] a[target]
    • [attr=value] p[class=”title”]
    • [attr~=value] p[class~=”test”] 包含指定属性值的元素,基于属性值空格分隔开的属性(“test a”包含,”test_a”不包含)
    • [attr|=value] [lang|=en] 用于选择指定属性具有指定值开始的元素(en-us,en)
    • [attr^=value] [class^=”test”] 匹配元素属性值带指定的值开始的元素(test,test_a)
    • [attr$=value] [class$=”test”] 匹配元素属性值带指定的值结尾的元素(test, a_test)
    • [attr*=value] [class*=”test”] 匹配元素属性值包含指定值的元素(test,a_test,test_a)
  • 伪类选择器
    :active,:after,:before,:checked,:disabled,:empty,:enabled,:first-child,:first-letter,:first-of-type,:focus,:hover,:in-range,:invalid,:lang(),:last-child,:last-of-type,:link,:not,:nth-child(),:nth-last-child(),:nth-last-of-type(),:nth-of-type(),:only-child,:optional,:out-of-range,:read-only,:read-write,:required,:root,::selection,:target,:valid,:visited

可继承的属性:

  • 字体系列属性
    font-family,font-weight,font-size,font-style,font-variant,font-stretch,font-size-adjust
  • 文本系列属性
    text-align, line-height, word-spacing, letter-spacing, text-transform, direction, color
  • 元素可见性
    visibility, opacity
  • 表格布局属性
  • 列表属性
  • 光标属性 cursor

15.写一个方法把下划线命名转成大驼峰命名

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
function toCamelCase(str) {
if (str.split('_').length === 1) return
let arr = str.split('_')
let res = ''
arr.forEach(item => {
res = res + item.substr(0,1).toUpperCase() + item.substr(1)
})
return res
}
toCamelCase('a_project_name_title') // 'AProjectNameTitle'

// 正则
function toCamelCase(str) {
if (!str.length) return
str = str.replace(/(_)(\w)/g, (match,$1,$2) => {
return $2.toUpperCase()
})
return str.substr(0,1).toUpperCase() + str.substr(1)
}
toCamelCase('test_project_container') // TestProjectContainer

function toCamelCase(str){
return str.replace(/(^|_)(\w)/g,(m,$1,$2)=>$2.toUpperCase());
}
toCamelCase('test_project_container') // TestProjectContainer

16.简述超链接target属性的取值和作用

target值 作用
_blank 在新的窗口打开被链接的文档
_self 默认,在相同框架中打开被链接的文档
_parent 在父框架集中打开被链接的文档
_top 在整个窗口中(最顶层框架集)打开被链接的文档
framename 在指定的框架中打开被链接的文档

17.CSS3新增伪类有哪些并简要描述?

新增伪类 作用
:first-of-type p:first-of-type 选择的每个 p 元素是其父元素的第一个 p 元素
:last-of-type p:last-of-type 匹配元素其父级是特定类型的最后一个子元素
:only-of-type p:only-of-type 匹配p的父元素的唯一子元素p
:only-child p:only-child 匹配p元素的父元素唯一的子元素p元素
:nth-child(n) p:nth-child(2) 选择所有 p 元素的父元素的第二个子元素(不是第二个子p元素)
:enabled input:enabled 选择所有启用的元素
:disabled input:disabled 选择所有禁用的元素
:checked input:checked 选择所有选中的元素
:empty p:empty 选择所有没有子元素的p元素
:focus input:focus 选择元素输入后具有焦点
:root 选择文档的根元素

18.写一个把字符串大小写切换的方法?

例:aBcdEFg –> AbCDefG

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function caseConvert(str) {
let res = ''
for(let i of str) {
res+= i.toLowerCase() === i ? i.toUpperCase() : i.toLowerCase()
}
return res
}
caseConvert('aBcdEfGD') // AbCDeFgd
// 正则
function caseConvert(str){
return str.replace(/([a-z]*)([A-Z]*)/g, (m, s1, s2)=>{
return `${s1.toUpperCase()}${s2.toLowerCase()}`
})
}
caseConvert('例:aBcdEFg') // AbCDefG

19.label都有哪些作用?

1.关联表单控件,扩大点选范围
2.关联表单控件,聚焦到关联输入框
3.为input元素定义的标记
4.利用label”模拟”button来解决不同浏览器原生button样式不同的问题

20. 用css创建一个三角形,并简述原理

当width和height为0时,设置border会将其分割成45度的等腰三角形,设置上下左右border宽度或颜色透明即可得到三角形

1
2
3
4
5
6
7
width: 0;
height: 0;
display: inline-block;
border: 10px solid red;
border-bottom-color: transparent;
border-left-color: transparent;
border-right-color: transparent;

若要获取左直角等三角形,只需修改上下左右边框颜色透明

21.写一个去除制表符和换行符的方法

1
2
3
4
function removeTab(str) {
return str.replace(/\n|\t/g, '')
}
removeTab('h\taha\nfdals') // hahafdals

22.iframe框架都有哪些优缺点?

缺点:
1.会产生多个页面,不容易管理
2.多iframe的页面会增加服务器的http请求
3.每个iframe对应一个页面,其多余的css和js文件的载入会增加请求的开销
4.window.onload事件会在所有的iframe加载完成后才触发,会造成页面阻塞
5.如果iframe内有滚动条,会影响用户的使用体验
6.代码复杂,无法被一些搜索引擎索引到,对搜索引擎不友好

优点:
1.投放广告之类的飘窗无疑是最好的选择
2.重载时只需要重载页面中的一个iframe,不需要重载整个页面
3.可以实现异步刷新,单个iframe刷新不影响整个窗口的刷新(在FormData无法使用时,可以实现无刷新上传)
4.可以实现跨域,每个iframe的源可以不相同(方便引入第三方内容)
5.多页面应用时,对于共同的header,footer可以使用iframe加载,拆分代码(方便制作导航栏)
6.技术容易掌握。可主要应用于不需要搜索引擎来搜索的页面

23.简述你对BFC规范的理解

查看css-BFC块级格式化上下文

24.统计某一字符或字符串在另一个字符串中出现的次数

1
2
3
4
5
6
7
8
9
10
11
12
function countTarget(str, target) {
let count = 0
while(target.match(str)) {
target = target.replace(str, " ")
count++
}
return count
}
function countTarget(str, target) {
return target.match(new RegExp(str, 'g')).length
}
countTarget("ad", "dasdlajdadeorwad") // 2

25.清除浮动的方式有哪些及优缺点

1.触发父元素BFC
如给父元素设置overflow:hidden,特别注意的是:在IE6中还需要触发hasLayout,例如给父元素设置zoom:1

原理是触发父级BFC后,父元素在计算高度时,浮动的子元素也会参与计算

优点
代码简洁

缺点
设置overflow:hidden容易造成不会自动换行导致超出的尺寸被隐藏掉,无法显示要溢出的元素

2.给父元素设置高度
优点
代码简洁

缺点
不够灵活,只适用于高度固定的布局

3.添加额外标签
在最后一个浮动元素的后面新加一个标签如

,并在其CSS样式中设置clear: both
优点
代码简洁,兼容性好

缺点
额外增加无语义html元素,代码语义化差,后期维护成本大

4.使用after伪元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.clearfix::after {
content: ".";
display: block;
height: 0;
line-height: 0;
clear: both;
visibility:hidden;
font-size: 0;
}

.clearfix {
// 注意此处是为了兼容IE6和IE7浏览器,即触发hasLayoutcs
zoom: 1;
}

优点
符合闭合浮动思想,结构语义化正确

缺点
代码量多,因为IE6-7下不支持after伪元素,需要额外写 zoom:1来 触发hasLayout

26.写一个加密字符串的方法

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
// 1.base-64加密
let tempStr = "hello world"
let tempPass = window.btoa(tempStr) // 'aGVsbG8gd29ybGQ='
// base-64解密
console.log(window.atob(tempPass)) // "hello world"

// 2.
function encode (str) {
return btoa(encodeURIComponent(str));
}

function decode (str) {
return decodeURIComponent(atob(str));
}
encode('hello world') // 'aGVsbG8lMjB3b3JsZA=='
decode('aGVsbG8lMjB3b3JsZA==') //'hello world'

// 3.
function encodeStr(str, padding) {
return !str
? str
: str.split('')
.map(s => {
return String.fromCharCode(s.charCodeAt() + padding)
})
.join('')
}
function decodeStr(str, padding) {
return !str
? str
: str.split('')
.map(s => {
return String.fromCharCode(s.charCodeAt() - padding)
})
.join('')
}
encodeStr('hello world!', 10) // 'rovvy*\x81y|vn+'
decodeStr('rovvy*\x81y|vn+', 10) // 'hello world!'

27.浏览器内多个标签页之间的通信方式有哪些?

1.websocket 可跨域
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议

2.postMessage 可跨域

1
2
window.addEventListener('message', function(){}) // 接收消息
window.parent.postMessage('msg', '*') // 发送消息 window.frames[0].postMessage Window.frames +索引值(命名或数字)

3.SharedWorker
作为浏览器的一个新特性,可以提供一个额外的线程来执行一些js代码(真正的多线程),并且不会影响到浏览器用户界面,但是不能DOM操作

4.Server-Sent Events
HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新。
Server-Sent 事件指的是网页自动获取来自服务器的更新。

5.localStorage(可以添加事件监听)

6.Cookies(Cookies在同一个域名内,并且目录也得相同)

7.BroadcastChannel(Chrome商店的api)
这个方式,只要是在同一原始域和用户代理下,所有窗口、iframe之间都可以进行交互。这个感觉就有点类似于广播了。

1
2
3
4
5
6
7
8
9
10
11
12
13
//在一个页面上,触发事件,引发以下代码执行
//创建一个名字是mychannel的对象。记住这个名字,下面会用到
let cast = new BroadcastChannel('mychannel');
let myObj = { from: "children1", content: "add" };
cast.postMessage(myObj)


//在子页面上,定义以下代码(当前页面也可以接收消息)
//创建一个和刚才的名字一样的对象
let cast1 = new BroadcastChannel('mychannel');
cast1.onmessage = function (e) {
alert(e)
}

28.简述下你理解的优雅降级和渐进增强

渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。

优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。

在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容.

29.写一个判断数据类型的方法

1
2
3
4
5
6
7
8
9
10
11
12
function getType(val) {
return Object.prototype.toString.call(val).replace(/\[object\s|\]/g, '').toLowerCase()
}
getType(null) // null
getType(undefined) // 'undefined'
getType('') // 'string'
getType([]) // 'array'
getType({}) // 'object'
getType(true) // 'boolean'
getType(Number) // 'function'
getType(12) // 'number'
getType(Symbol('1')) // 'symbol'

30.viewport常见设置都有哪些?

1
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

该meta标签的作用是让当前viewport的宽度等于设备的宽度.同时不允许用户手动缩放
meta viewport有6个属性(content设置内容),如下:

属性 作用
width 设置viewport 的宽度,为一个正整数,或字符串”width-device”
initial-scale 设置页面的初始缩放值,为一个数字,可以带小数
minimum-scale 允许用户的最小缩放值,为一个数字,可以带小数
maximum-scale 允许用户的最大缩放值,为一个数字,可以带小数
height 设置layout viewport 的高度,这个属性对我们并不重要,很少使用
user-scalable 是否允许用户进行缩放,值为”no”或”yes”, no 代表不允许,yes代表允许

此外,在安卓中还支持 target-densitydpi 这个私有属性,它表示目标设备的密度等级,作用是决定css中的1px代表多少物理像素.
target-densitydpi:值可以为一个数值或 high-dpi 、 medium-dpi、 low-dpi、 device-dpi 这几个字符串中的一个
当 target-densitydpi=device-dpi 时, css中的1px会等于物理像素中的1px。

首先如果不设置meta viewport标签,那么移动设备上浏览器默认的宽度值为800px,980px,1024px等这些,总之是大于屏幕宽度的。这里的宽度所用的单位px都是指css中的px,它跟代表实际屏幕物理像素的px不是一回事.

第二、每个移动设备浏览器中都有一个理想的宽度,这个理想的宽度是指css中的宽度,跟设备的物理宽度没有关系,在css中,这个宽度就相当于100%的所代表的那个宽度。我们可以用meta标签把viewport的宽度设为那个理想的宽度,如果不知道这个设备的理想宽度是多少,那么用device-width这个特殊值就行了,同时initial-scale=1也有把viewport的宽度设为理想宽度的作用.

可以同时使用

1
<meta name="viewport" content="width=device-width, initial-scale=1">

31.对比下px、em、rem有什么不同?

px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。

em单位名称为相对长度单位。相对于当前对象内文本的字体尺寸.em的值并不是固定的;

rem是CSS3新增的一个相对单位(root em,根em),仍然是相对大小,但相对的只是HTML根元素

32.简要描述下什么是回调函数并写一个例子出来

回调函数:做为实参数传入函数,并在该外部函数内调用,用以完成某些任务。

1
2
3
4
5
6
7
8
9
function greeting(name) {
alert('Hello,' + name)
}
function processUserInput(callback) {
var name = prompt('Please enter your name.');
callback(name);
}

processUserInput(greeting);

以上示例为同步回调,它是立即执行的。
回调函数经常被用于在一个异步操作完成后执行代码,它们被称为异步回调.
一个常见的例子是在 promise 末尾添加的 .then 内执行回调函数(在 promise 被兑现或拒绝时执行)

33.你对标签语义化的理解是什么?

代码结构清晰,方便阅读,有利于团队合作开发。

方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以语义的方式来渲染网页。

有利于搜索引擎优化(SEO)。

34.css常用的布局方式有哪些?

流式布局: 最基本的布局,就是顺着 html 像流水一样流下来
绝对定位:利用postion: absolute进行绝对定位的布局
flaot布局:浮动布局,最初用来解决多栏布局,比如圣杯、双飞燕布局都可以用float实现
栅格布局:bootstrap布局,把页面分为24列,通过row和col布局
flex布局:css3的布局,弹性布局”,用来为盒状模型提供最大的灵活性
grid布局:网格布局

35.简要描述下JS有哪些内置的对象

标准内置对象分类:

值属性
这些全局属性返回一个简单值,这些值没有自己的属性和方法

  • Infinity: 一个数值,表示无穷大
  • NaN: 全局属性 NaN 是一个表示非数字的值。
  • undefined: 表示原始值undefined,是js的一个原始数据类型
  • globalThis: 全局属性gobalThis包含全局的this,类似全局对象

函数属性
全局函数可以直接调用,不需要在调用时指定所属对象,执行结束后会将值返回给调用者。

  • eval():会将传入的字符串当做 JavaScript 代码进行执行。
  • isFinite(): 判断传入参数是否是一个有限数值。参数会首先转为一个数值。
  • isNaN(): 判断传入参数是否是NaN
  • parseFloat():解析一个参数(必要时先转换为字符串)并返回一个浮点数。
  • parseInt(): parseInt(string, radix) 解析一个字符串并返回指定基数的十进制整数,radix 是 2-36 之间的整数,表示被解析字符串的基数.
  • decodeURI(): 函数能解码由encodeURI 创建或其它流程得到的统一资源标识符(URI)。
  • decodeURIComponent(): 方法用于解码由 encodeURIComponent 方法或者其它类似方法编码的部分统一资源标识符(URI)
  • encodeURI(): 函数通过将特定字符的每个实例替换为一个、两个、三或四转义序列来对统一资源标识符 (URI) 进行编码
  • encodeURIComponent(): 函数通过将一个,两个,三个或四个表示字符的 UTF-8 编码的转义序列替换某些字符的每个实例来编码 URI

基本对象
顾名思义,基本对象是定义或使用其他对象的基础。基本对象包括一般对象、函数对象和错误对象

  • Object
  • Function
  • Boolean
  • Symbol

错误对象
错误对象是一种特殊的基本对象。它们拥有基本的 Error 类型,同时也有多种具体的错误类

  • Error:当运行时错误产生时,Error 对象会被抛出。Error 对象也可用于用户自定义的异常的基础对象
  • EvalError: 错误原因与eval()有关
  • RangeError: 错误原因:数值变量或参数超出其有效范围
  • ReferenceError: 无效引用
  • SyntaxError: 语法错误
  • TypeError: 变量或参数不属于有效类型
  • URIError:给encodeURI和decodeURI传递的参数无效
  • AggregateError:其中包裹了由一个操作产生且需要报告的多个错误。如:Promise.any() 产生的错误。
  • InternalError: 创建一个代表 Javascript 引擎内部错误的异常抛出的实例。如:递归太多。

数字和日期对象
用来表示数字、日期和执行数学计算的对象。

  • Number
  • BigInt
  • Math
  • Date

字符串
用来表示和操作字符串的对象

  • String
  • RegExp

可索引的集合对象
这些对象表示按照索引值来排序的数据集合,包括数组和类型数组,以及类数组结构的对象。

  • Array
  • Int8Array
  • Uint8Array
  • Uint8ClampedArray
  • Int16Array
  • Uint16Array
  • Int32Array
  • Uint32Array
  • Float32Array
  • Float64Array
  • BigInt64Array
  • BigUint64Array

使用键的集合对象
这些集合对象在存储数据时会使用到键,包括可迭代的Map 和 Set,支持按照插入顺序来迭代元素。

  • Map
  • Set
  • WeakMap
  • WeakSet

….

JavaScript 标准内置对象(MDN

36.常见的浏览器内核都有哪些?并介绍下你对内核的理解

浏览器内核分为渲染引擎和js引擎。渲染引擎负责页面的渲染,js引擎负责执行解析js。
之后,由于js引擎越来越独立,现在所说的浏览器内核大都指渲染引擎。
目前主流的浏览器内核有:

  • Trident:由微软开发的即ie内核
  • Gecko:使用c++开发的渲染引擎,firefox内核
  • Blink:Opera>12.18,chrome>=28,edge使用的内核
  • Webkit:chrome<28和safari使用的内核
  • Presto:Opera <= 12.18

37.说说你对css盒子模型的理解

完整的 CSS 盒模型应用于块级盒子,内联盒子只使用盒模型中定义的部分内容。模型定义了盒的每个部分 —— margin, border, padding, and content

CSS 中组成一个块级盒子需要:

  • Content box: 这个区域是用来显示内容,大小可以通过设置 width 和 height.
  • Padding box: 包围在内容区域外部的空白区域;大小通过 padding 相关属性设置
  • Border box: 边框盒包裹内容和内边距。大小通过 border 相关属性设置。
  • Margin box: 这是最外面的区域,是盒子和其他元素之间的空白区域。大小通过 margin 相关属性设置。

标准盒模型
在标准模型中,如果你给盒设置 width 和 height,实际设置的是 content box。padding 和 border 再加上设置的宽高一起决定整个盒子的大小。

1
2
3
4
5
6
7
.box {
width: 350px;
height: 150px;
margin: 25px;
padding: 25px;
border: 5px solid black;
}

如果使用标准模型宽度 = 410px (350 + 25 + 25 + 5 + 5),高度 = 210px (150 + 25 + 25 + 5 + 5),padding 加 border 再加 content box。

替代(IE)盒模型
宽度是可见宽度,所以内容宽度是该宽度减去边框和填充部分。

默认浏览器会使用标准模型。如果需要使用替代模型,您可以通过为其设置 box-sizing: border-box 来实现。

38.写一个获取当前url查询字符串中的参数的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function getUrlParams(url) {
if (url.split('?').length > 1) {
const urlParams = url.split('?')[1].split('&')
let res = {}
urlParams.forEach(item => {
let temp = item.split('=')
res[temp[0]] = temp[1]
})
return res
}
return {}
}
getUrlParams('http://192.168.1.200:8080?a=1&b=2') // {a: '1', b:'2'}
// 正则
function getUrlParams(url) {
let params = {}
url.replace(/([^&=?]+)=([^&]+)/g, (m, $1, $2) => {
params[$1] = $2
})
return params
}
getUrlParams('http://192.168.1.200:8080?a=1&b=2') // {a: '1', b:'2'}

39.网页应用从服务器主动推送到客户端有那些方式?

webSocket
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

eventsource(SSE)
EventSource 接口是 Web 内容与服务器发送的事件的接口。一个 EventSource 实例打开一个持久连接 HTTP 服务器,它发送事件的 text/event-stream 格式。连接保持打开状态,直到通过调用关闭 EventSource.close()。

与 WebSockets 不同,服务器发送的事件是单向的。也就是说,数据消息是从服务器到客户端(例如用户的 Web 浏览器)沿一个方向传递的

Web Push
就是用户订阅了一个站点的 Web Push 服务后,即使用户关闭了浏览器,一旦站点主动发送推送消息,用户都能收到,只要你的电脑是开着的。这是目前谷歌和苹果在 Chrome 和 Safari 上都力推的一种全新推送服务,Firefox 最近也加入了这个阵营。

但是由于需要 GCM 支持,所以这个方法并不常见

40.html5中的form怎么关闭自动完成?

autocomplete设置off,有时不生效
在浏览器设置里自动填充模块关闭

41.::before和:after中单冒号和双冒号的区别是什么,这两个伪元素有什么作用?

::和:是css3为了区分伪类和伪元素的,:表示伪类,::表示伪元素
::before是在元素前面插入内容,::after则是在元素后面插入内容,不过需要content配合,并且插入的内容是inline的。

43.http都有哪些状态码?

HTTP状态码分类:

分类 分类描述
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误

常见状态码:

状态码 描述
200 成功
301 永久重定向
302 临时重定向
304 使用缓存,不改变
400 客户端请求的语法错误,服务器无法理解
403 服务器理解请求客户端的请求,但是拒绝执行此请求
404 找不到资源
405 客户端请求中的方法被禁止
413 由于请求的实体过大,服务器无法处理,因此拒绝请求
500 服务器内部错误
502 Bad Gateway作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响
504 网关超时

44.为什么HTML5只需要写就可以?

因为html5和html4基于的基准不一样。html4基于SGML,因此除了DOCTYPE外还需要引入DTD来告诉浏览器用什么标准来渲染。DTD还区分严格模式和怪异模式。如果不写,浏览器自由发挥会变成怪异模式。
html5不基于SGML因此不需要DTD,但还是需要DOCTYPE来规范浏览器渲染行为。

SGML是通用标记语言的合集,有html、xml,因此需要DTD来指定使用哪种规范

DOCTYPE(Document Type Declaration)用于声明文档类型和DTD(Document Type Definition)规范,确保不同浏览器以相同的方式解析文档,以及执行相同的渲染模式。
DTD就是文档类型定义,一种标记符的语法规则,保证SGML和XML文档格式的合法性。

45.什么是闭包?优缺点分别是什么?

闭包是一个函数以及捆绑的周边环境状态(词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。闭包会随着函数的创建而被同时创建。

闭包:

1
2
3
4
5
6
7
8
9
10
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}

var myFunc = makeFunc();
myFunc();

for循环:

1
2
3
4
5
6
<ul>
<li>xxxxxxxxxxx</li>
<li>xxxxxxxxxxx</li>
<li>xxxxxxxxxxx</li>
<li>xxxxxxxxxxx</li>
</ul>
1
2
3
4
5
6
var liElements = document.getElementsByTagName('li');
for(var i=0; i< liElements.length; i++){
liElements[i].onclick = function(){
console.log(i) // 因为 变量i 是公用一个词法环境,所以最终输出的都一样,都输出 4
}
}

解决这个问题的一种方案是使用更多的闭包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var liElements = document.getElementsByTagName('li');
for(var i=0; i< liElements.length; i++){
(liElements[i].onclick = function(){
console.log(i)
})() // 匿名闭包
}
// 闭包-函数工厂
for(var i=0; i< liElements.length; i++){
liElements[i].onclick = function(){
conFun(i)()
}
}
function conFun(i) {
return function() {
console.log(i)
}
}
// const let
for(let i=0; i< liElements.length; i++){
liElements[i].onclick = function(){
console.log(i)
}
}

性能考量:
使用闭包可以隐藏变量以及防止变量被篡改和作用域的污染,从而实现封装。
而缺点就是由于保留了作用域链,会增加内存的开销。因此需要注意内存的使用,并且防止内存泄露的问题.
解决方法是:在退出函数之前,将不使用的局部变量全部删除;闭包会在函数外部,改变函数内部变量的值。

46.title与h1的区别、b与strong的区别、i与em的区别?

title与h1的区别:

  • 定义
    title是网站标题,一个页面只能有一个
    h1是文章主题
  • 作用
    title概括网站信息,可以直接告诉搜索引擎和用户这 个网站是关于什么主题和内容的,是显示在网页Tab栏里的;
    h1突出文章主题,面对用户,更突出其视觉效果,指向 页面主体信息,是显示在网页中的。
  • 注意
    如果title为空,但是页面存在h1,b,strong标签,搜索引擎会默认页面title为h1内的内容,所以 得出结论h1是在没有外界干扰下除title以外第二个能强调页面主旨的标记,在一个页面中应该使用且只使用一次h1标记。

b与strong的区别:

  • 定义
    b(bold)是实体标签,用来给文字加粗
    strong是逻辑标签,作用是加强字符语气
  • 区别
    b标签只是加粗的样式,没有实际含义,常用来表达无强调或着中意味的粗体文字
    trong表示标签内字符重要,用以强调,其默认格式是加粗,但是可以通过css添加样式,使用别的样式强调。在使用阅读设备时,会重读
  • 建议:为了符合css3的规范语义化,b应尽量少用而改用strong

i与em的区别:

  • 定义
    i(italic)是实体标签,用来使字符倾斜
    em(emphasis)是逻辑标签,作用是强调文本内容
  • 区别
    i标签只是斜体的样式,没有实际含义,常用来表达无强调或着重意味的斜体,比如生物学名、术语、外来语;
    em表示标签内字符重要,用以强调,其默认格式是斜体,但是可以通过CSS添加样式。在使用阅读设备时,会重读
  • 建议:为了符合CSS3的规 范,i应尽量少用而改用em。

物理元素是告诉浏览器我应该以何种格式显示文字,逻辑元素告诉浏览器这些文字有怎么样的重要性。
对于搜索引擎来说em和strong比i和b要重视的多。

47.style标签写在body前和body后的区别是什么?

在 HTML4 的时候,不应该把 style 放到 body 中间。

浏览器在渲染页面时 DOM 和 CSSOM 是并行的,然后两者结合形成 Render Tree 显示页面。从直觉上来说,style 写在 body 前不会对 DOM 的渲染进行阻塞;而写在 body 内会对 DOM 渲染进行阻塞。会产生 FOUC(Flash of Unstyled Content) 的现象,既一瞬间的白屏或者样式的突然变化(原因是 Render Tree 重新生成了)。

不过 W3C 在 HTML5.2 的定义中对于 style 标签的使用的定义中是允许将 style 放到 body 中的.

48.写一个数组去重的方法(支持多维数组)

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
// 1.
function flatArr(arr) {
let result = []
arr.forEach(item => {
if (Array.isArray(item)) {
result = result.concat(...flatArr(item))
} else {
result.push(item)
}
})
return result
}
function dupRemove(arr) {
arr = flatArr(arr)
return Array.from(new Set(arr))
}
dupRemove([1,2,3,[4,5], 3,2,1,[1,2,3,[4, 4, 5]],5,6,8,4,9,[1,2,3],[1,2,3], [4,5], [1,2,3,[4, 5]]]) // [1, 2, 3, 4, 5, 6, 8, 9]

// 2.不展开数组去重
function dupRemove(arr) {
arr = Array.from(new Set(arr))
arr.forEach((item, index) => {
if (Array.isArray(item)) {
arr[index] = dupRemove(item)
}
})
return arr
}
dupRemove([1,2,3,[4,5], 3,2,1,[1,2,3,[4, 4, 5]],5,6,8,4,9,[1,2,3],[1,2,3], [4,5], [1,2,3,[4, 5]]]) // [1, 2, 3, Array(2), Array(4), 5, 6, 8, 4, 9, Array(3), Array(3), Array(2), Array(4)]

// 3.
function dupRemove(arr) {
return [...new Set(arr.flat(Infinity))]
}
dupRemove([1,2,3,[4,5], 3,2,1,[1,2,3,[4, 4, 5]],5,6,8,4,9,[1,2,3],[1,2,3], [4,5], [1,2,3,[4, 5]]]) // [1, 2, 3, 4, 5, 6, 8, 9]

49.元素的alt和title有什么区别?

alt:

1
<img src="#" alt="alt 信息" />

当图片不输出信息的时候,会显示 alt 信息, 鼠标放上去没有信息。
当图片正常读取,不会出现 alt 信息。

title:

1
<img src="#" alt="alt 信息" title="title 信息" />

当图片不输出信息的时候,会显示 alt 信息,鼠标放上去会出现 title 信息。
当图片正常输出的时候,不会出现 alt 信息,鼠标放上去会出现 title 信息。

50.请描述margin边界叠加是什么及解决方案

块的上外边距 (margin-top)和下外边距 (margin-bottom)有时合并 (折叠) 为单个边距,其大小为单个边距的最大值 (或如果它们相等,则仅为其中一个),这种行为称为边距折叠。

注:有设定float和position=absolute的元素不会产生外边距重叠行为。

有三种情况会形成外边距重叠:

  • 同一层相邻元素之间
    相邻的两个元素之间的外边距重叠,除非后一个元素加上clear-fix 清除浮动
1
2
3
4
5
6
7
8
9
10
11
<style>
p:nth-child(1){
margin-bottom: 13px;
}
p:nth-child(2){
margin-top: 87px;
}
</style>

<p>下边界范围会...</p>
<p>...会跟这个元素的上边界范围重叠。</p>
  • 没有内容将父元素和后代元素分开
    如果没有边框border,内边距padding,行内内容,也没有创建块级格式上下文或清除浮动来分开一个块级元素的上边界margin-top 与其内一个或多个后代块级元素的上边界margin-top;或没有边框,内边距,行内内容,高度height,最小高度min-height或 最大高度max-height 来分开一个块级元素的下边界margin-bottom与其内的一个或多个后代后代块元素的下边界margin-bottom,则就会出现父块元素和其内后代块元素外边界重叠,重叠部分最终会溢出到父级块元素外面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<style type="text/css">
section {
margin-top: 13px;
margin-bottom: 87px;
}

header {
margin-top: 87px;
}

footer {
margin-bottom: 13px;
}
</style>

<section>
<header>上边界重叠 87</header>
<main></main>
<footer>下边界重叠 87 不能再高了</footer>
</section>
  • 空的块级元素
    当一个块元素上边界margin-top 直接贴到元素下边界margin-bottom时也会发生边界折叠。这种情况会发生在一个块元素完全没有设定边框border、内边距padding、高度height、最小高度min-height 、最大高度max-height 、内容设定为 inline 或是加上clear-fix的时候。
1
2
3
4
5
6
7
8
9
10
11
12
13
<style>
​​​​​​p {
margin: 0;
}
div {
margin-top: 13px;
margin-bottom: 87px;
}
</style>

<p>上边界范围是 87 ...</p>
<div></div>
<p>... 上边界范围是 87</p>

解决方法,可以通过触发BFC解决:

  • 1、根元素,即 html
  • 2、float 的值不为 none(默认)
  • 3、overflow 的值不为 visible(默认)
  • 4、display 的值为 inline-block、table-cell、table-caption
  • 5、position 的值为 absolute 或 fixed
  • 6.外层padding
  • 7.透明边框border:1px solid transparent;

51.返回到顶部的方法有哪些?

1.window.scrollTo(0,0) ie支持不好
2.window.scroll(0,0) 和scrollTo类似
3.<a href="#">top</a>
4.location.href += ‘#’;当这个方法执行多次即有多个 # 时,页面不会有响应。
5.document.documentElement.scrollTop = 0;
6.锚点法,在顶部加个标签

52.解释下 CSS sprites的原理和优缺点分别是什么?

将一个页面涉及到的所有零星图片都包含到一张大图中, 利用CSS的“background-image”,“background- repeat”,“background-position”的组合进行背景定位, 访问页面时避免图片载入缓慢的现象。

优点:
1.减少网页的http请求,从而大大的提高页面的性能
缺点:
图片合并麻烦
图片适应性差:在高分辨的屏幕下自适应页面,若图片不够宽会出现背景断裂。
图片定位繁琐
可维护性差

53.typeof(‘abc’)和typeof ‘abc’都是string, 那么typeof是操作符还是函数?

typeof是操作符不是函数,括号只是进行分组而非函数。

54.说说你对SVN和GIT的理解和区别

svn是集中式的,允许单次下载单文件修改,因为对每个文件都有对应的.svn文件控制
git是分布式的,每次clone都是获得一个完整的代码版本,可以不依赖服务器本地独立运行项目

55.怎样在页面上实现一个圆形的可点击区域?

1.DOM 元素配合 border-radius: 50% 即可实现圆形点击区域
2.利用 <map><area>标签设置圆形点击区域。参考文章:HTML 标签及在实际开发中的应用
3.利用 SVG 作出圆形,然后添加点击事件。
4.如果在 canvas 上,就需要画出圆形,然后计算鼠标的坐标是否落在圆内。

56.什么是FOUC?你是如何避免FOUC的?

FOUC 即 Flash of Unstyled Content,是指页面一开始以样式 A(或无样式)的渲染,突然变成样式B。原因是样式表晚于 HTML 加载导致页面重新进行绘制。

  • 通过 @import 方式导入样式表
  • style 标签在 body 中

解决方法:把 link 标签将样式放在 head 中

57.你理解的”use strict”;是什么?使用它有什么优缺点?

JavaScript 严格模式(strict mode)即在严格的条件下运行。

为什么使用严格模式:

  • 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
  • 消除代码运行的一些不安全之处,保证代码运行的安全;
  • 提高编译器效率,增加运行速度;
  • 为未来新版本的Javascript做好铺垫。

严格模式的限制:

不允许使用未声明的变量:

1
2
"use strict";
x = 3.14; // 报错 (x 未定义)

不允许删除变量或对象:

1
2
3
"use strict";
var x = 3.14;
delete x; // 报错

不允许删除函数:

1
2
3
"use strict";
function x(){};
delete x // 报错

不允许变量重名:

1
2
"use strict";
function x(p1, p1) {}; // 报错

不允许使用八进制:

1
2
"use strict";
var x = 010; // 报错

不允许使用转义字符:

1
2
"use strict";
var x = \010; // 报错

不允许对只读属性赋值:

1
2
3
4
5
"use strict";
var obj = {};
Object.defineProperty(obj, "x", {value:0, writable:false});

obj.x = 3.14; // 报错

不允许对一个使用getter方法读取的属性进行赋值:

1
2
3
4
"use strict";
var obj = {get x() {return 0} };

obj.x = 3.14; // 报错

不允许删除一个不允许删除的属性:

1
2
"use strict";
delete Object.prototype; // 报错

变量名不能使用 “eval” 字符串:

1
2
"use strict";
var eval = 3.14; // 报错

变量名不能使用 “arguments” 字符串:

1
2
"use strict";
var arguments = 3.14; // 报错

不允许使用以下这种语句:

1
2
"use strict";
with (Math){x = cos(2)}; // 报错

由于一些安全原因,在作用域 eval() 创建的变量不能被调用:

1
2
3
"use strict";
eval ("var x = 2");
alert (x); // 报错

禁止this关键字指向全局对象:

1
2
3
4
5
6
7
8
9
10
function f(){
return !this;
}
// 返回false,因为"this"指向全局对象,"!this"就是false

function f(){
"use strict";
return !this;
}
// 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。

保留关键字:

implements
interface
let
package
private
protected
public
static
yield

注: “use strict” 指令只允许出现在脚本或函数的开头。

58.可替换元素

在css中,可替换元素的展现效果不是由css来控制的,这些元素是一种外部对象,它们外观的渲染是独立于css的。简单来说,它们的内容不受当前文档样式的影响。CSS 可以影响可替换元素的位置,但不会影响到可替换元素自身的内容。

CSS 能对可替换元素产生的唯一影响在于,部分属性支持控制元素内容在其框中的位置或定位方式

可替换元素有:

  • iframe
  • video
  • embed
  • img

用 CSS content 属性插入的对象是匿名的可替换元素。它们并不存在于 HTML 标记中,因此是“匿名的“。

某些 CSS 属性可用于指定 可替换元素中包含的内容对象 在该元素的盒区域内的位置或定位方式

  • object-fit
    指定可替换元素的内容对象在元素盒区域中的填充方式(有些类似于 background-size )
  • object-position
    指定可替换元素的内容对象在元素盒区域中的位置。(类似于 background-position )

59.css重的content属性有什么作用?有哪些场景可以用到?

css中的content属性用于::before和::after伪元素中插入内容。使用content属性拆入的内容都是匿名的可替换元素

content的值:

  • none: 不会产生伪元素
  • normal: before 和 :after 伪类元素中会被视为 none
  • <string>: 文本内容
  • <uri>: url(‘http://www.example.com/test.html'),URI 值会指定一个外部资源(比如图片)
  • <counter>:计数器可以指定两种不同的函数:counter() 或 counters()
  • attr(x): 将元素的x属性以字符串形式返回。如果该元素没有 X 属性,则返回一个空字符串。区分大小写的属性返回值依赖文挡的语言设定。
  • open-quote | close-quote:这些值会被 quotes 中定义的字符串替换
  • no-open-quote | no-close-quote:不会生产任何内容,但是会改变(增加或降低)引号层级。

60.“attribute”和“property”有什么不同?

property:

  • 是DOM的属性,js中的对象
  • 读取方式,element.id,element.value,element.className
  • 设置方式:element.id = newId
  • 对大小写敏感

attribute:

  • 是HTML的属性,直接在html标签添加的都是attribute属性
  • 读取方式:element.getAttribute(“attrName”),比如element.getAttribute(‘class’)
  • 设置方式:element.setAttribute(“attrName”, value)

61.请描述HTML元素的显示优先级

元素的显示优先级,即元素覆盖次序的规则。显示优先级规则如下:

  • 帧元素(frameset)> 表单元素 > 非表单元素;
  • 有窗口元素 > 无窗口元素;
  • 同一类元素间,z-index 值大的元素 > z-index 值小的元素。

表单元素:文本输入框、密码输入框、单选框、复选框、文本输入域、列表框等等;

非表单元素:a、div、table、span 等等;

有窗口元素:select 元素、object 元素、frames 元素等等;

无窗口元素:大部分 html 元素都是无窗口元素,如 a、table 等等

62.要让Chrome支持小于12px的文字怎么做?

  1. 改用图片
  2. 使用 -webkit-text-size-adjust:none; 但是不支持chrome 27.0以上版本
  3. 使用 transform: scale()缩小
  • transform 对行内元素无效,因此要么使用 display: block; 要么使用 display: inline-block;
  • transform 即使进行了缩放,原来元素还是会占据对应的位置。因此需要做调整,最好是在外面再包一层元素,以免影响其他元素。

63.身份证号校验的方法

身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X:(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)

64.谈谈你对input元素中readonly和disabled属性的理解

readonly:
这个布尔属性指明无法修改控件的值。如果控件的type属性为hidden,range,color,checkbox,radio,file,此属性将被忽略。可以被提交,可以tab获取焦点

disabled:
这个布尔属性指明表单控件不可用。特别是在禁用的控件中,click事件将不会被分发。并且,禁用的控件的值在提交表单时也不会被提交。如果 type 属性为 hidden,此属性将被忽略。不可获取焦点。

65.说说你对line-height是如何理解的

line-height CSS 属性用于设置多行元素的空间量,如多行文本的间距。对于块级元素,它指定元素行盒(line boxes)的最小高度。对于非替代的 inline 元素,它用于计算行盒(line box)的高度。

line-height 属性被指定为以下任何一个:

  • 一个数字: line-height: 2;
  • 一个长度: line-height: 2em;
  • 一个百分比: line-height: 30%;
  • 关键词:normal

取值:

  • normal: 取决于用户端,桌面浏览器(包括 Firefox)使用默认值,约为1.2,这取决于元素的 font-family。
  • 数字:该属性的应用值是这个无单位数字<数字>乘以该元素的字体大小
  • 长度:line-height: 2em;。以 em 为单位的值可能会产生不确定的结果。
  • 百分比: 与元素自身的字体大小有关。计算值是给定的百分比值乘以元素计算出的字体大小

66.写一个方法验证是否是中文?

1
2
3
4
5
// 使用的Unicode 编码 4e00 和 9fa5 分别表示第一个汉字和最后一个汉字的编码
function isChinese(str) {
const re = /^[\u4e00-\u9fa5]+$/;
return re.test(str);
}

67.来说说你对重绘和重排的理解,以及如何优化?

浏览器渲染过程如下:

  • 解析HTML,生成DOM树,解析CSS,生成CSSOM树
  • 将DOM树和CSSOM树结合,生成渲染树(Render Tree)
  • Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
  • Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
  • Display:将像素发送给GPU,展示在页面上

通过构造渲染树,我们将可见DOM节点以及它对应的样式结合起来,可是我们还需要计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流

我们通过构造渲染树和回流阶段,我们知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(位置、大小),那么我们就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘节点。

何时发生回流重绘

  • 添加或删除可见的DOM元素
  • 元素的位置发生变化
  • 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
  • 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
  • 页面一开始渲染的时候(这肯定避免不了)
  • 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)

注意:回流一定会触发重绘,而重绘不一定会回流根据改变的范围和程度,渲染树中或大或小的部分需要重新计算,有些改变会触发整个页面的重排,比如,滚动条出现的时候或者修改了根节点。

当你获取布局信息的操作的时候,会强制队列刷新

最小化重绘和重排:

批量修改DOM:
使元素脱离文档流
对其进行多次修改
将元素带回到文档中。

有三种方式可以让DOM脱离文档流:

隐藏元素,应用修改,重新显示
使用文档片段(document fragment)在当前DOM之外构建一个子树,再把它拷贝回文档。
将原始元素拷贝到一个脱离文档的节点中,修改节点后,再替换原始的元素。

68.js放在html的<body><head>有什么区别?

点击查看script标签的加载和执行

69.说说浏览器解析CSS选择器的过程?

浏览器渲染过程:
images

浏览器渲染分为两部分:

  • HTML Parser生成DOM树;
  • CSS Parser生成Style Rules;

之后DOM树和Style Rules会生产Render Tree渲染树,结合Layout绘制在屏幕上,从而展现出来。

CSS 选择器解析顺序:
解析 CSS 选择器时是从右往左解析。
如果采用从左至右的方式读取 CSS 规则,那么大多数规则读到最后(最右)才会发现是不匹配的,这样会做费时耗能,最后有很多都是无用的;而如果采取从右向左的方式,那么只要发现最右边选择器不匹配,就可以直接舍弃了,避免了许多无效匹配。

浏览器 CSS 匹配核心算法的规则是以从右向左方式匹配节点的。这样做是为了减少无效匹配次数,从而匹配快、性能更优。

70.你对new 运算符的理解是什么?手动实现一个new方法

new 运算符创建一个用户定义的对象类型的实例或者具有构造函数的内置对象的实例。

语法:
new constructor[(arguments)]

参数:

  • constructor: 一个指定对象实例的类型的类或函数
  • arguments:一个用于被constructor调用的参数列表。

描述:

new 关键字会进行如下操作:

  • 创建一个空的简单js对象(即{});
  • 为新创建的对象添加属性proto,将该属性链接到构造函数的原型对象;
  • 将新创建的对象作为this的上下文;
  • 如果该函数没有返回对象,则返回this;

创建一个用户自定义对象需要两步:
1.通过编写函数来定义对象类型
2.通过new来创建对象实例

下面的代码将一个值为 null 的 color 属性添加到 car 类型的所有对象,然后仅在实例对象 car1 中用字符串 “black” 覆盖该值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Car() {}
car1 = new Car();
car2 = new Car();

console.log(car1.color); // undefined

Car.prototype.color = "original color";
console.log(car1.color); // original color

car1.color = 'black';
console.log(car1.color); // black

console.log(car1.__proto__.color) //original color
console.log(car2.__proto__.color) //original color
console.log(car1.color) // black
console.log(car2.color) // original color

如果你没有使用 new 运算符,构造函数会像其他的常规函数一样被调用,并不会创建一个对象。在这种情况下, this 的指向也是不一样的。

对象类型和对象实例:

1
2
3
4
5
6
7
8
// car汽车对象类型
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
// 对象实例
var mycar = new Car("Eagle", "Talon TSi", 1993);

对象属性为其他对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 定义了一个对象叫做 person:
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 实例化两个新的 person 对象如下:
var rand = new Person("Rand McNally", 33, "M");
var ken = new Person("Ken Jones", 39, "M");
// 可以重写 car 的定义,添加一个值为 person 对象的 owner 属性,如下:
function Car(make, model, year, owner) {
this.make = make;
this.model = model;
this.year = year;
this.owner = owner;
}
// 实例化新的对象
var car1 = new Car("Eagle", "Talon TSi", 1993, rand);
var car2 = new Car("Nissan", "300ZX", 1992, ken);
console.log(car2.owner.name) // Ken Jones

模拟new:

Object.create()方法创建一个新的对象,使用现有的对象来提供新创建对象的proto.
语法:Object.create(proto, [propertiesObject]):

apply用来重新定义this对象的

1
2
3
4
5
6
7
8
9
function _new(fn, ...arg) {
const obj = Object.create(fn.prototype)
// obj: {
// __proto__: {
// fn.prototype
// }
// }
const _this = fn.apply(obj, arg) // _this对象的this指向obj
return _this instanceof Object ? _this : obj

扩展:

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
// Object.create示例:
var aObj = {
a:'zjy',
b:'name',
c:function(n){
console.log('n:'+n);
}
};
var _aObj = Object.create(aObj,{
txt:{
value:'Object.create()方法的继承'
}
});
console.log(_aObj);
// _aObj{
// txt:'Object.create()方法的继承',
// __proto__:{
// a:'zjy',
// b:'name',
// c:funtion()
// }
// }
_aObj.c('haha'); // n:haha


// call/apply/bind示例:
var name = 'wang',age = 17;
var obj = {
name: 'zhang',
objAag: this.age,
myFun:function(fm,t){
console.log(this.name + '年龄' + this.age,'来自 '+ fm+' 去往'+t)
}
}
var db = {
name:'dema',
age: 99
}

obj.myFun.call(db,'成都','上海'); //dema年龄99 来自 成都 去往上海
obj.myFun.apply(db,['成都','上海']); //dema年龄99 来自 成都 去往上海
obj.myFun.bind(db,['成都','上海'])(); //dema年龄99 来自 成都,上海 去往undefined
obj.myFun.bind(db,'成都','上海')(); //dema年龄99 来自 成都 去往上海
obj.myFun.bind(db)('成都','上海'); // dema年龄99 来自 成都 去往上海

71.关于<form>标签的enctype属性你有哪些了解?

当method属性为post时,enctype就是将表单的内容提交给服务器的MIME类型。可能的值有:

  • application/x-www-form-urlencoded: 未指定属性时的默认值,在发送前对所有字符进行编码(将空格转换为 “+” 符号,特殊字符转换为 ASCII HEX 值)。
  • mulipart/form-data:当表单包含type=file的input元素时使用此值。
  • text/plain: 表单以纯文本形式进行编码.将空格转换为 “+” 符号,但不编码特殊字符.

72.说说CSS的优先级是如何计算的?

优先级就是分配给指定的 CSS 声明的一个权重,它由 匹配的选择器中的 每一种选择器类型的 数值 决定。
当同一个元素有多个声明的时候,优先级才会有意义

css里的c代表cascade,层叠,层叠决定了如何解决冲突,是css语言的基础。层叠会依据三种条件解决冲突。

(1) 样式表的来源:样式是从哪里来的,包括你的样式和浏览器默认样式等。

(2) 选择器优先级:哪些选择器比另一些选择器更重要。

(3) 源码顺序:样式在样式表里的声明顺序。

1.样式表的来源:

你添加到网页里的样式表并不是浏览器唯一使用的样式表,还有其他类型或来源的样式表。你的样式表属于作者样式表,除此之外还有用户代理样式表,即浏览器默认样式。用户代理样式表优先级低,你的样式会覆盖它们.

! important声明会被当作更高优先级的来源,因此总体的优先级按照由高到低排列如下所示:
(1) 作者的!important
(2) 作者的样式表
(3) 用户代理样式表

层叠规则顺序:不同来源的声明-内联声明-选择器优先级声明-源码顺序声明

2.选择器优先级:

伪类选择器(:hover)和属性选择器([type=”input”])与一个类选择器的优先级相同。
通用选择器(*)和组合选择器(>,+,~)对优先级无影响。

!important > 内联样式 > id > 类选择器((例如,.example),属性选择器(例如,[type=”radio”])和伪类(例如,:hover)) > 类型选择器(例如,h1)和伪元素(例如,::before) > * > 继承 >默认

73.0.1 + 0.2、0.1 + 0.3和0.1 * 0.2分别等于多少?并解释下为什么?

Javascript不详细区分整数、浮点数以及带符号的数字类型。使用双精度的64位浮点数字格式(IEEE 754)来表示数字,因此数字本质上都是浮点数。在该格式中,符号占1位(bit),指数部分占11位,小数部分占52位,共64位。

简单来说就是js中采用IEEE754的双精度标准,因为精度不足导致的问题。

0.1不再是 0.1 了,而是变成了 0.100000000000000002

1
0.100000000000000002 === 0.1 // true

0.2 :0.200000000000000002

1
0.200000000000000002 === 0.2 // true

由此我们可以得出:

1
0.1 + 0.2 === 0.30000000000000004 // true

所以0.1+0.2 != 0.3

1
parseFloat((0.1+0.2).toFixed(10)) === 0.3 // true

74.对属性data-的理解

data-*全局属性是一类被称为自定义数据属性的属性,它赋予我们在所有 HTML 元素上嵌入自定义数据属性的能力,并可以通过脚本在 HTML 与 DOM 表现之间进行专有数据的交换。

HTML语法.

所有元素上以data-开头的属性为数据属性。

比如说你有一篇文章,而你又想要存储一些不需要显示在浏览器上的额外信息。请使用 data 属性:

1
2
3
4
5
6
7
<article
id="electriccars"
data-columns="3"
data-index-number="12314"
data-parent="cars">
...
</article>

写入数据属性:

1
2
3
4
var article = document.querySelector('#electriccars');

article.dataset.column = 5; // 将column修改为5
console.log(article.dataset.columns); // 5

JavaScript 访问.

可以使用getAttribute()配合它们完整的 HTML 名称去读取它们.

为了使用dataset对象去获取到数据属性,需要获取属性名中data-之后的部分 (要注意的是破折号连接的名称需要改写为骆驼拼写法 (如”index-number”转换为”indexNumber”))。

1
2
3
4
5
var article = document.querySelector('#electriccars');

article.dataset.columns // "3"
article.dataset.indexNumber // "12314"
article.dataset.parent // "cars"

CSS 访问.

data 设定为 HTML 属性,他们同样能被CSS访问

1
2
3
article::before {
content: attr(data-parent);
}

也同样可以在 CSS 中使用属性选择器根据 data 来改变样式:

1
2
3
4
5
6
article[data-columns='3'] {
width: 400px;
}
article[data-columns='4'] {
width: 600px;
}

75.如何快速让一个数组乱序

1
2
3
4
5
6
7
8
9
10
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1))
var target = array[j]
array[j] = array[i]
array[i] = target
}
return array
}
shuffle([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]) //  [1, 3, 9, 4, 8, 10, 7, 2, 6, 5]

76.请说说<script><script async><script defer>的区别?

点击查看script标签的加载和执行

77.写一个判断设备来源的方法

1
2
3
4
5
6
7
8
9
10
11
12
function checkPlatform() {
let userAgentInfo = navigator.userAgent;
const Agents = ['Android', 'iPhone', 'SysbianOS', 'Windows Phone', 'iPad', 'iPod'];

for (let i = 0; i < Agents.length; i++) {
if (userAgentInfo.indexOf(Agents[i]) > 0) {
return alert('当前为移动端设备,机型为:' + Agents[i]);
}
}
return alert('当前为PC端');
}
checkPlatform();

或者https://github.com/matthewhudson/current-device

78.解释下你对GBK和UTF-8的理解?并说说页面上产生乱码的可能原因

GBK编码:
是指中国的中文字符,其它它包含了简体中文与繁体中文字符,另外还有一种字符“gb2312”,这种字符仅能存储简体中文字符。

UTF-8编码:
它是一种全国家通过的一种编码,如果你的网站涉及到多个国家的语言,那么建议你选择UTF-8编码。由于 UTF-8 包含了多种语言,也因此其占用的空间会比较大一些。

而网页产生乱码往往是因为编码与解码不匹配造成的。一般我们会在<meta> 标签中设置 charset 来决定网页采用的编码。如果引用的文件为其他格式,则会出现无法解释或者解释不对的字符,即乱码问题。

79.说说你对z-index的理解

查看css中的z-index属性

80.说说bind、call、apply的区别?并手写实现一个bind的方法

1
2
3
4
5
6
7
8
9
10
11
var name = 'wang',age = 17;
var obj = {
name: 'zhang',
objAag: this.age,
myFun:function(){
console.log(this.name + '年龄' + this.age)
}
}
obj.objAag; //17
obj.myFun(); //zhang年龄undefined

使用call/apply/bind

1
2
3
4
5
6
7
var db = {
name:'dema',
age: 99
}
obj.myFun.call(db); // dema年龄99
obj.myFun.apply(db); // dema年龄99
obj.myFun.bind(db)(); // dema年龄99

以上除了bind多了个()外,结果都一致,由此可知,bind返回的是一个新函数,必须调用它能执行

call/apply/bind 传参数区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var name = 'wang',age = 17;
var obj = {
name: 'zhang',
objAag: this.age,
myFun:function(fm,t){
console.log(this.name + '年龄' + this.age,'来自 '+ fm+' 去往'+t)
}
}
var db = {
name:'dema',
age: 99
}

obj.myFun.call(db,'成都','上海'); //dema年龄99 来自 成都 去往上海
obj.myFun.apply(db,['成都','上海']); //dema年龄99 来自 成都 去往上海
obj.myFun.bind(db,['成都','上海'])(); //dema年龄99 来自 成都,上海 去往undefined
obj.myFun.bind(db,'成都','上海')(); //dema年龄99 来自 成都 去往上海
obj.myFun.bind(db)('成都','上海'); // dema年龄99 来自 成都 去往上海

call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数:
call的参数直接放进去,多个参数用逗号分隔
apply的第二个参数是数组
bind 除了返回是函数以外,它 的参数和 call 一样

实现:

1
2
3
4
5
6
7
Function.prototype.myCall = function(context = window) {
context.fn = this
var args = [...arguments].slice(1)
var result = context.fn(...args)
delete context.fn
return result
}
1
2
3
4
5
6
7
8
9
10
Function.prototype.myApply = function(context = window) {
context.fn = this
var result
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
return result
}
1
2
3
4
5
6
7
Function.prototype.myBind = function (context) {
if (typeof this !=== 'function') {
throw new Error('Error')
}
var args = [...arguments].slice(1)
return (...args) => this.call(context, ...args)
}

81.git branch

git branch: 不带参数命令,获取本地仓库的分支列表,并显示当前所在分支,即head指向的分支

git branch -v: 查看每个分支的最后一次commit提交信息

git branch –merged: 查看已经合并到当前分支的分支

git branch –no-merged: 查看没有合并到当前分支的分支

git branch -D branchname: 强制删除某个分支,会丢失被删除的分支上面的所有内容。

82.说说你对影子(Shadow)DOM的了解

Shadow Dom是对标记结构、样式和行为的封装,Shadow DOM 接口可以将一个隐藏的独立的DOM附加到另一个元素上。
Shadow DOM 内部的元素始终不会影响到它外部的元素。
比如你所能看到的只是一个 <video> 标签,实际上,在它的 Shadow DOM 中,包含了一系列的按钮和其他控制器

基本用法.

可以使用 Element.attachShadow() 方法来将一个 shadow root(shadow tree 的根节点) 附加到任何一个元素上。它接受一个配置对象作为参数,该对象有一个 mode 属性,值可以是 open 或者 closed。

open 表示可以通过页面内的 JavaScript 方法来获取 Shadow DOM,例如使用 Element.shadowRoot 属性:

1
let myShadowDom = myCustomElem.shadowRoot

mode 设置为 closed,那么就不可以从外部获取 Shadow DOM 了——myCustomElem.shadowRoot 将会返回 null.
浏览器中的某些内置元素就是如此,例如video,包含了不可访问的 Shadow DOM。

1
2
3
let shadow = this.attachShadow({mode: 'open'});
var para = document.createElement('p');
shadow.appendChild(para);

将 Shadow DOM 附加到一个元素之后,就可以使用 DOM APIs 对它进行操作,就和处理常规 DOM 一样。

使用 shadow DOM(MDN)

83.怎样修改chrome记住密码后自动填充表单的黄色背景?

-webkit-text-fill-color: red; 设置文本颜色
-webkit-box-shadow: 0 0 0 1000px white inset; 设置内阴影

84.说说你对arguments的理解,它是数组吗?

arguments是一个对应于传递给函数的参数的类数组对象。

类数组意味着arguments有长度属性并且属性的索引时从零开始的,但是并没有Array的内置方法,比如forEach()和map()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function func1(a, b, c) {
console.log(Object.prototype.toString.call(arguments))
// output: "[object Arguments]"

console.log(arguments[0]);
// expected output: 1

console.log(arguments[1]);
// expected output: 2

console.log(arguments[2]);
// expected output: 3
}

func1(1, 2, 3);

arguments对象是所有函数(非箭头函数)都可用的局部变量。可以使用arguments对象在函数中引用函数的参数。

1
2
arguments[0]
arguments[1]

也可以被设置:

1
arguments[0] = 0

arguments没有Array内置方法,但是可以转化为Array:

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
function func1(a, b, c) {
console.log(Object.prototype.toString.call(arguments))
console.log(arguments[0]);
// expected output: 1

console.log(arguments[1]);
// expected output: 2

console.log(arguments[2]);
// expected output: 3

arguments[0] = 0
console.log(arguments[0]);

var args = Array.prototype.slice.call(arguments);
console.log('args', args)
// output: "args" Array [0, 2, 3]

var args1 = [].slice.call(arguments);
console.log('args1', args1)
// output: "args1" Array [0, 2, 3]

var args2 = Array.from(arguments)
console.log('args2', args2)
// output: "args2" Array [0, 2, 3]

var args3 = [...arguments]
console.log('args3', args3)
// output: "args3" Array [0, 2, 3]
}

func1(1, 2, 3);

arguments.callee指向参数所属的当前执行的函数。

85.说说你对<meta>标签的理解

文档级元数据元素,表示那些不能被其他html元相关元素(base、link、script、style、title)之一表示的任何元数据信息。

meta 元素定义的元数据的类型包括以下几种:

  • 如果设置了name属性,meta元素提供的是文档级别的元数据,应用于整个页面。
  • 如果设置了http-equiv属性,meta元素则是编译指令,提供的信息与类似命名的http头部相同。
  • 如果设置了charset属性,meta元素是一个字符集声明,告诉文档用哪种字符编码。
  • 如果设置了itemprop属性,meta元素提供用户自定义的元数据。

属性:

备注: 全局属性 name 在 <meta>元素中具有特殊的语义;另外,在同一个 <meta>标签中,name, http-equiv 或者 charset 三者中任何一个属性存在时,itemprop 属性不能被使用。

  • charset
    声明字符编码,如果使用了这个属性,其值必须是与ASCLL大小写无关的“utf-8“
1
<meta charset="utf-8">
  • content
    此属性包含http-equiv 或name 属性的值,具体取决于所使用的值。
1
<meta http-equiv="refresh" content="3;url=https://www.mozilla.org">
  • http-equiv
    属性定义了一个编译指示指令。这个属性叫做 http-equiv(alent) 是因为所有允许的值都是特定 HTTP 头部的名称,如下:
    • content-security-policy 它允许页面作者定义当前页的内容策略 (en-US)。内容策略主要指定允许的服务器源和脚本端点,这有助于防止跨站点脚本攻击。
    • content-type 如果使用这个属性,其值必须是”text/html; charset=utf-8”。注意:该属性只能用于 MIME type 为 text/html 的文档,不能用于 MIME 类型为 XML 的文档。
    • default-style 设置默认 CSS 样式表组的名称。
    • x-ua-compatible 如果指定,则 content 属性必须具有值 “IE=edge”。用户代理必须忽略此指示。
    • refresh 这个属性指定:
      如果 content 只包含一个正整数,则为重新载入页面的时间间隔 (秒);
      如果 content 包含一个正整数,并且后面跟着字符串 ‘;url=’ 和一个合法的 URL,则是重定向到指定链接的时间间隔 (秒)
1
2
<!-- 可以在 https 协议下请求 http -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
  • name
    name 和 content 属性可以一起使用,以名 - 值对的方式给文档提供元数据,其中 name 作为元数据的名称,content 作为元数据的值。
1
2
3
4
5
6
7
<!-- 移动端页面设置视口宽度等于设备宽度,并禁止缩放。 -->
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<!-- 禁止将页面中的数字识别为电话号码 -->
<meta name="format-detection" content="telephone=no" />
<!-- name=author: 用来设置作者,给 SEO 使用 -->
<!-- name=keywords: 网页的关键字,给 SEO 使用 -->
<!-- name=description: 页面的描述,在浏览器用作书签时会显示对应的内容 -->

87.rgba()和opacity这两个的透明效果有什么区别呢?

opacity:

指定了一个元素的不透明度。换言之,opacity 属性指定了一个元素后面的背景的被覆盖程度。
当 opacity 属性的值应用于某个元素上时,是把这个元素(包括它的内容)当成一个整体看待,即使这个值没有被子元素继承。
因此,一个元素和它包含的子元素都会具有和元素背景相同的透明度,哪怕这个元素和它的子元素有不同的 opacity 属性值。

使用 opacity 属性,当属性值不为 1 时,会把元素放置在一个新的层叠上下文中。

语法:

1
2
3
4
5
6
7
8
9
10
11
12
/* 完全不透明 */
opacity: 1;
opacity: 1.0;

/* 半透明 */
opacity: 0.6;

/* 完全透明 */
opacity: 0.0;
opacity: 0;

opacity: inherit;

rgba():

rgba 只对颜色(backgorund-color、color)有影响,放在background的话只对背景颜色有影响,不会影响其他内容及子元素。

88.解释代码意思

1
2
3
[].forEach.call($$("*"),function(a){ 
a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)
})

作用:
给页面所有 dom 元素添加随机颜色的边框。

解析:

  • [].forEach.call() => 调用引用数组的forEach方法
  • $$(‘‘) => document.querySelectorAll(‘‘)
  • ~~a => parseInt(a)
  • 1<<24 => 对二进数1小数点右移24位
  • (parseInt(Math.random()*(1<<24)).toString(16)) => 获得了一个位于0-16777216之间的随机整数,也就是随机颜色,再使用toString(16)将它转化为十六进制数。
1
2
3
4
5
6
7
[].forEach.call(
document.querySelectorAll('*'),
function(a){
a.style.outline="1px solid #" +
(parseInt(Math.random()*(1<<24)).toString(16))
}
)

89.在浏览器中输入url到页面显示出来的过程发生了什么?

1.浏览器地址栏输入URL并回车
2.通过DNS将域名解析成IP地址。在解析过程中,按照浏览器缓存、系统缓存、路由器缓存、ISP(运营商)DNS缓存、根域名服务器、顶级域名服务器、主域名服务器的顺序,逐步读取缓存,直到拿到IP地址。(应用层)
3.根据获取IP进行tcp连接(三次握手)(传输层)
4.发送http请求
5.服务器处理请求,浏览器接收http的响应
6.渲染页面,构造dom树
7.关闭tcp连接(四次挥手)

90.写一个获取数组的最大值、最小值的方法?

1
2
3
4
5
6
7
8
9
10
11
12
Math.max.apply(Array, [12, 9,239,12348,83974,1,324,342, -1, -273]) // 83974
Math.min.apply(Array, [12, 9,239,12348,83974,1,324,342, -1, -273]) // -273

function getMax(arr) {
return arr.reduce((total, current) => total = total > current ? total : current)
}
getMax([12, 9,239,12348,83974,1,324,342, -1, -273]) // 83974

function getMin(arr) {
return arr.reduce((total, current) => total = total < current ? total : current)
}
getMin([12, 9,239,12348,83974,1,324,342, -1, -273]) // -273

91.网页上的验证码是为了解决什么问题?说说你了解的验证码种类有哪些

1.图形验证码
2.字符验证码 文字+混淆 如早期的7456这种结果的验证码
3.复杂字符验证码 复杂文字+混淆 如加入中文等本土化的增加识别难度
4.计算验证码 数字+运算符+混淆 如1+2=? 需要识别表达式增加识别难度
5.精确识别 文字+混淆文字 如选出 优贝在线 中的 贝字,或者选出所有的筷子,所有的红绿灯(12306)
6.滑动拼图验证 图像+滑块+图像凹槽 如常见的滑动拼图,提供商有易盾之类的
7.拼图验证 图像+打乱 需要用户去拼合完成
8.手机短信验证码
9.手机发送一条短信

防止机器行为,确定是人为操作,比如登陆、发帖等。
保护服务器

92.描述下你所了解的图片格式及使用场景

格式 优点 缺点 适用场景
gif 文件小,支持动画、透明,无兼容性问题 只支持256种颜色 色彩简单的logo、icon、动图
jpg 色彩丰富,文件小 有损压缩,反复保存图片质量下降明显 色彩丰富的图片/渐变图像
png 无损压缩,支持透明,简单图片尺寸小 不支持动画,色彩丰富的图片尺寸大 logo/icon/透明图
webp 文件小,支持有损和无损压缩,支持动画、透明 浏览器兼容性不好 支持webp格式的app和webview

93.写一个方法判断字符串是否为回文字符串

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
// 使用for循环进行遍历
function isPalindrome(str){
if(str.length === 1) return true;
str = str.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
let flag = true
for(let i = 0; i < str.length; i++){
if(str[i] !== str[str.length - 1 - i]){
flag = fasle
break
}
}
return flag;
}
// 通过数组反转字符,然后再和原字符串进行比较
function isPalindrome(str){
if(str.length === 1) return true;
str = str.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
let newStr = str.split('').reverse().join('');
return str === newStr;
}

// 双指针遍历,从两边向中间进行遍历。其实和第一种方法中的for循环中if语句的判断条件类似
function isPalindrome(str){
if(str.length === 1) return true;
str = str.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
let lp = 0,
rp = str.length -1;
while(lp <= rp){
if(str[lp++] !== str[rp--]){
return false;
}
}
return true;
}

94.CRLF是什么?

CRLF的含义 是“carriage return/line feed”,意思是回车换行。CR回车\r,LF换行\n。

Windows操作系统采用两个字符来进行换行,即 CRLF;”\r\n”
Unix/Linux/Mac OS X操作系统采用单个字符 LF 来进行换行.”\n”

95.DOM和BOM有什么区别?

BOM:

BOM是Browser Object Model的缩写,即浏览器对象模型。
每个类型的浏览器都有各自的标准
最根本对象是window,主要的属性frames、location、history、navigator、screen

DOM:

DOM是Document Object Model的缩写,即文档对象模型。
DOM是W3C的标准
其根本是window.document

DOB&DON

96.让网页的字体变得清晰,变细用CSS怎么做?

让文字变细有两个要素:

1.font-weight + font-family
font-weight 来控制粗细还是需要看对应的字体有没有对应的变种字体。因此这就和 font-family 相关。

2.-webkit-font-smoothing
这个属性是 Chrome 的抗锯齿属性。加上后会显得细一些,但是只针对 webkit 内核的浏览器才有效。

97.写一个方法把0和1互转(0置1,1置0)

使用异或

1
2
3
const convert = num => num^1;
convert(0); // 1
convert(1); // 0

98.line-height3种设置方式的区别

line-height: 1.5;
line-height: 1.5em;
line-height: 150%;

对于应用在单个元素上,这几种写法的效果都是一样的(除了 px 需要一些计算)。但由于 line-height 是可以被继承的,因此会影响内部子元素的 line-height。简单的可以总结为:

  • 带有单位的 line-height 会被计算成 px 后继承。子元素的 line-height = 父元素的 line-height * font-size (如果是 px 了就直接继承)
  • 而不带单位的 line-height 被继承的是倍数,子元素的 line-height = 子元素的 font-size * 继承的倍数

99.造成内存泄漏的操作有哪些?

1、没有使用的全局变量;
2、闭包(闭包可以维持函数内部变量);
3、循环引用(引用计数不为0);
4、对页面中的一些 副作用没有清除(比如setInterval)

100.html和html5有什么区别呢?

1.HTML5简化了很多细微的语法,例如doctype的声明,只需要写就行了。HTML5与HTML5,XHTML1兼容,但是与SGML不兼容。
2.新增与语义化标签【header、footer、section、article等】
3.canvas替代Flash
4.html5媒体支持:audio vedio,HTML:如果不使用Flash播放器支持,它不支持音频和视频

102.说说你对this的理解

this是指当前运行环境的上下文。

全局this指向window(如果开启严格模式,this将指向undefined)

如果函数被一个对象调用,this指向该对象。如果fn()调用,指向window

箭头函数中的this例外,它指向定义时所在的位置,或者可以说箭头函数的this继承自外层作用域,只要确定了外层作用域的this,就知道箭头函数中的this指向谁了。

构造函数的指向new它的对象

可以通过apply call bind方法来改变函数的指向,指向就是第一个参数

定时器、延时器的this指向window

103.Standards模式和Quirks模式有什么区别?

mode = document.compatMode表明当前文档的渲染模式是怪异模式/混杂模式还是标准模式。
mode是一个枚举值(enumerated value),可能的值有:

  • “BackCompat”:文档为怪异模式。
  • “CSS1Compat”:文档不是怪异模式,意味着文档处于标准模式或者准标准模式。

Quirks mode:怪异模式 混杂模式
Standards mode: 标准模式

唯一的作用是启用标准模式。
quirks主要是为了兼容各个浏览器,远古时期遗留下来的BUG(或者说是当时的标准,对于现在来说的BUG),它并未遵循W3C的标准

主要的区别在盒模型:
Standards盒模型:width = content (box-sizing: content-box;)
Quirks盒模型: width = content + border + padding (box-sizing: border-box)

104.浏览器是怎样判断元素是否和某个CSS选择器匹配?

先产生一个元素集合,然后从后往前判断;

浏览器先产生一个元素集合,这个集合往往由最后一个部分的索引产生(如果没有索引就是所有元素的集合)。然后向上匹配,如果不符合上一个部分,就把元素从集合中删除,直到真个选择器都匹配完,还在集合中的元素就匹配这个选择器了.

示例:

有选择器:
div.ready #wrapper > .bg-red
先把所有元素 class 中有 bg-red 的元素拿出来组成一个集合,然后上一层,对每一个集合中的元素,如果元素的 parent id 不为 #wrapper 则把元素从集合中删去。 再向上,从这个元素的父元素开始向上找,没有找到一个 tagName 为 div 且 class 中有 ready 的元素,就把原来的元素从集合中删去。
至此这个选择器匹配结束,所有还在集合中的元素满足。

105.用一个div模拟textarea的实现

1
<div class="edit" contenteditable="true" style="resize: both"></div>

contenteditable设置可编辑,resize设置右下角可拉伸

106.使用flex实现三栏布局,两边固定,中间自适应

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
<style>
.container {
width: 100%;
height: 150px;
border-top: 1px solid;
display: flex;
flex: 1 1 auto;
}
.main {
height: 150px;
background-color: aquamarine;
width: 100%;
}
.left {
width: 30px;
height: 100px;
background-color: darkkhaki;
}
.right {
width: 60px;
height: 100px;
background-color: firebrick;
flex-shrink: 0;
}
</style>

<div class="container">
<div class="left">left</div>
<div class="main">
flex
</div>
<div class="right">right</div>
</div>

107.请你解释一个为什么10.toFixed(10)会报错?

.既可以理解为小数点也可以理解为方法调用
按照规范,紧跟数字后面就把它判断为一个小数点。可以改为:

1
2
3
4
(10).toFixed(10)
10 .toFixed(10)
10..toFixed(10)
10.0.toFixed(10)

108.谈一谈你知道的前端性能优化方案有哪些?

代码层面:避免使用css表达式,避免使用高级选择器,通配选择器。减少重绘重拍
缓存利用:缓存Ajax,使用CDN,使用外部js和css文件以便缓存,添加Expires头,服务端配置Etag,减少DNS查找等
请求数量:合并样式和脚本,使用css图片精灵,初始首屏之外的图片资源按需加载,静态资源延迟加载。
请求带宽:压缩文件,开启GZIP
优化加载:

webpack 开启 tree-shaking 减少代码体积
通过preload prefetch优化加载资源的时间
import(‘’).then()异步加载资源
图片小于30k的图片直接做成base64;
对于首屏的样式可以直接内嵌到html中;

服务端渲染:SSR对于首页可以直接通过node jade模板引擎输出,其他页面继续使用前端渲染,优化首屏、SEO

109.HTML和XHTM有什么不同?

  1. XHTML 元素必须被正确地嵌套。
  2. XHTML 元素必须被关闭。
  3. 标签名必须用小写字母。
  4. XHTML 文档必须拥有根元素

110.写出主流浏览器内核私有属性的css前缀

CSS 前缀:

主流浏览器引擎前缀:

  • -webkit- (谷歌,Safari,新版 Opera 浏览器,以及几乎所有 iOS 系统中的浏览器(包括 iOS 系统中的火狐浏览器);基本上所有基于 WebKit 内核的浏览器)
  • -moz-:(火狐浏览器)
  • -o- (旧版 Opera 浏览器)
  • -ms- (IE 浏览器 和 Edge 浏览器)

111.手写幻灯片效果

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wraper {
width: 500px;
height: 400px;
overflow: hidden;
}
.container {
width: 1500px;
height: 400px;
position: relative;
animation: move 5s infinite linear forwards;
}
.swiperItem {
width: 500px;
height: 400px;
font-size: 50px;
text-align: center;
line-height: 400px;
user-select: none;
float: left;
}
@keyframes move {
0% {
/* transform: translateX(0); */
margin-left: 0;
}
25% {
/* transform: translateX(0); */
margin-left: 0;
}
33.3% {
/* transform: translateX(-500px); */
margin-left: -500px;
}
58% {
/* transform: translateX(-500px); */
margin-left: -500px;
}
66.6% {
/* transform: translateX(-1000px); */
margin-left: -1000px;
}
100% {
/* transform: translateX(-1000px); */
margin-left: -1000px;
}
}
.swiperItem:nth-child(1) {
background-color: aquamarine;
}
.swiperItem:nth-child(2) {
background-color: burlywood;
}
.swiperItem:nth-child(3) {
background-color: cornflowerblue;
}
</style>
</head>
<body>
<div class="wraper">
<div class="container">
<div class="swiperItem">1</div>
<div class="swiperItem">2</div>
<div class="swiperItem">3</div>
</div>
</div>
</body>
</html>

112.对于前端安全,你了解多少?说说你对XSS和CSRF的理解

内容安全:

CSP内容安全策略:通过探测和减轻包括跨站脚本攻击 XSS (en-US) 和数据注入攻击的攻击手段,更进一步提升安全性

连接安全:

传输层安全TLS:传输层安全协议是在两个互联的应用或设备上稳定且私密地交换信息的标准

HTTPS:https超文本传输协议安全,使用SSL或TLS协议来对客户的端和服务器之间的所有通信进行加密

数据安全:

使用 HTTP Cookies:HTTP cookie(web cookie,浏览器 cookie)是服务器发送给客户端 web 浏览器的一小块数据。浏览器可能会存储它,并在后续对同一服务器的请求中将它发送回服务器

Local storage:Window 对象的 Window.localStorage 属性是一种服务器在客户端上存储持久性数据的方法,数据可以在不同的会话中持久访问

信息泄露:

完整性:

同源策略:同源策略限制了一个源中加载的文档或脚本与其他源中的资源交互的方式。这是一种用来隔离潜在恶意文档的关键安全机制。

点击劫持保护:

点击劫持 (en-US)描述了用户被愚弄,点击了一个产生用户意料之外行为的 UI 元素的现象

用户信息安全:

不安全的密码

Cross-site scripting 跨站脚本攻击XSS

是一种安全漏洞,攻击者可以使用这些漏洞在网站上注入恶意的客户端代码。若受害者运行这些代码,攻击者就可以突破网站的访问限制并冒充受害者。

在以下 2 种情况下,容易发生 XSS 攻击:

1.数据从一个不可靠的链接进入一个web应用程序
2.没有过滤掉恶意代码的动态内容被发送给web客户

恶意内容一般包括 JavaScript,但是,有时候也会包括 HTML,FLASH 或是其他浏览器可执行的代码。XSS 攻击的形式千差万别,但他们通常都会:将 cookies 或其他隐私信息发送给攻击者,将受害者重定向到由攻击者控制的网页,或是经由恶意网站在受害者的机器上进行其他恶意操作。

分类:

  1. 存储型(持久型)
  2. 反射型(非持久型)
  3. DOM型

存储型XSS

注入型脚本永久存储在目标服务器上。当浏览器请求数据时,脚本从服务器返回并执行。

反射型XSS

当用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网站时,注入脚本进入被攻击者的网站。Web 服务器将注入脚本,比如一个错误信息,搜索结果等 返回到用户的浏览器上。由于浏览器认为这个响应来自”可信任”的服务器,所以会执行这段脚本。

基于DOM的XSS

通过修改原始的客户端代码,受害者浏览器的 DOM 环境改变,导致有效载荷的执行。也就是说,页面本身并没有变化,但由于 DOM 环境被恶意修改,有客户端代码被包含进了页面,并且意外执行。

跨站请求伪造CSRF

跨站请求伪造是一种冒充受信任用户,向服务器发送非预期请求的攻击方法。

CSRF攻击之所以有效,是因为浏览器请求自动包含所有cookie,包括会话cookie.因此,如果用户对站点进行了身份验证,则站点无法区分合法授权请求和伪造的身份验证请求

如何防御:

1.get请求不修改数据
2.不让第三方网站访问到cookie,可以对 Cookie 设置 SameSite 属性。该属性表示 Cookie 不随着跨域请求发送,可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容
3.请求时附带验证信息,比如验证码或者token
4.检查Referer字段,http请求头中referer字段表明请求来源于哪个地址,通常来说,Referer字段应和请求的地址位于同一域名下

113.html5哪些标签可以优化SEO?

搜索引擎的排序主要由以下方面共同确定:

网页内容 权重分数
内部链接文字 10
标题title 10
域名 7
H1,H2字号标题 5
路径或文件名 4
title属性,a标签的title属性 1
加粗或斜体 1
alt标记 0.5

SEO中常见的语义化标签:

  • H标签的使用
  • strong标签的使用
  • title网站seo标题
  • meta name=”description” content=”网站描述”
  • meta name=”keywords” content=”网站关键词”
  • a href=”链接地址” title=”链接说明”
  • img src=”图片链接地址” alt=”图片说明”
  • div id=”copyright” 版权部分加上网站名称和链接
  • nav:可以帮助 UA 迅速获得导航内容,例如读屏器可以省去很多渲染直接跳到导航位置。
  • aside :可以表示与周围内容关系不太密切的内容 (广告),通常表现为侧边栏内容 (相关背景内容)、引述内容
  • header
  • article:独立的文档、页面、应用、站点,可以单独发布、重用;可以是一篇帖子、一篇文章、一则用户评论、一个可交互的 widget
  • section:按主题将内容分组,通常会有标题 (heading)

114.不使用border画出1px高的线,在不同浏览器的标准和怪异模式下都能保持效果一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.border {
box-shadow: 0 1px 0 0 #333;
height: 1px;
}
.border {
width: 100%;
height: 1px;
background: #333;
}
.border:after{
content: '';
display: block;
height: 1px;
background-color: #333;
}
<hr size="1">

115.找到字符串中最长的单词,并返回它的长度

1
2
3
4
5
6
7
8
function findLongestWord(str) {
if (!str) return
var strArr = str.split(' ')
return strArr.reduce(function(prev, current) {
return Math.max(prev, current.length)
}, 0)
}
findLongestWord('hello world w3c school education') // 9

116.说说你对cookie和session的理解

什么是Cookie?

  • HTTP是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息):每个请求都是完全独立的,服务端无法确认当前访问者的身份信息,无法分辨上一次的请求发送者和这一次的发送者是不是同一个人。所以服务器与浏览器为了进行会话跟踪(知道是谁在访问我),就必须主动的去维护一个状态,这个状态用于告知服务端前后两个请求是否来自同一浏览器。而这个状态需要通过 cookie 或者 session 去实现。

  • cookie存储在客户端:cookie是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器发送请求时被携带并发送到服务器上。

  • cookie是不可的:每个cookie都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(靠domain)

  • cookie重要的属性:

    • name=value健值对,设置cookie的名称及相应的值,都必须是字符串类型。

      如果值为unicode字符,需要转为字符编码
      如果值为二进制,需要转为base64编码
    • domain指定cookie所属域名,默认是当前域名,path指定cookie在哪个路径下生效,默认是’/‘。如果设置为/abc,则只有/abc下的路由可以访问到该cookie,如/abc/read。

    • maxAgeCookie:失效的时间,单位秒,如果为整数,则该cookie在maxAge秒后失效。如果为负数,则该cookie为临时cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该cookie。如果为0,表示删除该cookie。默认为-1。比expires好用。一般浏览器的 cookie 都是默认储存的,当关闭浏览器结束这个会话的时候,这个 cookie 也就会被删除。

    • expires:过期时间,在设置的某个时间点后该cookie就会失效。

    • secure:该cookie是否仅被使用安全协议传输。安全协议有HTTPS,SSL等。在网络上传输数据先将数据进行加密。默认是false,当secure为true时,cookie在http中是无效的,在https才有效。

    • httpOnly:如果给某个cookie设置来httpOnly属性,则无法通过js脚本读取到该cookie的信息,但是还是能够通过Application中手动修改cookie,所以只是在一定程度上可以防止 XSS 攻击,不是绝对的安全

什么是Session?

  • session是另一种记录服务器和客户端会话状态的机制

  • session是基于cookie实现的,session存储在服务端,sessionId会被存储在客户端的cookie中

  • session认证流程:

    • 用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的session

    • 请求返回将此session的唯一标识sessionId返回给浏览器

    • 浏览器接收到服务器返回的sessionId后会将该信息存储到cookie中,同时cookie将记录此sessionId属于哪个域名

    • 当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在cookie信息,如果存在自动将cookie信息也发送给服务器,服务端会从cookie中获取sessionId,再根据sessionId查找对于session信息,如果没有找到说明用户没有登录或者登录失效,如果找到session证明用户已经登录可执行后续操作。

  • sessionId是连接cookie和session的一道桥梁,大部分系统也是根据此原理来验证用户登录状态

cookie和session的区别?

  • 安全性:session比cookie安全,session是存储在服务端的,cookie是存储在客户端的
  • 存取值的类型不同: cookie只支持字符串数据,想要设置其他类型的数据,需要将其转换为字符串,session可以存任意数据类型。
  • 有效期不同:cookie可设置为长时间保持,比如我们经常使用的默认登录功能。session一般失效时间较短,客户端关闭或者session超时都会失效。
  • 存储大小不同:单个cookie存储数据不能超过4k,session可存储数据远高于cookie,但是当访问量过多,会占用过多的服务器资源。

117.实现单行文本居中和多行文本左对齐并超出显示”…”

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
.one {
text-align: center;
}
/* 只webkit内核 */
.multi {
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
}
/* after伪元素 */
.multi2 {
height: 2.8em;
line-height: 1.4;
overflow: hidden;
position: relative;
}
.multi2::after {
position: absolute;
right: 0;
bottom: 0;
content: '...';
height: 1.4em;
background: white;
padding: 0 5px;
}

118.说说你对eval的理解

eval() 函数会将传入的字符串当做 JavaScript 代码进行执行。

1
2
3
4
5
6
7
8
9
10
11
console.log(eval('2 + 2'));
// expected output: 4

console.log(eval(new String('2 + 2')));
// expected output: 2 + 2

console.log(eval('2 + 2') === eval('4'));
// expected output: true

console.log(eval('2 + 2') === eval(new String('2 + 2')));
// expected output: false

eval() 是全局对象的一个函数属性。

eval() 通常比其他替代方法更慢,因为它必须调用 JS 解释器,而许多其他结构则可被现代 JS 引擎进行优化。

不建议使用eval。eval() 是一个危险的函数,它使用与调用者相同的权限执行代码。如果你用 eval() 运行的字符串代码被恶意方(不怀好意的人)修改,您最终可能会在您的网页/扩展程序的权限下,在用户计算机上运行恶意代码。更重要的是,第三方代码可以看到某一个 eval() 被调用时的作用域,这也有可能导致一些不同方式的攻击

119.写出你知道的CSS水平和垂直居中的方法

如何居中一个元素

一、水平居中

1.行内元素水平居中

给块级父元素设置text-align: center;可使行内子元素水平居中,此方法对inlin、inline-block、inline-flex、inline-table、inline-grid水平居中都有效。

1
2
3
.parent {
text-align: center;
}

2.块级元素的水平居中

(1).将该块级元素左右外边距margin-left和margin-right设置为auto并设置宽度

1
2
3
4
.block {
width: 100px;
margin: 0 auto;
}

(2).使用table + margin, 此时元素宽度为内容宽度

1
2
3
4
.block {
margin: 0 auto;
display: table;
}

(3).absolute+transform

给父元素设置相对定位,子块元素设置绝对定位,利用left和transform将元素水平居中

1
2
3
4
5
6
7
8
.parent {
position: relative;
}
.blockClild {
position: absolute;
left: 50%;
transform: translateX(-50%);
}

(4).使用flex + justify-content

1
2
3
4
.block {
display: flex;
justify-content: center;
}

(5).使用flex + margin

给父元素设置flex,子元素设置margin: 0 auto;

1
2
3
4
5
6
.parent {
display: flex;
}
.blockClild {
margin: 0 auto;
}

3.多块级元素水平居中

(1).使用flex布局

1
2
3
4
5
6
7
8
9
10
<style>
.parent {
display: flex;
justify-content: center;
}
</style>
<div class="parent">
<div class="blockClild">block</div>
<div class="blockClild">block</div>
</div>

(2).使用inline-block

将要水平排列的块状元素设为display:inline-block,然后在父级元素上设置text-align:center,达到与上面的行内元素的水平居中一样的效果。

1
2
3
4
5
6
.parent {
text-align: center;
}
.blockClild {
display: inline-block;
}

二、垂直居中

1.单行内联元素垂直居中

1
2
3
4
5
6
7
8
9
<style>
.parent {
height: 120px;
line-height: 120px;
}
</style>
<div class="parent">
<span>childchildchildchildchildchildchildchildchildchild</span>
</div>

2.多行内联元素垂直居中

(1). 使用flex布局

1
2
3
4
5
6
7
8
9
10
11
12
13
<style>
.parent {
height: 120px;
display: flex;
flex-direction: column;
justify-content: center;
}
</style>
<div class="parent">
<span>hello world.</span>
<span>hello world.</span>
<span>hello world.</span>
</div>

(2).利用table布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
.parent {
height: 120px;
display: table;
background-color: bisque;
}
span {
background-color: pink;
display: table-cell;
vertical-align: middle;
}
</style>
<div class="parent">
<span>hello world.</span>
<span>hello world.</span>
<span>hello world.</span>
</div>

3.块级元素垂直居中

(1).使用absolute+transform

1
2
3
4
5
6
7
8
9
10
11
12
13
<style>
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
</style>
<div class="parent">
<div class="child">hello world.hello world.</div>
</div>

(2).使用flex+align-items

1
2
3
4
5
6
7
8
9
<style>
.parent {
display:flex;
align-items:center;
}
</style>
<div class="parent">
<div class="child">hello world.hello world.</div>
</div>

(4).使用table-cell+vertical-align

1
2
3
4
5
6
7
8
9
<style>
.parent {
display: table-cell;
vertical-align: middle;
}
</style>
<div class="parent">
<div class="child">hello world.hello world.</div>
</div>

三、水平垂直居中

(1).使用absolute+负边距(已知宽高)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
margin: -50px 0 0 -50px;
width: 100px;
height: 100px;
background-color: #666
}
</style>
<div class="parent">
<div class="child">center</div>
</div>

(2).绝对定位与margin:auto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<style>
.parent {
position: relative;
height:100px; /* 必须有个高度 */
}
.child {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
background-color: #666
}
</style>
<div class="parent">
<div class="child">center</div>
</div>

(3).绝对定位 + transform

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
<div class="parent">
<div class="child">center</div>
</div>

(4).flex布局

1
2
3
4
5
6
7
8
9
10
<style>
.parent {
display: flex;
justify-content: center;
align-items: center;
}
</style>
<div class="parent">
<div class="child">center</div>
</div>

120.说说你对模块化的理解

代码抽离重用,模块化开发,多人合作

  • AMD: require.js 为代表,依赖前置,一律先加载再使用。
  • CMD: sea.js 为代表,异步加载模块,依赖就近原则
  • UMD: 兼容AMD和commonJS规范的同时,还兼容全局引用的方式。
  • ES6 import/export

121.公钥加密和私钥加密是什么?

私钥加密,也称对称加密,使用一个密钥对内容进行加密和解密,加密算法可以是公开的,但密钥必须保密,常见的私钥加密算法有:DES、AES、RC5

公钥加密,也称非对称加密,使用两个密钥,一个公开密钥用来加密,另一个私有密钥用来解密,基于其特性,可以用作数字签名的功能(如 HTTPS),常见的公钥加密算法有:RSA

122.html5都有哪些新的特性?移除了哪些元素?

新增特性:

  • canvas
  • svg
  • video
  • drag & drop
  • localStorage/sessionStorage
  • 语义化标签: header/nav/section/article/footer
  • input 类型: date/datetime/email/range

移除元素:

  • applet
  • big
  • font
  • frame/frameset

123.怎么才能让图文不可复制?

1
2
3
4
5
-webkit-user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
user-select: none;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 禁止右键菜单
document.body.oncontextmenu = e => {
return false;
// e.preventDefault();
}
// 禁止文字选择
document.body.onselectstart = e => {
return false;
// e.preventDefault();
}
// 禁止复制
document.body.oncopy = e => {
return false;
// e.preventDefault();
}
// 禁止粘贴
document.body.onpaste = e => {
return false;
// e.preventDefault();
}

124.为什么会有跨域问题?怎么解决跨域?

查看跨域问题总结

125.怎么让英文单词的首字母大写?

1
2
3
4
5
6
7
.demo {
text-transform: capitalize; /* 单词的首字母转换为大写。*/
}
/* 或 */
.demo::first-letter {
text-transform: uppercase;
}

126.说说你对IIFE的理解

IIFE(立即调用函数表达式)是一个在定义时就会立即执行的 JavaScript 函数。独立作用域,避免变量冲突问题

1
2
3
(function () {
statements
})();

这是一个被称为 自执行匿名函数 的设计模式,主要包含两部分。第一部分是包围在 圆括号运算符 () 里的一个匿名函数,这个匿名函数拥有独立的词法作用域。这不仅避免了外界访问此 IIFE 中的变量,而且又不会污染全局作用域。

第二部分再一次使用 () 创建了一个立即执行函数表达式,JavaScript 引擎到此将直接执行函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
(function () {
var name = "Barry";
})();
// 无法从外部访问变量 name
name // 抛出错误:"Uncaught ReferenceError: name is not defined"

// 将 IIFE 分配给一个变量,不是存储 IIFE 本身,而是存储 IIFE 执行后返回的结果。
var result = (function () {
var name = "Barry";
return name;
})();
// IIFE 执行后返回的结果:
result; // "Barry"

127.window对象和document对象有什么区别?

window对象

window作为全局变量,代表了脚本正在运行的窗口,暴露给 Javascript 代码。
window 对象表示一个包含 DOM 文档的窗口,其 document 属性指向窗口中载入的 DOM 文档。

在有标签页功能的浏览器中,每个标签都拥有自己的 window 对象;也就是说,同一个窗口的标签页之间不会共享一个 window 对象。

有一些方法,如 window.resizeTo 和 window.resizeBy 之类的方法会作用于整个窗口而不是 window 对象所属的那个标签。一般而言,如果一样东西无法恰当地作用于标签,那么它就会作用于窗口。

document对象

Document 接口表示任何在浏览器中载入的网页,并作为网页内容的入口,也就是 DOM 树。
Document 接口描述了任何类型的文档的通用属性与方法。
每一个载入浏览器的HTML文档都会成为document对象。document对象使我们可以使用脚本(js)中对HTML页面中的所有元素进行访问。

128.重置(初始化)css的作用是什么?

清除不同浏览器默认的样式,让元素的样式统一。

129.如何让元素固定在页面底部?有哪些比较好的实践?

所谓 “Sticky Footer”,并不是什么新的前端概念和技术,它指的就是一种网页效果: 如果页面内容不足够长时,页脚固定在浏览器窗口的底部;如果内容足够长时,页脚固定在页面的最底部。 总而言之,就是页脚一直处于最底.

如何实现?

1
2
3
4
5
6
<body>
<div class="wrapper">
<div class="content">页面主体内容区域 </div>
</div>
<div class="footer">需要做到 Sticky Footer 效果的页脚</div>
</body>

1.使用flex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<style>
html,body {
height: 100%;
padding: 0;
margin: 0;
}
.wrapper {
min-height: 100%;
display: flex;
flex-direction: column;
margin-bottom: -50px;
}
.content {
flex: 1;
}
.footer {
height: 50px;
}
</style>

2.使用min-height + margin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
html,body {
height: 100%;
padding: 0;
margin: 0;
}
.wrapper {
min-height: 100%;
margin-bottom: -50px;
}
.footer {
height: 50px;
}
</style>

3.使用padding-bottom + margin上父间距

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
html,body {
height: 100%;
padding: 0;
margin: 0;
}
.wrapper {
min-height: 100%;
}
.content {
padding-bottom: 50px;
}
.footer {
height: 50px;
margin-top: -50px;
}
</style>

3.使用calc

1
2
3
4
5
6
7
8
9
10
11
12
13
<style>
html,body {
height: 100%;
padding: 0;
margin: 0;
}
.wrapper {
min-height: calc(100vh - 50px);
}
.footer {
height: 50px;
}
</style>

4.flex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<div class="content">
content
</div>
<footer class="footer"></footer>
</body>
<style>
html, body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
}
.content {
flex: 1 0 auto;
}
.footer {
flex-shrink: 0;
}
</style>

130.span与span之间有看不见的空白间隔是什么原因引起的?有什么解决办法?

产生空白的原因:元素被当成行内元素排版的时候,元素之间的空白符(空格、回车换行等)都会被浏览器转化为一个空白字符,字符大小受font-size的影响

解决方法:

1.父元素设置font-size为0,子元素单独再设置字体大小。

2.父元素设置display:flex;

3.子元素设置同方向float

131.说说video标签中预加载视频用到的属性是什么?

preload:
该枚举属性旨在提示浏览器,作者认为在播放视频之前,加载哪些内容会达到最佳的用户体验。可能是下列值之一:

  • none: 表示不应该预加载视频。
  • metadata: 表示仅预先获取视频的元数据(例如长度)。
  • auto: 表示可以下载整个视频文件,即使用户不希望使用它。
  • 空字符串: 和值为 auto 一致。每个浏览器的默认值都不相同,即使规范建议设置为 metadata。

132.手写一个满屏品字布局的方案

1.flex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<style>
.box {
height: 100%;
}
.row {
height: 50%;
display: flex;
justify-content: center;
}
.item {
flex: 0 0 50%;
height: 100%;
border: 1px solid;
}
</style>
<div class="box">
<div class="row">
<div class="item">1</div>
</div>
<div class="row">
<div class="item">2</div>
<div class="item">3</div>
</div>
</div>

2.标准流

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
<style>
.box {
height: 100%;
}
.row {
height: 50%;
width: 100%;
}
.item {
width: 50%;
height: 100%;
border: 1px solid;
display: inline-block;
}
.top {
height: 50%;
width: 50%;
margin: 0 auto;
border: 1px solid;
}
</style>
<div class="box">
<div class="top">1</div>

<div class="row">
<div class="item">2</div>
<div class="item">3</div>
</div>
</div>

3.浮动

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
<style>
.box {
height: 100%;
}
.row {
height: 50%;
width: 100%;
}
.item {
width: 50%;
height: 100%;
border: 1px solid;
float: left
}
.top {
height: 50%;
width: 50%;
margin: 0 auto;
border: 1px solid;
}
</style>
<div class="box">
<div class="top">1</div>

<div class="row">
<div class="item">2</div>
<div class="item">3</div>
</div>
</div>

133.深度克隆对象的方法有哪些?

1.es6 扩展运算符(浅拷贝)

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
// es6 扩展运算符
{
var obj = {
name: 'xiaoming',
info: {
age: 19,
obj: {
sex: 1
}
}
}
var deepObj = { ...obj }
deepObj.info.obj.sex = 2
console.log('obj', obj); // sex:2
// output: {
// name: 'xiaoming',
// info: {
// age: 19,
// obj: {
// sex: 2
// }
// }
// }
console.log('deepObj', deepObj); // sex:2
// output: {
// name: 'xiaoming',
// info: {
// age: 19,
// obj: {
// sex: 2
// }
// }
// }
}

2.Object.assign(浅拷贝)

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
// Object.assign
{
var obj = {
name: 'xiaoming',
info: {
age: 19,
obj: {
sex: 1
}
}
}
var deepObj = Object.assign({}, obj)
deepObj.info.obj.sex = 2
console.log('obj', obj); // sex:2
// output: {
// name: 'xiaoming',
// info: {
// age: 19,
// obj: {
// sex: 2
// }
// }
// }
console.log('deepObj', deepObj); // sex:2
// output: {
// name: 'xiaoming',
// info: {
// age: 19,
// obj: {
// sex: 2
// }
// }
// }
}

3.JSON.stringify的方式(深拷贝)

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
// JSON.stringify的方式
{
var obj = {
name: Symbol('xiaoming'),
info: {
age: 19,
obj: {
sex: 1
}
},
reg: /\d+/g,
fun: function() {
console.log('fun', this);
}
}
var deepObj = JSON.parse(JSON.stringify(obj))
deepObj.info.obj.sex = 2
console.log('obj', obj);
// output: {
// name: Symbol('xiaoming'),
// info: {
// age: 19,
// obj: {
// sex: 1
// }
// },
// reg: /\d+/g,
// fun: f()
// }
console.log('deepObj', deepObj);
// output: {
// info: {
// age: 19,
// obj: {
// sex: 1
// }
// },
// reg: {}, 正则
// 缺少fun,name
// }
}

es6语法糖和合并对象的方法都只能浅拷贝, 当出现对象中有多层级时只会独立拷贝第一层
JSON.stringify的方式虽然能实现深度拷贝, 但是如果对象中有出现方法、正则、Symbol的情况下 方法无法正常进行克隆

4.实现深拷贝

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
function getDataType(obj) {
var toString = Object.prototype.toString;
var map = {
'[object Array]': 'array',
'[object Object]': 'object',
'[object String]': 'string',
'[object Number]': 'number',
'[object Null]': 'null',
'[object Undefined]': 'undefined',
'[object Boolean]': 'boolean',
'[object RegExp]': 'regExp',
'[object Function]': 'function',
'[object Date]': 'date',
'[object Symbol]': 'symbol',
}
if (obj instanceof Element) {
return 'element'
}
return map[toString.call(obj)]
}

function deepClone(data) {
let type = getDataType(data)
let obj = type === 'array' ? [] : type === 'object' ? {} : false
if (!obj) return data
if (type === 'array') {
for (let i = 0; i < data.length; i++) {
obj.push(deepClone(data[i]))
}
} else if (type === 'object') {
for (const key in data) {
obj[key] = deepClone(data[key])
}
}
return obj
}
var obj = {
name: Symbol('xiaoming'),
info: {
age: 19,
reg: /\d+/g,
birth: new Date('1995-02-08'),
isSenior: true,
obj: {
sex: 1
}
},
fun: function() {
console.log('fun', this.info.obj.sex);
}
}
console.log('------------')
var target = deepClone(obj)
target.info.obj.sex = 2
target.info.reg = new RegExp()
console.log('obj', obj, obj.fun());
// output: fun 1
// obj {
// name: Symbol(xiaoming),
// info: {
// age: 19,
// birth: 'Wed Feb 08 1995 08:00:00 GMT+0800 (中国标准时间)',
// isSenior: true,
// reg: /\d+/g,
// obj: {
// sex: 1
// }
// },
// fun: f()
// }
console.log('target', target, target.fun());
// output: fun 2
// target {
// name: Symbol(xiaoming),
// info: {
// age: 19,
// birth: 'Wed Feb 08 1995 08:00:00 GMT+0800 (中国标准时间)',
// isSenior: true,
// reg: /(?:)/g,
// obj: {
// sex: 2
// }
// },
// fun: f()
// }

134.使用js库的download来下载资源

html5的a标签的download属性可以下载资源,但是需要同源,如果浏览器可以解析也会之间打开。
可以使用第三方库download来实现更完整的下载功能。

download.js 相关资源:

使用:

download.js 库提供了 download() 函数用于下载文件。

下载内容可以是 URL、字符串、Blob 或类型化的数据数组,或者通过将文件数据表示为 base64 或 url 编码字符串的 dataURL。

无论输入格式如何,download() 都使用指定的文件名和 mime 信息以与使用 Content-Disposition HTTP 标头的服务器相同的方式保存文件。

语法:download(data, strFileName, strMimeType);

  • data - 下载的数据内容,可以是 Blob、File、String 或 dataURL。
  • strFileName - 要创建的文件的名称。
  • strMimeType - 要下载的文件的 MIME 内容类型

文本下载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 字符串
download("hello world", "dlText.txt", "text/plain");

// dataURL
download("data:text/plain,hello%20world", "dlDataUrlText.txt", "text/plain");

// blob
download(new Blob(["hello world"]), "dlTextBlob.txt", "text/plain");

// url
download("/robots.txt");

// unit8文本数组
var str= "hello world", arr= new Uint8Array(str.length);
str.split("").forEach(function(a,b){
arr[b]=a.charCodeAt();
});

download(arr, "textUInt8Array.txt", "text/plain" );

html下载:

1
2
3
4
5
6
7
8
9
10
11
// html 字符串实例:
download(document.documentElement.outerHTML, "dlHTML.html", "text/html");

// html Blob 实例:
download(new Blob(["hello world".bold()]), "dlHtmlBlob.html", "text/html");

// ajax 回调实例:
$.ajax({
url: "/download.html",
success: download.bind(true, "text/html", "dlAjaxCallback.html")
});

二进制文件:

1
2
3
4
5
6
7
8
9
10
11
// 图片 URL
download("https://img1.baidu.com/it/u=3155988012,1977937542&fm=253&app=138&size=w931&n=0&f=JPG&fmt=auto?sec=1670432400&t=43e5ed572796b21d99c7fd46b71bbf51")

// 异步下载图片:
var x=new XMLHttpRequest();
x.open( "GET", "https://img1.baidu.com/it/u=3155988012,1977937542&fm=253&app=138&size=w931&n=0&f=JPG&fmt=auto?sec=1670432400&t=43e5ed572796b21d99c7fd46b71bbf51" , true);
x.responseType="blob";
x.onload= function(e){
download(e.target.response, "awesomesauce.png", "image/png");
};
x.send();

135.JavaScript 实现复制功能

一、使用js代码
clipboard API的writeText()或write()方法来指定数据覆盖剪贴板内容。

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
<p>单击按钮以复制输入框中的文本,然后尝试将文本(例如 ctrl+v)粘贴到不同的窗口中,以查看效果。</p>

<input type="text" value="你复制的内容" id="myInput">
<button onclick="copyF()">复制</button>
<p>可以尝试粘贴到以下输入框:</p>
<textarea></textarea>

<script>
function copyF() {
/* 获取文本内容 */
var copyText = document.getElementById("myInput");

/* 选择复制内容 */
copyText.select();
copyText.setSelectionRange(0, 99999); /* 为移动设备设置 */

// 给定 API 的用户权限状态
navigator.permissions.query({name: 'clipboard-write'}).then(res => {
// document.hasFocus()方法返回一个 Boolean,表明当前文档或者当前文档内的节点是否获得了焦点
// 'granted', 'denied', or 'prompt' 同意、拒绝、提示
if (document.hasFocus() && ['granted', 'prompt'].includes(res.state)) {
/* 复制内容到文本域 */
navigator.clipboard.writeText(copyText.value);
/* 弹出已复制的内容 */
console.log("复制的文本为: " + copyText.value);
}
}).catch((err) => {
console.log('fail',err)
})
}
</script>

注:必须使当前文档获取焦点,否则复制无效并报错Document is not focused

二、使用第三方库 clipboard.js(推荐,兼容性强)

直接使用国内 CDN 库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<p>单击按钮以复制输入框中的文本,然后尝试将文本(例如 ctrl+v)粘贴到不同的窗口中,以查看效果。</p>

<input type="text" value="你复制的内容" id="myInput">
<button id="copyInput" onclick="copyF()">复制</button>
<p>可以尝试粘贴到以下输入框:</p>
<textarea></textarea>

<script src="https://cdn.staticfile.org/clipboard.js/2.0.4/clipboard.min.js"></script>
<script>
function copyF() {
new ClipboardJS('#copyInput', {
text: function(trigger) {
return document.getElementById("myInput").value;
}
}).on('success', function(e) {
console.log("复制成功!!!");
e.clearSelection();
}).on('error', function(e) {
console.log('Error!');
});
}
</script>

136.http,https,http2的了解

1.http:

http是超文本传输协议,也就是HyperText Transfer Protocaol。
HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。
HTTP 是无状态协议,这意味着服务器不会在两个请求之间保留任何数据(状态)。
尽管通常基于 TCP/IP 层,但它可以在任何可靠的传输层上使用
HTTP 遵循经典的客户端 - 服务端模型,客户端打开一个连接以发出请求,然后等待直到收到服务器端响应,请求-应答的通信模式。
信息是明文传输,存在安全隐患。

2.https:

HTTPS(超文本传输安全协议)是 HTTP 协议的加密版本.
它使用 SSL 或 TLS 协议来加密客户端和服务器之间所有的通信.
HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换资料的隐私与完整性。

与HTTP的差异:

  • HTTP的URL是由”http://“起始与默认使用端口80,而HTTPS的URL则是由”https://“起始与默认使用端口443。

  • HTTP不是安全的,而且攻击者可以通过监听和中间人攻击等手段,获取网站帐户和敏感信息等。HTTPS的设计可以防止前述攻击,在正确配置时是安全的。

  • HTTPS连接需要证书:由证书颁发机构签发的证书有免费的,也有每年收费数美元到数千美元不等的。
    一个组织也可能有自己的证书颁发机构,尤其是当设置浏览器来访问他们自己的网站时(如,运行在公司或学校局域网内的网站)。他们可以容易地将自己的证书加入浏览器中。

  • HTTP协议和HTTPS安全协议同属于应用层,具体来讲,安全协议工作在HTTP之下,传输层之上:安全协议向运行HTTP的进程提供一个类似于TCP的套接字,供进程向其中注入报文,安全协议将报文加密并注入运输层套接字;或是从运输层获取加密报文,解密后交给对应的进程。严格地讲,HTTPS并不是一个单独的协议,而是对工作在一加密连接(TLS或SSL)上的常规HTTP协议的称呼。

3.http/2:

HTTP/2(超文本传输协议第2版,最初命名为HTTP 2.0),HTTP/2主要基于SPDY协议.
通过以下举措,减少网络延迟,提高浏览器的页面加载速度:

  • 对HTTP头字段进行数据压缩(即HPACK算法);
  • HTTP/2服务端推送(Server Push);
  • 请求流水线;
  • 修复HTTP/1.0版本以来未修复的队头阻塞问题;
  • 对数据传输采用多路复用,让多个请求合并在同一TCP连接内。
  • 支持现有的HTTP应用场景,包括桌面和移动设备浏览器、网络API、不同规格的网络服务器和正向代理、反向代理服务器软件、防火墙和CDN等。

HTTP/2与HTTP/1.1比较:

HTTP/2相比HTTP/1.1的修改并不会破坏现有程序的工作,但是新的程序可以借由新特性得到更好的速度。新增的性能改进不仅包括HTTP/1.1中已有的多路复用,修复队头阻塞问题,允许设置设定请求优先级,还包含了一个头部压缩算法(HPACK)。此外, HTTP/2采用了二进制而非明文来打包、传输客户端和服务器之间的数据。

HTTP/2保留了HTTP/1.1的大部分语义,例如请求方法、状态码乃至URI和绝大多数HTTP头字段一致。而HTTP/2采用了新的方法来编码、传输客户端和服务器之间的数据。

HTTP/2引入了服务器推送,即服务端向客户端发送比客户端请求更多的数据。这允许服务器直接提供浏览器渲染页面所需资源,而无须浏览器在收到、解析页面后再提起一轮请求,节约了加载时间。

HTTP/1.1与SPDY的区别:

SPDY(发音同“speedy”)是一个由Google主导的HTTP替代协议。SPDY一开始主要关注降低延迟,采用了TCP通道,但是使用了不同的协议来达到此目的。其与HTTP/1.1相比,主要的改变有:

  • 实现无需先入先出的多路复用
  • 为简化客户端和服务器开发的消息—帧机制
  • 强制性压缩(包括HTTP头部)
  • 优先级排序
  • 双向通讯

137.xml和html有什么区别?

XML可扩展标记语言是w3c指定的一种标记语言。允许用户定义自己的标签更加灵活。
XML是数据描述性语言,HTML时陈述性语言。
规则:

  1. 必须有声明语句,XML声明是XML文档的第一句
  2. 区分大小写
  3. XML文档有且只有一个根元素,就是紧接着声明后面建立的第一个元素
  4. 属性值使用引号(在HTML代码里面,属性值可以加引号,也可以不加。但是XML规定,所有属性值必须加引号(可以是单引号,也可以是双引号,建议使用双引号),否则将被视为错误)
  5. 所有的标记必须有相应的结束标记,在HTML中,标记可以不成对出现
  6. 所有的空标记也必须被关闭

HTML(超文本标记语言——HyperText Markup Language),HTML 标签里的元素名不区分大小写。

XML与HTML区别:

(1)可扩展性方面:HTML不允许用户自行定义他们自己的标识或属性,而在XML中,用户能够根据需要自行定义新的标识及属性名,以便更好地从语义上修饰数据。

(2)结构性方面:HTML不支持深层的结构描述,XML的文件结构嵌套可以复杂到任意程度,能表示面向对象的等级层次。

(3)可校验性方面:HTML没有提供规范文件以支持应用软件对HTML文件进行结构校验,而XML文件可以包括一个语法描述,使应用程序可以对此文件进行结构校验。

138.写出几种创建对象的方式,并说说他们的区别是什么?

第一种:字面量

1
var o1 = {name: "o1"}

第二种:new实例化

1
var o2 = new Object({name: "o2"})

第三种:通过构造函数

1
2
var M = function(name){this.name = name}
var o3 = new M("o3")

第四种:Object.create()

1
2
var p = {name: "p"}
var o4 = Object.create(p)

查看javascript的Object.create方法

139.页面中怎么嵌入Flash?有哪些方法?写出来

1.embed标签,标签的作用是在 HTML 页面中嵌入多媒体元素。

1
<embed src="intro.swf" height="200" width="200">

embed元素没有关闭标签。 不能使用替代文本。
HTML4 无法识别embed标签。您的页面无法通过验证。
如果浏览器不支持 Flash,那么视频将无法播放.
iPad 和 iPhone 不能显示 Flash 视频。
如果您将视频转换为其他格式,那么它仍然不能在所有浏览器中播放。

2.object标签,用于包含对象,比如图像、音频、视频、Java applets、ActiveX、PDF 以及 Flash。

1
<object data="intro.swf" height="200" width="200"></object>

如果浏览器不支持 Flash,那么视频将无法播放.
iPad 和 iPhone 不能显示 Flash 视频。
如果您将视频转换为其他格式,那么它仍然不能在所有浏览器中播放。

140.说说你对媒体查询的理解

媒体查询(Media queries)非常实用,尤其是当你想要根据设备的大致类型(如打印设备与带屏幕的设备)或者特定的特征和设备参数(例如屏幕分辨率和浏览器视窗宽度)来修改网站或应用程序时.
媒体查询通常用于一下目的:

  • 有条件的通过@media和@import rules用css装饰样式
  • 用media= 属性为<style>,<link>, <source>和其他HTML元素指定特定的媒体类型。如:
1
2
<link rel="stylesheet" src="styles.css" media="screen" />
<link rel="stylesheet" src="styles.css" media="print" />
  • 使用Window.matchMedia() 和MediaQueryList.addListener() 方法来测试和监控媒体状态。

141.写一个使两个整数进行交换的方法(不能使用临时变量)

1.利用运算符优先级和0*

1
b = a + 0 * (a = b);

2.利用执行顺序

1
2
3
a = a + b;
b = a - b;
a = a - b;

3.异或取值

1
2
3
a ^= b;
b ^= a;
a ^= b;

4.es6解构

1
2
let a = 1, b= 2
[a, b] = [b, a]

142.HTML5如何使用音频和视频?

video视频:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<video controls width="250">
<source src="/media/cc0-videos/flower.webm"
type="video/webm">

<source src="/media/cc0-videos/flower.mp4"
type="video/mp4">

Download the
<a href="/media/cc0-videos/flower.webm">WEBM</a>
or
<a href="/media/cc0-videos/flower.mp4">MP4</a>
video.
<!-- 在不支持 video 元素的浏览器中,<video></video> 标签中间的内容会显示,
作为降级处理。 -->
</video>

属性:

  • autoplay: 布尔属性;声明该属性后,视频会尽快自动开始播放,不会停下来等待数据全部加载完成。
  • controls: 加上这个属性,浏览器会在视频底部提供一个控制面板,允许用户控制视频的播放,包括音量,跨帧,暂停/恢复播放。
  • crossorigin: 该枚举属性指明是否使用 CORS(跨域资源共享)来获取相关视频.取值如下:
    • anonymous: 在发送跨域请求时不携带凭证(credential)信息
    • use-credentials: 在发送跨域请求时携带凭证(credential)信息
  • height: 视频显示区域的高度,单位是 CSS 像素(仅限绝对值;不支持百分比)。
  • width: 视频显示区域的宽度,单位是 CSS 像素(仅限绝对值;不支持百分比).
  • loop: 布尔属性;指定后,会在视频播放结束的时候,自动返回视频开始的地方,继续播放。
  • muted: 布尔属性,指明在视频中音频的默认设置。设置后,音频会初始化为静音。默认值是 false, 意味着视频播放的时候音频也会播放(不静音)。
  • poster:海报帧图片 URL,用于在视频处于下载中的状态时显示。如果未指定该属性,则在视频第一帧可用之前不会显示任何内容,然后将视频的第一帧会作为海报(poster)帧来显示。
  • preload:该枚举属性旨在提示浏览器,作者认为在播放视频之前,加载哪些内容会达到最佳的用户体验。可能是下列值之一:
    • none: 表示不应该预加载视频。
    • metadata: 表示仅预先获取视频的元数据(例如长度)。
    • auto: 表示可以下载整个视频文件,即使用户不希望使用它。
    • 空字符串: 和值为 auto 一致。每个浏览器的默认值都不相同,即使规范建议设置为 metadata。
  • src: 要嵌到页面的视频的 URL。可选;你也可以使用 video 块内的 <source> 元素来指定需要嵌到页面的视频。

audio音频:

<audio> 元素可以包含一个或多个音频资源,这些音频资源可以使用 src 属性或者<source> 元素来进行描述:浏览器将会选择最合适的一个来使用

1
2
3
4
5
6
7
8
<audio
controls
src="/media/cc0-audio/t-rex-roar.mp3">
<a href="/media/cc0-audio/t-rex-roar.mp3">
Download audio
</a>
<!-- 在浏览器不支持该元素时,会显示 <audio></audio> 标签之间的内容作为回退。 -->
</audio>

属性:

  • autoplay: 布尔属性;声明该属性后,音频会尽快自动开始播放,不会停下来等待数据全部加载完成。
  • controls: 如果声明了该属性,浏览器将提供一个包含声音,播放进度,播放暂停的控制面板,让用户可以控制音频的播放。
  • crossorigin: 该枚举属性指明是否使用 CORS(跨域资源共享)来获取相关音频.取值如下:
    • anonymous: 在发送跨域请求时不携带凭证(credential)信息
    • use-credentials: 在发送跨域请求时携带凭证(credential)信息
  • currentTime:读取 currentTime 属性将返回一个双精度浮点值,用以标明以秒为单位的当前音频的播放位置
  • loop: 布尔属性;如果声明该属性,将循环播放音频。
  • muted: 表示是否静音的布尔值。默认值为 false,表示有声音。
  • preload:枚举属性,让开发者自行思考来示意浏览器使用何种加载方式以达到最好的用户体验。可以是以下属性之一:
    • none: 示意用户可能不会播放该音频,或者服务器希望节省带宽;换句话说,该音频不会被缓存;
    • metadata: 示意即使用户可能不会播放该音频,但获取元数据 (例如音频长度) 还是有必要的。
    • auto: 示意用户可能会播放音频;换句话说,如果有必要,整个音频都将被加载,即使用户不期望使用。
    • 空字符串 : 等效于auto属性。不同浏览器会有自己的默认值,规范建议的默认值为 metadata。
  • src: 要嵌到页面的音频的 URL。可选;你也可以使用 audio 块内的 <source> 元素来指定需要嵌到页面的音频。

143.请说说你对事件冒泡机制的理解?

DOM事件模型分为捕获和冒泡。一个事件发生后,会在子元素和父元素之间传播(propagation)。这种传播分成三个阶段

1.捕获阶段:事件从window对象自上而下向目标节点传播的阶段
2.目标阶段:真正的目标节点正在处理事件的阶段
3.冒泡阶段:事件从目标节点自下而上向window对象传播的阶段

事件委托:冒泡还允许我们利用事件委托——这个概念依赖于这样一个事实,如果你想要在大量子元素中单击任何一个都可以运行一段代码,您可以将事件监听器设置在其父节点上,并让子节点上发生的事件冒泡到父节点上,而不是每个子节点单独设置事件监听器。

event.preventDefault();阻止默认事件的发生,比如链接跳转,表单提交
event.stopPropagation();阻止事件流在dom结构中传播,取消后续的事件捕获或冒泡。
event.stopImmediatePropagation();用于取消后续事件捕获或事件冒泡,并阻止调用任何后续事件处理程序。

144.说说你对WEB标准和W3C的理解与认识?

个人理解:

  • html - 表示人的光身体 —结构
  • css - 表示给人穿的衣服 —表现
  • js - 表示人的行为,走路等 —行为

web简单来说可以分为结构、表现和行为。

  • 其中结构主要是由HTML标签组成。
  • 表现是指css样式表,可用通过css使页面标签更具美感。
  • 行为是指用户和页面有一定的交互,同时结构和表现也会发生变化,主要由js组成

web标准一般是将该三部分独立分开,使其更具有模块化。但一般产生行为时,就会有结构或者表现的变化,也使这三者的界限并不那么清晰。

W3C对web标准提出了规范化的要求,也就是在实际编程中的一些代码规范:

  • 对于结构要求(标签规范可以提高搜索引擎对页面的抓取率,对seo很有帮助):
    标签要小写
    标签要闭合
    标签不能随意嵌套

  • 对于css和js来说:
    使用外链css和js,使结构、表现、行为三者分离。
    提高页面渲染速度,提高用户体验
    尽量少使用行内样式,使结构和表现分离,标签的id和class要见文知意,标签越少,加载越快,用户体验越高
    不需要变动页面内容,便可提供打印版本而不需要复制内容,提高网站易用性。

145.你知道全屏滚动的原理是什么吗?它用到了CSS的哪些属性?

css的overflow:hidden,配合transition : all 1s ease;

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
/* html, body设置 overflow 为 hidden, 让视图中只包括一个分页;设置滑动分页的长宽都是 100%; 外部容器设置 transition 过渡效果, 并设置为相对定位, 滚动是修改外部容器的 Top 值, 实现滚动效果. */
html,
body {
padding: 0;
margin: 0;
overflow: hidden;
}
.page-container {
position: relative;
top: 0;
transition: all 1000ms ease;
touch-action: none;
}
.page-item {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<!-- 初始三个分页 -->
<div class="page-container">
<div class="page-item">1</div>
<div class="page-item">2</div>
<div class="page-item">3</div>
</div>
<script>
var container = document.querySelector('.page-container')
// 获取根元素高度, 页面可视高度
var viewHeight = document.documentElement.clientHeight
// 获取滚动的页数
var pageNum = document.querySelectorAll('.page-item').length
// 初始化当前位置, 距离原始顶部距离
var currentPosition = 0
// 设置页面高度 容器高度设置为窗口高度
container.style.height = viewHeight + 'px'

// 初始化滚动事件:向下滚动时, 当 currentPosition 比 -整体分页高度 大的时候(绝对值相比小的时候), 向下滚动;向上滚动时, 当 currentPosition 大于 0 的时候, 向上滚动.
// 向下滚动页面
function goDown () {
if (currentPosition > - viewHeight * (pageNum - 1)) {
currentPosition = currentPosition - viewHeight
console.log('down', currentPosition)
container.style.top = currentPosition + 'px'
}
}

// 向上滚动页面
function goUp () {
if (currentPosition < 0) {
currentPosition = currentPosition + viewHeight
container.style.top = currentPosition + 'px'
}
}
// 节流函数:即在规定时间内只会触发一次指定方法, 用于滚动时防止多次触发
function throttle (fn, delay) {
let baseTime = 0
return function () {
const currentTime = Date.now()
if (baseTime + delay < currentTime) {
fn.apply(this, arguments)
baseTime = currentTime
}
}
}
// 监听鼠标滚动:滚动事件firefox与其他浏览器的事件不同, 所以需要进行判断. deltaY大于0的时候, 向下滚动; 反之, 向上滚动.
var handlerWheel = throttle(scrollMove, 1000)
// https://developer.mozilla.org/en-US/docs/Web/API/Element/mousewheel_event#The_detail_property
// firefox的页面滚动事件其他浏览器不一样
if (navigator.userAgent.toLowerCase().indexOf('firefox') === -1) {
document.addEventListener('mousewheel', handlerWheel)
} else {
document.addEventListener('DOMMouseScroll', handlerWheel)
}
function scrollMove (e) {
console.log(e.deltaY)
if (e.deltaY > 0) {
goDown()
} else {
goUp()
}
}

// 监听移动端touch操作:当 touch 的最终位置大于起始位置时, 则页面向上滚动; 反之, 向下滚动.

var touchStartY = 0
document.addEventListener('touchstart', event => {
touchStartY = event.touches[0].pageY
})
var handleTouchEnd = throttle(touchEnd, 500)
document.addEventListener('touchend', handleTouchEnd)
function touchEnd (e) {
var touchEndY = e.changedTouches[0].pageY
if (touchEndY - touchStartY < 0) { // 向上滑动, 页面向下滚动
goDown()
} else {
goUp()
}
}
</script>
</body>
</html>

146.你对事件循环有了解吗?说说看

  • 同步任务:在主线程上执行的任务,只有前一个任务执行完,才能执行下一个任务

  • 异步任务:不进入主线程而进入“任务队列”的任务,只有任务队列通知主线程,某个任务可以执行了,该任务才会进入主线程执行。

    异步执行的运行机制如下。(同步执行也是如此,因为它可以被视为没有异步任务的异步执行。):
    1)所以同步任务都在主线程执行,形成一个执行栈
    2)主线程之外,还有一个任务队列,只要异步任务有了执行结果,就在任务队列放置一个事件
    3)一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,看看有哪些事件,对应的事件就结束等待状态,进入执行栈进行执行
    4)主线程不断重复第三步

主线程从“任务队列”中读取事件,这个事件是循环不断的,又称为事件循环(Event loop)

js是单线程非阻塞的脚本语言,意味着代码在js执行的任何时候只有一个主线程来处理所有任务。而非阻塞是指当代码需要异步处理的时候,主线程会挂起这个任务,当异步任务处理完毕后,主线程再根据一定规则去执行相应的回调。

当任务处理完毕,js会将这个事件加入一个队列,这个队列叫做事件队列。被放入事件队列中的事件不会立刻执行其回调,而是等待执行栈中所有任务都执行完毕后,主线程会查询事件队列中是否有任务。

异步任务分为:宏任务和微任务,不同类型的任务会被分配到不同的任务队列中。

当执行栈中所有任务都执行完毕后,会去检查微任务队列是否有事件存在,如果存在,会依次执行任务队列对应的回调,直到为空。然后去宏任务队列中取出一个事件,把对应的回调加入到当前执行战,当执行栈中所有任务都执行完毕后,检查为任务队列是否有事件存在。无限重复此过程,就形成了循环,这个循环就叫做事件循环。

微任务包括但不限于以下几种:

  • Promise.then
  • MutationObserver
  • Object.observe
  • process.nextTick

宏任务包括但不限于以下几种:

  • setTimeout
  • setInterval
  • setImmediate
  • MessageChannel
  • requestAnimationFrame
  • I/O
  • UI交互事件

147.说说你对target=”_blank”的理解?有啥安全性问题?如何防范?

如果此文档可以安全地显示,则需要一个新的未命名窗口或标签来显示链接的内容。如果用户代理不支持多个窗口/选项卡,则结果与_top 相同。

问题:
在调用window下的open方法创建一个新窗口的同时,可以获得一个创建窗口的opener句柄,通过target=”_blank”点开的窗口或者标签页,子窗口也能捕获opener句柄,通过这个句柄,子窗口可以访问到父窗口的一些属性,虽然很有限,但是却可以修改父窗口的页面地址,让父窗口显示指定的页面。

防范:
如果需要限制window.opener的访问行为,我们只需要在原始页面每个使用了target=”_blank”的链接中加上一个rel=”noopener”属性。
但是,火狐并不支持这个属性值,火狐浏览器里需要写成rel=”noreferrer”,所以我们可以将两个属性值合并写成rel=”noopener noreferrer”来完整覆盖。

1
<a href="https://www.baidu.com" target="_blank" rel="noopener noreferrer nofollow">内容</a>

nofollow 是HTML页面中a标签的属性值。这个标签的意义是告诉搜索引擎”不要追踪此网页上的链接或不要追踪此特定链接”。

148.写个还剩下多少天过年的倒计时

1
Math.floor((new Date(new Date().getFullYear() + 1, 0, 1) - Date.now()) / (1000 * 60 * 60 * 24)) - 1

149.列举CSS优化、提高性能的方法

加载性能.

压缩CSS
通过link方式加载,而不是@import
复合属性其实分开写,执行效率更高,因为CSS最终也还是要去解析如 margin-left: left;

选择器性能
尽量少的使用嵌套,可以采用BEM的方式来解决命名冲突
尽量少甚至是不使用标签选择器,这个性能实在是差,同样的还有*选择器
利用继承,减少代码量

渲染性能
慎重使用高性能属性:浮动、定位;
尽量减少页面重排、重绘;
css雪碧图
自定义web字体,尽量少用
尽量减少使用昂贵属性,如box-shadow/border-radius/filter/透明度/:nth-child等
使用transform来变换而不是宽高等会造成重绘的属性

150.请写出一个函数求出N的阶乘(即N!)

1
2
3
4
function factorial(n) {
if (n > 1) return n*factorial(n-1);
return 1;
}

151.如何实现换肤功能?

一、使用link引入不同主题css,利用js设置link disabled加载不同样式表
image

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>换肤</title>
<link rel="alternate stylesheet" type="text/css" href="red.css" title="红色">
<link rel="alternate stylesheet" type="text/css" href="green.css" title="绿色">
<link rel="stylesheet" type="text/css" href="default.css" title="默认">
<style>
html, body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div>
换肤:
<input id="default" name="skin" type="radio" value="default.css" checked><label for="default">默认</label>
<input id="red" name="skin" type="radio" value="red.css"><label for="red">红色</label>
<input id="green" name="skin" type="radio" value="green.css"><label for="green">绿色</label>
</div>
<div class="container">
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
Web Worker 有以下几个使用注意点。
</div>
<script>
const $ = document.querySelectorAll.bind(document)
var links = $('link[title]');
var radios = $('input[type=radio]');
[].slice.call(radios).forEach(radio => {
radio.addEventListener('click', function() {
var value = this.value;
[].slice.call(links).forEach(function (link) {
link.disabled = true // 必须先设置为true
if (link.getAttribute('href') == value) {
link.disabled = false
}
})
})
})
</script>
</body>
</html>

二、使用全局变量 var
换肤

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
--textColor: blue;
}
.container {
color: var(--textColor);
}
</style>
</head>
<body>
<div>
换肤:
<input id="default" name="skin" type="radio" value="blue" checked><label for="default">默认</label>
<input id="red" name="skin" type="radio" value="red"><label for="red">红色</label>
<input id="green" name="skin" type="radio" value="green"><label for="green">绿色</label>
</div>
<div class="container">
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
Web Worker 有以下几个使用注意点。
</div>
<script>
const $ = document.querySelectorAll.bind(document)
var radios = $('input[type=radio]');
[].slice.call(radios).forEach(radio => {
radio.addEventListener('click', function() {
var value = this.value;
document.body.style.setProperty('--textColor', value)
})
})
</script>
</body>
</html>

<!-- 或者 -->
<!DOCTYPE html>
<html lang="en" data-theme="default">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>换肤</title>
<style>
:root {
--textColor: blue;
}
[data-theme="red"] {
--textColor: red;
}
[data-theme="green"] {
--textColor: green;
}
.container {
color: var(--textColor);
}
</style>
</head>
<body>
<div>
换肤:
<input id="default" name="skin" type="radio" value="default" checked><label for="default">默认</label>
<input id="red" name="skin" type="radio" value="red"><label for="red">红色</label>
<input id="green" name="skin" type="radio" value="green"><label for="green">绿色</label>
</div>
<div class="container">
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
Web Worker 有以下几个使用注意点。
</div>
<script>
const $ = document.querySelectorAll.bind(document)
const html = $('html')[0]
var radios = $('input[type=radio]');
[].slice.call(radios).forEach(radio => {
radio.addEventListener('click', function() {
var value = this.value;
html.setAttribute('data-theme', value)
})
})
</script>
</body>
</html>

三、使用css命名空间
images

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.red-theme .container {
color: red;
}
.green-theme .container {
color: green;
}
.container {
color: blue;
}
</style>
</head>
<body>
<div>
换肤:
<input id="default" name="skin" type="radio" value="" checked><label for="default">默认</label>
<input id="red" name="skin" type="radio" value="red"><label for="red">红色</label>
<input id="green" name="skin" type="radio" value="green"><label for="green">绿色</label>
</div>
<div class="container">
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
Web Worker 有以下几个使用注意点。
</div>
<script>
const $ = document.querySelectorAll.bind(document)
var radios = $('input[type=radio]');
[].slice.call(radios).forEach(radio => {
radio.addEventListener('click', function() {
var value = this.value;
document.body.className = value ? value + '-theme' : ''
})
})
</script>
</body>
</html>

152.如何取消promise

153.如何捕获 setTimeout 异常

try catch 是捕获同步异常的。这里可以用 promise 来捕获,异步错误会触发 reject 函数

1
2
3
4
5
6
7
new Promise((resolve, reject) => {
setTimeout(()=> {
resolve()
}, 2000)
}).catch(err => {
console.log('异常捕获')
})

154.fetch 和 ajax 区别

fetch:

全局的 fetch() 方法用于发起获取资源的请求。它返回一个 promise,这个 promise 会在请求响应后被 resolve,并传回 Response 对象。

当遇到网络错误时,fetch() 返回的 promise 会被 reject,并传回 TypeError,虽然这也可能因为权限或其它问题导致。成功的 fetch() 检查不仅要包括 promise 被 resolve,还要包括 Response.ok 属性为 true。HTTP 404 状态并不被认为是网络错误。

语法:

1
Promise<Response> fetch(input[, init]);

input: 定义要获取的资源,可能是url或Request对象
init: 可选,一个配置项对象,包括所有对请求的设置,method,headers,mode, credentials,cache,redirect,referrer,referrerPolicy,integrity

返回值:一个 Promise,resolve 时回传 Response 对象。

ajax:

AJAX 是异步的 JavaScript 和 XML(Asynchronous JavaScript And XML)。简单点说,就是使用 XMLHttpRequest 对象与服务器通信.

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
<button id="ajaxButton" type="button">Make a request</button>

<script>
(function() {
var httpRequest;
document.getElementById("ajaxButton").addEventListener('click', makeRequest);

function makeRequest() {
httpRequest = new XMLHttpRequest();

if (!httpRequest) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
httpRequest.onreadystatechange = alertContents;
httpRequest.open('GET', 'test.html');
httpRequest.send();
}

function alertContents() {
try {
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
alert(httpRequest.responseText);
} else {
alert('There was a problem with the request.');
}
}
}
catch( e ) {
alert('Caught Exception: ' + e.description);
}
}

})();
</script>

fetch和ajax区别:

  • 当接收代表错误的状态码,从fetch返回的promise不会被标记为reject,即使响应http状态码为404或500.相反,它会将 Promise 状态标记为 resolve(如果响应的 HTTP 状态码不在 200 - 299 的范围内,则设置 resolve 返回值的 ok 属性为 false),仅当网络故障时或请求被阻止时,才会标记为 reject。
  • fetch 不会发送跨域 cookie,除非你使用了 credentials 的初始化选项。
1
2
3
fetch(url, {
credentials: 'same-origin'
})

一个简单的fetch请求:

1
2
3
fetch("http://pmcp-gateway.dev.hxss.com.cn/gateway/client")
.then(res => res.json())
.then(data => console.log(data))

155.form表单是怎么上传文件的?你了解它的原理吗?

1
2
3
4
5
6
7
8
9
<form method="post" enctype="multipart/form-data">
<div>
<label for="file">选择要上传的文件</label>
<input type="file" id="file" name="file" multiple />
</div>
<div>
<button>提交</button>
</div>
</form>

文件input的value属性包含了一个字符串,表示已选择文件的路径。如果用户没有选择任何文件,则该值为空字符串(””)。如果用户选择了多个文件,则 value 表示他们选择的文件列表中的第一个文件。

注:为了阻止恶意软件猜测文件路径,该值的字符串表示总是以 C:\fakepath\ 为前缀的文件名,而并不是文件的真实路径。

accept:是一个字符串,它定义了文件 input 应该接受的文件类型。这个字符串是一个以逗号为分隔的唯一文件类型说明符列表。

capture 属性是一个字符串,如果 accept (en-US) 属性指出了 input 是图片或者视频类型,则它指定了使用哪个摄像头去获取这些数据。值 user 表示应该使用前置摄像头和(或)麦克风。值 environment 表示应该使用后置摄像头和(或)麦克风。

multiple:当指定布尔类型属性 multiple时,文件 input 允许用户选择多个文件。

文件上传form表单:method必须为post,enctype=”multipart/form-data”(二进制字节流)
http请求包含两部分header+body, 一部分是Request Payload,另一部分是Requst Header,文件上传header的Content-Type=”multipart/form-data;boundary=ed67c97e-2000-47de-9033-77aeb8df43d9”,boundary它标志着一段数据(当有多个上传内容时)的开始和结束.

156.字符串相连有哪些方式?哪种最好?为什么?

ES6: ${var} 模版字符串
简单,方便,但是不兼容低版本浏览器
ES5:””+”” ‘’+’’
兼容性好,但是比较麻烦考验心智,如果拼接的有””‘’时需要\转义

157.说说你对CDN的理解,使用过程中有没有遇到过问题?

一、概述
CDN (内容分发网络) 指的是一组分布在各个地区的服务器。这些服务器存储着数据的副本,因此服务器可以根据哪些服务器与用户距离最近,来满足数据的请求。CDN提供快速服务,较少受高流量影响。

CDN被广泛用于传输 stylesheets 和 JavaScript 等静态资源,像 Bootstrap,Jquery 等。对这些库文件使用 CDN 技术,有以下几点好处:

  • 通过CDN向用户分发相关静态资源文件,可以降低自身服务器的压力
  • 大多数 CDN 在全球都有服务器,所以 CDN 上的服务器在地理位置上可能比你自己的服务器更接近你的用户。地理距离会按比例影响延迟。
  • CDN已经配置了恰当的缓存设置。使用 CDN 节省了在你的服务器中对静态资源文件的配置。

有点不好就是:

大部分CDN是单独收费的。
CDN更新资源麻烦,可能需要手动来刷新CDN来刷新资源的缓存。
如果CDN出了故障,需要联系CDN提供商来解决,中间增加了沟通耗时。
可能对SEO有影响,CDN ip的多样性,部分ip可能对爬虫并不友好。

158.web workers有用过吗?能帮我们解决哪些问题?

JavaScript 语言采用的是单线程模型,也就是说,所有任务只能在一个线程上完成,一次只能做一件事.
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行.
在主线程运行的同时,Worker 线程在后台运行,两者互不干扰

Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭.

Web Worker 有以下几个使用注意点。

  • 1.同源限制
    Worker线程运行的脚本文件,必须和运行主线程的脚本文件同源
  • DOM限制
    Worker线程所在的全局环境和主线程不一致,所以不能使用document,window,parent等,但能使用navigator,location
  • 通信限制
    Worker线程和主线程不在同一个上下文环境,无法直接通信,只能通过消息
  • 脚本限制
    Woker线程不能执行alert方法和confirm方法,但可以使用ajax
  • 文件限制
    Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

二、使用

主线程采用new命令,调用Worker()构造函数,新建一个 Worker 线程

1
var worker = new Woker('work.js') // 必须是网络脚本

然后,主线程调用worker.postMessage()方法,向 Worker 发消息。

1
2
worker.postMessage('hello world'); //参数,就是主线程传给 Worker 的数据。它可以是各种数据类型,包括二进制数据。
worker.postMessage({method: 'echo', args: ['Work']});

主线程通过worker.onmessage指定监听函数,接收子线程发回来的消息。

1
2
3
4
worker.onmessage = function(event) {
console.log('received message ', event.data);
// do something
}

Worker 完成任务以后,主线程就可以把它关掉。

1
worker.terminate()

Worker 线程内部需要有一个监听函数,监听message事件。

1
2
3
this.addEventListener('message', function (e) {
this.postMessage('You said: ' + e.data);
}, false);

worker 线程关闭

1
this.close()

159.怎么使用自定义字体?有什么注意事项?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@font-face {
font-family: 'myFont';
src: url('字体文件名.eot'); /* IE9 Compat Modes */
src: url('字体文件名.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('字体文件名.woff') format('woff'), /* Modern Browsers */
url('字体文件名.ttf') format('truetype'), /* Safari, Android, iOS */
url('字体文件名.svg#字体文件名') format('svg'); /* Legacy iOS */
font-style: normal;
font-weight: normal;
}
/* 使用 */
.demo {
font-family: 'myFont'
}

注意版权,以及字体文件大,加载慢

160.window的load 和ready有什么区别?

window的load:

load 事件在整个页面及所有依赖资源如样式表和图片都已完成加载时触发。它与 DOMContentLoaded 不同,后者只要页面 DOM 加载完成就触发,无需等待依赖资源的加载。

该事件不可取消,也不会冒泡。

所有以 load 命名的事件都不会传递到 Window 上,即使 bubbles 初始化为 true。要在 window 上捕获 load 事件,相关的 load 事件必须直接绑定到 window 上。只能绑定一次load事件

示例:

1
2
3
4
5
6
window.addEventListener('load', (event) => {
console.log('page is fully loaded');
});
window.onload = (event) => {
console.log('page is fully loaded');
};

$(document).ready jQuery等待加载:

只需要等DOM结构加载完毕,就能执行包裹的代码,可以绑定多次ready事件,并且不会被覆盖

161.你有了解HTML5的地理定位吗?怎么使用?

Geolocation.

用于获得用户的地理位置。

使用 getCurrentPosition() 方法来获得用户的位置。

1
2
3
4
5
6
7
8
9
10
11
var x=document.getElementById("demo");
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
x.innerHTML="该浏览器不支持获取地理位置。";
}

function showPosition(position) {
x.innerHTML="纬度: " + position.coords.latitude +
"<br>经度: " + position.coords.longitude;
}

162.css3的:nth-child和:nth-of-type的区别是什么?

:nth-child(n) 选择器匹配父元素中的第 n 个子元素,元素类型没有限制。

:nth-of-type(n)选择器匹配同类型中的第n个同级兄弟元素。

163.写一个函数找出给定数组中的最大差值

1
2
3
4
function getMaxDiff(arr) {
return Math.max(...arr) - Math.min(...arr)
}
getMaxDiff([1,2,3,4,5]) // 4

164.HTML5中新添加的表单属性有哪些?

查看HTML5中新添加的表单属性

165.写出4个使用this的典型例子

全局 this 是 window
函数 this 是调用者
构造函数的 this 是 new 之后的新对象
call ,apply ,bind 的 this 是第一个参数

166.网站被劫持植入广告该怎么办?如何防止?

这是因为你的网页没有加密,一些运行商通过HTTP劫持来植入广告.HTTPS能够加密网页传输内容,不仅可以防止强插广告,还可以防盗号

167.渐进式渲染是什么?

渐进式渲染是用于提高网页性能(尤其是提高用户感知的加载速度),以尽快呈现页面的技术

比如:
1.图片懒加载——页面上的图片不会一次性全部加载。当用户滚动页面到图片部分时,JavaScript 将加载并显示图像。
2.确定显示内容的优先级-为了尽快将页面呈现给用户,页面只包含基本的最少量的 CSS、脚本和内容,然后可以使用延迟加载脚本或监听DOMContentLoaded/load事件加载其他资源和内容。
3.异步加载 HTML 片段——当页面通过后台渲染时,把 HTML 拆分,通过异步请求,分块发送给浏览器。

168.JSONP的原理是什么?解决什么问题?

原理:

动态插入script标签,执行callback回调函数,将回调函数中的参数输出

解决:

解决跨越问题

JS 动态插入 script 并将 src 指向后端 API,后台返回 json 并使用协定的 callback 函数把 json 包起来。浏览器以 JS 内容解析执行返回的内容,回调函数得以被调用并传入了返回的 json 对象。

169.说说你对域名收敛和域名发散的理解?分别在什么场景下使用?

域名发散:是将静态资源放在多个子域名下,就可以多线程下载,提高并行度,使客户端加载静态资源更加迅速。域名发散是pc端为了利用浏览器的多线程并行下载能力。

域名收敛:就是将静态资源放在一个域名下。减少DNS解析的开销。域名收敛多用与移动端,提高性能,因为dns解析是是从后向前迭代解析,如果域名过多性能会下降,增加DNS的解析开销。

170.有使用过vue吗?说说你对vue的理解

1.vue是渐变式框架,根据自己的需求添加功能
2.vue数据驱动采用mvvm模式,m是数据层,v是视图层,vm是调度者
3.组件化,复用性强
4.SPA单页面应用,只有一个页面,加载速率快
5.vue操作的是虚拟DOM,采用diff算法更新DOM,比传统的DOM操作更加的高效。

Model:模型层,负责处理业务逻辑以及和服务器端进行交互
View:视图层:负责将数据模型转化为UI展示出来,可以简单的理解为HTML页面
ViewModel:视图模型层,监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步 View 和 Model 的对象,连接 Model 和 View之间的桥梁,绑定数据到viewmodel层并自动更新渲染到页面上,视图变化通知到viewmodel层去更新数据

171.什么是双向绑定?原理是什么?

vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

172.什么是虚拟DOM?

用js对象描述dom结构,虚拟dom属性和真实的dom属性一一对应。
diff是发生在虚拟dom上的,新的虚拟dom和旧的虚拟dom进行diff,算出最小量更新,最后反映在真实dom上

数据更新->虚拟dom计算变更->操作真实的dom->视图更新

虚拟DOM 表现为一个 Object对象。并且最少包含标签名 (tag)、属性 (attrs) 和子元素对象 (children) 三个属性

173.vue组件之间的通信都有哪些?

  • 父子间通信: 父->子: props 子->父:$emit/$on
    获取父子组件实例 :$parent/$children ref获取实例的方式调用组件的属性或方法
  • 兄弟组件通信: Event Bus/vuex
  • 跨级组件通信:1.vuex 2.Event Bus 3.($attrs/$listeners) 4.(Provide/inject)

透传 attribute:

vue2: 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件——在创建高级别的组件时非常有用。

vue3:
“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。

当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上。如果一个子组件的根元素已经有了 class 或 style attribute,它会和从父组件上继承的值合并。
同样的规则也适用于 v-on 事件监听器,如子父自己都绑定事件,则两个监听器都会被触发。

禁用 Attributes 继承:在子组件设置inheritAttrs: false。
最常见的需要禁用 attribute 继承的场景就是 attribute 需要应用在根节点以外的其他元素上。通过设置 inheritAttrs 选项为 false,你可以完全控制透传进来的 attribute 被如何使用。

透传进来的 attribute 可以在模板的表达式中直接用 $attrs 访问到。

$attrs: 对象包含了除组件所声明的 props 和 emits 之外的所有其他 attribute,例如 class,style,v-on 监听器等等

有几点需要注意:

和 props 有所不同,透传 attributes 在 JavaScript 中保留了它们原始的大小写,所以像 foo-bar 这样的一个 attribute 需要通过 $attrs[‘foo-bar’] 来访问。

像 @click 这样的一个 v-on 事件监听器将在此对象下被暴露为一个函数 $attrs.onClick。

1
2
3
<div class="btn-wrapper">
<button class="btn">click me</button>
</div>

我们想要所有像 class 和 v-on 监听器这样的透传 attribute 都应用在内部的 button 上而不是外层的 div 上。我们可以通过设定 inheritAttrs: false 和使用 v-bind=”$attrs” 来实现.

1
2
3
<div class="btn-wrapper">
<button class="btn" v-bind="$attrs">click me</button>
</div>

tips:没有参数的 v-bind 会将一个对象的所有属性都作为 attribute 应用到目标元素上.

和单根节点组件有所不同,有着多个根节点的组件没有自动 attribute 透传行为。如果 $attrs 没有被显式绑定,将会抛出一个运行时警告。
如果 $attrs 被显式绑定,则不会有警告:

1
2
3
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>

可以通过 $attrs 这个实例属性来访问组件的所有透传 attribute:

1
2
3
4
5
export default {
created() {
console.log(this.$attrs)
}
}

$listeners:

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件——在创建更高层次的组件时非常有用.

vue3 可从透传$attrs获取事件监听器。

Provide:

provide和inject: 一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

为组件后代提供数据,需要用到provide选项:

1
2
3
4
5
export default {
provide: {
message: 'hello!'
}
}

如果我们需要提供依赖当前组件实例的状态 (比如那些由 data() 定义的数据属性),那么可以以函数形式使用 provide:

1
2
3
4
5
6
7
8
9
10
11
12
13
export default {
data() {
return {
message: 'hello!'
}
},
provide() {
// 使用函数的形式,可以访问到 `this`
return {
message: this.message
}
}
}

除了在一个组件中提供依赖,还可以在整个应用层面提供依赖:

1
2
3
4
5
import { createApp } from 'vue'

const app = createApp({})

app.provide(/* 注入名 */ 'message', /* 值 */ 'hello!')

在应用级别提供的数据在该应用内的所有组件中都可以注入。这在你编写插件时会特别有用,因为插件一般都不会使用组件形式来提供值。

Inject(注入):

要注入上层组件提供的数据,需使用 inject 选项来声明:

1
2
3
4
5
6
export default {
inject: ['message'],
created() {
console.log(this.message) // injected value
}
}

注入会在组件自身的状态之前被解析,因此你可以在 data() 中访问到注入的属性:

1
2
3
4
5
6
7
8
9
export default {
inject: ['message'],
data() {
return {
// 基于注入值的初始数据
fullMessage: this.message
}
}
}

为保证注入方和供给方之间的响应性链接,我们需要使用 computed() 函数提供一个计算属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { computed } from 'vue'

export default {
data() {
return {
message: 'hello!'
}
},
provide() {
return {
// 显式提供一个计算属性
message: computed(() => this.message)
}
}
}

174.请描述下vue的生命周期是什么?

  • beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用,props,methods,data还不能访问

  • created:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el property 目前尚不可用。一般creadted钩子函数主要是用来初始化数据。

  • beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。

  • mounted: 实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。注意 mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick。该钩子函数是在挂在完成以后也就是模板渲染完成以后才会被调用

  • beforeUpdate: 数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。

  • updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。

  • activated:被 keep-alive 缓存的组件激活时调用。

  • deactivated:被 keep-alive 缓存的组件停用时调用

  • beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用

  • destroyed: 实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁

  • errorCaptured:当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

175.说下你对指令的理解?

指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM.

指令:绑定元素,直接操作dom,可以简化dom操作

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • bind: 只调用一次,指令第一次绑定到元素时调用。
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

176.v-show和v-if有什么区别?使用场景分别是什么?

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
v-show:带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display。display:none;不占据空间。
v-show 不支持 <template> 元素,也不支持 v-else。

v-if vs v-show:

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

css:visibility: hidden; 不同于v-show看不见仍占据位置,发生重绘。
v-if和v-show都会造成回流,只要页面渲染发生变化都会导致生命周期钩子beforeUpdate和updated执行,也即v-show、v-if、visibility都会触发生命周期钩子。

177.说说你对MVC、MVP、MVVM模式的理解

查看MVC/MVP/MVVM模式的概念和区别

178.inline、block、inline-block这三个属性值有什么区别?

CSS display 属性设置元素是否被视为块或者内联元素以及用于子元素的布局.

形式上,display 属性设置元素的内部和外部的显示类型.外部类型设置元素参与流式布局;内部类型设置子元素的布局。

CSS 流式布局

“文档流”或”流式布局”是在对布局进行任何更改之前,在页面上显示”块”和”内联”元素的方式。这个”流”本质上是一系列的事物,它们都在你的布局中一起工作,并且互相了解。一旦某部分脱离了”流”,它就会独立地工作。

在文档流中,内联元素按内联方向显示,即词语在依据文件写作模式的句子中表示的方向。块元素则一个接一个地显示,就像该文档的写作模式中的段落一样。因此在英语中,内联元素从左边开始一个接一个地显示,块元素从顶部开始向下显示并移动页面。

block

该元素生成一个块级元素盒,在正常的流中,该元素之前和之后产生换行。

inline

该元素生成一个或多个内联元素盒,它们之前或者之后并不会产生换行。在正常的流中,如果有空间,下一个元素将会在同一行上。

inline-block

该元素生成块级元素盒,如果它是一个单独的内联盒,它将盒周围的内容一起流动(行为类似于替换元素)。

它等同于 inline flow-root

flow-root: 该元素生成一个块级元素盒,其会建立一个新的块级格式化上下文,定义格式化上下文的根元素。

  • 行内元素(display: inline):

    • 设置宽高无效,宽度和高度由内容决定
    • 设置margin左右有效,上下无效,padding都有效
    • 不会自动换行
    • 有span,img,input,a,b,sub,sup,i
  • 块级元素(display:block):

    • 可以设置宽高
    • margin和padding都有效
    • 自动换行
    • 多个块元素写一起,排列从上到下
    • 由div,p,nav,h,footer,main,header等
  • 行内块元素(display:inline-block)

    • 能够设置宽高
    • margin/padding都有效
    • 不会自动换行
    • 默认排列方式从左到右

179.写一个方法,使得sum(x)(y)和sum(x,y)返回的结果相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//函数柯理化
function sum1(x, y, z) {
return x + y + z
}
function sum2() {
var args = arguments
return function () {
var arr = []
arr.push(...args, ...arguments)
return arr.reduce((total, item) => total += item, 0)
}
}
console.log(sum1(6, 9, 14)) //29
console.log(sum2(6)(9, 14)) //29

180.说你对浏览器的关键渲染路径(CRP)的理解

关键渲染路径是浏览器把html、css、js转换为屏幕上的像素所经历的步骤序列,优化关键渲染路径可提高渲染性能。关键渲染路径包含了文档对象模型DOM、css对象模型CSSOM、渲染树和布局

web性能包含了服务器请求和响应、加载、执行脚本、渲染、布局和绘制每个像素到屏幕上。

CRP:

网页请求从 HTML 文件请求开始。

服务器返回 HTML – 响应头和数据。

然后浏览器开始解析 HTML,转换收到的数据为 DOM 树。

浏览器每次发现外部资源就初始化请求,无论是样式、脚本或者嵌入的图片引用。

有时请求会阻塞,这意味着解析剩下的 HTML 会被终止直到重要的资源被处理。

浏览器接着解析 HTML,发请求和构造 DOM 直到文件结尾,这时开始构造 CSS 对象模型。

等到 DOM 和 CSSOM 完成之后,浏览器构造渲染树,计算所有可见内容的样式。

一旦渲染树完成布局开始,定义所有渲染树元素的位置和大小。

完成之后,页面被渲染完成,或者说是绘制到屏幕上。

文档对象模型DOM:

DOM 构建是增量的。HTML 响应变成令牌(token),令牌变成节点,而节点又变成 DOM 树。节点数量越多,关键渲染路径中的后续事件将花费的时间就越长

CSS 对象模型:

DOM 包含页面所有的内容。CSSOM 包含了页面所有的样式,也就是如何展示 DOM 的信息。
DOM 构造是增量的,CSSOM 却不是。CSS 是渲染阻塞的:浏览器会阻塞页面渲染直到它接收和执行了所有的 CSS。CSS 是渲染阻塞是因为规则可以被覆盖,所以内容不能被渲染直到 CSSOM 的完成。

从选择器性能的角度,更少的特定选择器是比更多的要快。

渲染树:

渲染树包括了内容和样式:DOM 和 CSSOM 树结合为渲染树。为了构造渲染树,浏览器检查每个节点,从 DOM 树的根节点开始,并且决定哪些 CSS 规则被添加。

渲染树只包含了可见内容。头部(通常)不包含任何可见信息,因此不会被包含在渲染树种。如果有元素上有 display: none;,它本身和其后代都不会出现在渲染树中。

布局:

一旦渲染树被构建,布局变成了可能。布局取决于屏幕的尺寸。布局这个步骤决定了在哪里和如何在页面上放置元素,决定了每个元素的宽和高,以及他们之间的相关性。

布局性能受 DOM 影响 – 节点数越多,布局就需要更长的时间。

为了减小布局事件的频率和时长,批量更新或者避免改动盒模型属性。

绘制:

最后一步是将像素绘制在屏幕上。一旦渲染树创建并且布局完成,像素就可以被绘制在屏幕上。加载时,整个屏幕被绘制出来。之后,只有受影响的屏幕区域会被重绘,浏览器被优化为只重绘需要绘制的最小区域。

优化CRP:

提升页面加载速度需要通过被加载资源的优先级、控制它们加载的顺序和减小这些资源的体积。

性能提升包含:

  1. 通过异步、延迟加载或者消除非关键资源来减少关键资源的请求数量
  2. 优化必须的请求数量和每个请求的文件体积
  3. 通过区分关键资源的优先级来优化被加载关键资源的顺序,来缩短关键路径长度。

181.box-sizing常用的属性有哪些?分别有什么作用?

CSS 中的 box-sizing 属性定义了 user agent 应该如何计算一个元素的总宽度和总高度。

box-sizing属性值:

content-box:

默认值,标准盒子模型。width和height只包含内容的宽和高,不包含边框、内边距、外边距。
尺寸计算公式:
width = 内容的宽度
height = 内容的高度

border-box:

width和height包含内容、边框、内边距,但不包含外边距。文档处于Quirks模式时ie使用的盒模型。
尺寸计算公式:
width = border + padding + 内容的宽度
height = border + padding + 内容的高度

182.请说下你对__proto__和prototype的理解

prototype属性:

原型属性,是函数独有的,每个函数都有一个prototype属性,是一个指针,指向一个对象即原型对象,这个对象包含了所有实例共享的属性和方法。

__proto__:

实例对象都有的属性,它指向该实例对象所对应的原型对象。

prototype和__proto__都指向原型对象,任意一个函数包括构造函数都有一个prototype属性,指向该函数的原型对象;
任何一个构造函数的实例化对象,都有一个__proto__对象,它指向构造函数的原型对象。

1
2
3
4
5
function Student(){}
let s = new Student()

s.__proto__ === Student.prototype // true
Student.prototype.constructor === Student // true

两者区别:

  • 1.prototype是函数独有的,而__proto__是每一个对象都有的包括函数。
  • 2.prototype的作用是保存所有实例共享的属性和方法;__proto__的作用当访问一个对象的属性或方法时,如果内部没有该属性或方法,就去__proto__属性所指的原型对象去找,如果没有就去原型对象的原型去找,直到null,即原型链。
    1. s.__proto__ === Student.prototype; prototype还有一个constructor属性,指向该对象的构造函数本身。

183.写一个格式化金额的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
// * @param {*} num 要格式化的数字
// * @param {*} decimals 保留几位小数
// * @param {*} thousandsSep 千分位符号
**/
function numberFormat(num, decimals, thousandsSep) {
if (isNaN(num)) {
num = '0.00'
}
let prec = !isFinite(+decimals) ? 0: Math.abs(decimals)
let sep = !thousandsSep ? ',' : thousandsSep
let s = num.toString().replace(/,/g, '')
let p = parseFloat(s)
let n = isNaN(p) ? 1 : p
let formatNum = n.toFixed(prec).toString().replace(/(\d)(?=(\d{3})+\.)/g, function ($0,$1) {
return $1 + ','
})
return num ? formatNum : ''
}
numberFormat('1234567.123', 2)
// '1,234,567.12'

184.src、href、link的区别是什么?

href:Hypertext Reference的缩写,超文本引用,它指向一些网络资源,建立和当前元素或者说是本文档的链接关系。在加载它的时候,不会停止对当前文档的处理,浏览器会继续往下走。常用在a、link等标签。

1
2
<a href="http://www.baidu.com"></a>
<link type="text/css" rel="stylesheet" href="index.css">

src:source的缩写,表示的是对资源的引用,它指向的内容会嵌入到当前标签所在的位置.由于src的内容是页面必不可少的一部分,因此浏览器在解析src时会停下对后续文档的处理,直到src的内容加载完毕.

href用于建立当前页面与引用资源之间的关系(链接),而src则会替换当前标签。
遇到href,页面会并行加载后续内容;而src则不同,浏览器需要加载完毕src的内容才会继续往下走。

185.请实现一个flattenDeep函数,把多维数组扁平化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function flatArr(arr) {
let result = []
if (!Array.isArray(arr)) return result
arr.forEach(item => {
if (Array.isArray(item)) {
result.push(...flatArr(item))
} else {
result.push(item)
}
})
return result
}
flatArr([1,2,[1,2], [1,[1,2, [1,2,3]]]]) // [1, 2, 1, 2, 1, 1, 2, 1, 2, 3]

[1,2,[1,2], [1,[1,2, [1,2,3]]]].flat(Infinity) // [1, 2, 1, 2, 1, 1, 2, 1, 2, 3]

186.写一个方法获取图片的原始宽高

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
function getImageSize(url) {
return new Promise((resolve, reject) => {
let img = new Image()
img.onload = function() {
resolve({
width: img.width,
height: img.height
})
}
img.onerror = function(err) {
reject(err)
}
img.src = url
})
}
getImageSize('https://img1.baidu.com/it/u=3155988012,1977937542&fm=253&app=138&size=w931&n=0&f=JPG&fmt=auto?sec=1671123600&t=cc0cc30d2d7bca64d5bff71d1b7bd1e7').then(res => {
console.log(res) // { width: 600, height: 343 }
})
// 或者
document.getElementById('myImg').naturalWidth // 600
document.getElementById('myImg').naturalHeght // 343

// 或者
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
var image = new Image();
image.onload = function() {
var obj = {
width: image.naturalWidth,
height: image.naturalHeight
}
resolve(obj);
};

image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}

187.知道IPV6是什么吗?说说它和IPV4的区别是什么?

IPv6 是当前版本的互联网(Internet)通信协议(protocol)。IPv6 正在慢慢地取代 IPv4 (en-US),因为 IPv6 允许使用更多不同的 IP 地址。

ipv4提供的2的32次方的地址根本不够无数的家用设备使用。而2的128次方的地址可为飞速增加的物联网设备提供足够的地址。

188.怎么使css样式只在当前组件中生效?

1.style scoped
2.css module

在webpack中,作为处理css的css-loader,它实现了css module的思想,要启用css module,需要将css-loader的配置modules设置为true。

原理极其简单,开启了css module后,css-loader会将样式中的类名进行转换,转换为一个唯一的hash值。

由于hash值是根据模块路径和类名生成的,因此,不同的css模块,哪怕具有相同的类名,转换后的hash值也不一样

189.keep-alive

<KeepAlive> 是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例.
<KeepAlive> 包裹动态组件时,会缓存不活跃的组件实例,而不是销毁它们。

任何时候都只能有一个活跃组件实例作为 <KeepAlive> 的直接子节点。

当一个组件在 <KeepAlive> 中被切换时,它的 activated 和 deactivated 生命周期钩子将被调用,用来替代 mounted 和 unmounted。这适用于 <KeepAlive> 的直接子节点及其所有子孙节点。

190.v-for循环中key有什么作用?

key 这个特殊的 attribute 主要作为 Vue 的虚拟 DOM 算法提示,在比较新旧节点列表时用于识别 vnode。

191.vue如何监听键盘事件?

1.keyup

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<input ref="myInput" type="text" value="hello world" autofocus @keyup.enter="handleKey">
</template>

<script>
export default {
methods: {
handleKey(e) {
console.log(e)
}
}
}
</script>

2.addEventListener

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
export default {
mounted() {
document.addEventListener('keyup', this.handleKey)
},
beforeDestroy() {
document.removeEventListener('keyup', this.handleKey)
},
methods: {
handleKey(e) {
console.log(e)
}
}
}
</script>

192.watch和computed有什么区别?

watch:

  1. watch 是观察的作用,类似于某些数据的监听回调
  2. 无缓存性,页面重新渲染时,即使值没有改变也执行
  3. 能调用异步函数。

computed:

  1. 计算属性,用于计算值等场景
  2. computed的值具有缓存性,computed的值在getter执行后是会缓存的,只有它依赖的属性值改变后,下一次获取computed的值才会重新调用getter来计算。
  3. computed适用于计算比较消耗性能的计算场景
  4. 不能调用异步函数。

193.watch监听

1.深度监听对象,deep: true
2.监听开始后立即被调用,immediate: true

194.为什么data属性必须声明为返回一个初始数据对应的函数呢?

对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题.

195.$nextTick有什么作用?

vue响应式的改变一个值以后,此时的dom并不会立即更新,如果需要在数据改变以后立即通过dom做一些操作,可以使用$nextTick获得更新后的dom。

196.分别说说vue能监听到数组或对象变化的场景,还有哪些场景是监听不到的?无法监听时有什么解决方案?

vue如何追踪变化:

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。在 property 被访问和修改时通知变更。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

由于 JavaScript 的限制,Vue 不能检测数组和对象的变化

对于对象:

vue无法检测property的添加或移除。
由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的

对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property

1
2
3
4
5
6
Vue.set(vm.someObj, 'b', 2)

// 您还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:

this.$set(vm.someObj, 'b', 2)

有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。

1
2
3

// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

对于数组:

Vue 不能检测以下数组的变动:

  • 1.当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  • 2.当你修改数组的长度时,例如:vm.items.length = newLength
1
2
3
4
5
6
7
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

解决第一类问题:

1
2
3
4
5
6
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)

// 或者
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

为了解决第二类问题,你可以使用 splice:

1
vm.items.splice(newLength)

197.v-if和v-for的优先级是什么?如果这两个同时出现时,那应该怎么优化才能得到更好的性能?

v-if和v-for同时使用,v-for的优先级高。

一般我们在两种常见的情况下会倾向于这样做:

  • 为了过滤一个列表中的项目 (比如 v-for=”user in users” v-if=”user.isActive”)。在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。

  • 为了避免渲染本应该被隐藏的列表 (比如 v-for=”user in users” v-if=”shouldShowUsers”)。这种情形下,请将 v-if 移动至容器元素上 (比如 ul、ol)。

198.vue实例挂载的过程是什么?

1、实例化阶段

new Vue(el)创建实例化对象,初始化实例的配置,如el, data, methods等

2、初始化阶段

初始化实例的数据响应式系统,按照props、methods、data顺序来初始化相关数据,包括对data中的属性进行依赖收集并进行劫持,数据发生变化时可以自动更新视图。

3、模板编译阶段

如果vue实例选项中有render函数直接渲染dom,如果没有,但是实例中配置了template则对其进行预编译成render函数,如果没有template则将el所在的dom内容作为模版进行编译

将template解析成ast tree抽象语法树
将ast tree转换成render语法字符串
生成render函数

4、挂载阶段

调用render函数生成vnode树,再调用patch生成真实dom,最后将实例挂载到el所在dom元素上,并开始渲染视图。

注意:挂载方法是调用vm.$mount,调用 $mount 方法后,Vue 会通过模板编译器把模板转换成渲染函数

199.说说你对选项el,template,render的理解

el:

提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。

注意:

  • 如果 render 函数和 template property 都不存在,挂载 DOM 元素的 HTML 会被提取出来用作模板,此时,必须使用 Runtime + Compiler 构建的 Vue 库。

template:

一个字符串模板作为 Vue 实例的标识使用。模板将会替换挂载的元素。挂载元素的内容都将被忽略,除非模板的内容有分发插槽。

注意:

  • 如果 Vue 选项中包含渲染函数,该模板将被忽略。

render:

字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode.

注意:

  • Vue 选项中的 render 函数若存在,则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。

el,template,render属性优先性:

当Vue选项对象中有render渲染函数时,Vue构造函数将直接使用渲染函数渲染DOM树,当选项对象中没有render渲染函数时,Vue构造函数首先通过将template模板编译生成渲染函数,然后再渲染DOM树,而当Vue选项对象中既没有render渲染函数,也没有template模板时,会通过el属性获取挂载元素的outerHTML来作为模板,并编译生成渲染函数。
换言之,在进行DOM树的渲染时,render渲染函数的优先级最高,template次之且需编译成渲染函数,而挂载点el属性对应的元素若存在,则在前两者均不存在时,其outerHTML才会用于编译与渲染。

对不同构建版本的解释:
完整版:同时包含编译器和运行时的版本。
编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。
用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。基本上就是除去编译器的其它一切。

200.说说你对同构和SSR的理解

Isomorphism, 同构,指一套代码既可以在server端工作,也可以在web 客户端运行,可以无缝在server端和client端渲染两种模式间切换。这个概念由airbnb的Rendr发扬光大。
所以一楼说的其实指的并不是同构JS,而是Universal Javascript.

在PWA 大行其道的环境下,因为爬虫需要和框架初始化容易白屏等等问题,服务端渲染的呼声又物论沸腾。SSR其实就是在server端把需要的页面和数据组装起来发给客户端而已。

SSR的好处

  • SEO友好
  • 首页加载更快
  • 减少请求

201.什么是html的字符实体?版权符号代码怎么写?

HTML 中的预留字符必须被替换为字符实体。

一些在键盘上找不到的字符也可以使用字符实体来替换。

在 HTML 中,某些字符是预留的。

在 HTML 中不能使用小于号(<)和大于号(>),这是因为浏览器会误认为它们是标签。

如果希望正确地显示预留字符,我们必须在 HTML 源代码中使用字符实体。

显示结果 描述 实体名称 实体编号
空格 &nbsp; &nbsp; &#160;
< 小于号 &lt; &#60;
> 大于号 &gt; &#62;
& 和号 &amp; &#38;
引号 &quot; &#34;
撇号 &apos; (IE不支持) &#39;
&cent; &#162;
£ &pound; &#163;
¥ 人民币/日元 &yen; &#165;
欧元 &euro; &#8364;
§ 小节 &sect; &#167;
© 版权 &copy; &#169;
® 注册商标 &reg; &#174;
商标 &trade; &#8482;
× 乘号 &times; &#215;
÷ 除号 &divide; &#247;

202.说说position的absolute和fixed共同与不同点分别是什么?

absolute
元素会被移出正常文档流,并不为元素预留空间,通过指定元素相对于最近的非 static 定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。

fixed
元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的层叠上下文。当元素祖先的 transform, perspective 或 filter 属性非 none 时,容器由视口改为该祖先。

203.举例子说明javascript的变量声明提升和函数声明提升

变量声明:

1
2
3
console.log(a);// undefinde
var a= "hello world";
console.log(a);// "hello world"

函数声明:

1
2
3
4
f()
function f(){
console.log('hello world');// "hello world"
}

变量声明只提升声明 不提升赋值操作,函数声明 函数体整体被提升。

1
2
3
4
5
6
7
8
getName();
var getName = function(){
console.log("小明");
}
function getName(){
console.log("大明");
}
getName();

提升之后变成:

1
2
3
4
5
6
7
8
9
var getName;
function getName(){
console.log("大明");
}
getName();//”大明“
getName= function(){
console.log("小明");
}
getName();//"小明"

204.组件与插件的区别

Vue组件(component)用来构成你的App的业务模块,它的目标是App.vue。
Vue插件(plugin) 用来增强你的技术栈的功能模块, 它的目标是Vue本身。(插件是对Vue的功能的增强和补充)

205.动态给vue的data添加一个新的属性时会发生什么?怎样解决?

如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。
Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的.

对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property.

206.删除数组用delete和Vue.delete有什么区别?

delete:只是被删除数组成员变为 empty / undefined,其他元素键值不变,不能触发视图更新
Vue.delete:直接删了数组成员,并改变了数组的键值(如果对象是响应式的,确保删除能触发更新视图,这个方法主要用于避开 Vue 不能检测到属性被删除的限制)

207.说说你对vue的mixin的理解,有什么应用场景?

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

选项合并:

  • 数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
  • 同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
  • 值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。

208.v-model是什么?有什么用呢?

在表单输入元素或组件上创建双向绑定。

限制:

  • <input>
  • <select>
  • <textarea>
  • components

修饰符:

  • lazy - 取代 input 监听 change 事件
  • number - 输入字符串转为有效的数字
  • trim - 输入首尾空格过滤

v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据.v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

  • text 和 textarea 元素使用 value property 和 input 事件;
  • checkbox 和 radio 使用 checked property 和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。

209.vue常用的修饰符有哪些?列举并说明

.stop - 调用 event.stopPropagation()。
.prevent - 调用 event.preventDefault()。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器
.lazy - 取代 input 监听 change 事件
.number - 输入字符串转为有效的数字
.trim - 输入首尾空格过滤

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

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

<!-- 键修饰符,键别名 -->
<input @keyup.enter="onEnter">

<!-- 键修饰符,键代码 -->
<input @keyup.13="onEnter">

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

<!-- 对象语法 (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

210.v-on可以绑定多个方法吗?

可以

1
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

211.说说你对vue的template编译的理解?

image

将模版编译成渲染函数可以分为两个步骤,先将模版解析成AST抽象语法树,再使用AST生成渲染函数。
但是由于静态节点不需要总是重新渲染,所以在生成AST之后,生成渲染函数之前这个阶段,需要做一个操作,那就是遍历AST,给所有静态节点做一个标记,这样在虚拟DOM更新节点时,如果发现节点有这个标记,就不会重新渲染它。

模版编译分为三个部分内容:

  • 将模版解析为AST
  • 遍历AST标记静态节点
  • 使用AST生成渲染函数

这三部分内容在模版编译中分别抽象出三个模块来实现各自的功能,分别是:

  • 解析器(将模版解析为AST)
  • 优化器(遍历AST标记静态节点)
  • 代码生成器(使用AST生成渲染函数)

image

212.写出html提供的几种空格实体(5种以上)

&nbsp;

它叫不换行空格,全称No-Break Space,它是最常见和我们使用最多的空格,大多数的人可能只接触了 ,它是按下space键产生的空格。在HTML中,如果你用空格键产生此空格,空格是不会累加的(只算1个)。要使用html实体表示才可累加,该空格占据宽度受字体影响明显而强烈。

&ensp;

它叫“半角空格”,全称是En Space,en是字体排印学的计量单位,为em宽度的一半。根据定义,它等同于字体度的一半(如16px字体中就是8px)。名义上是小写字母n的宽度。此空格传承空格家族一贯的特性:透明的,此空格有个相当稳健的特性,就是其占据的宽度正好是1/2个中文宽度,而且基本上不受字体影响。

&emsp;

它叫“全角空格”,全称是Em Space,em是字体排印学的计量单位,相当于当前指定的点数。例如,1 em在16px的字体中就是16px。此空格也传承空格家族一贯的特性:透明的,此空格也有个相当稳健的特性,就是其占据的宽度正好是1个中文宽度,而且基本上不受字体影响。

&thinsp;

它叫窄空格,全称是Thin Space。我们不妨称之为“瘦弱空格”,就是该空格长得比较瘦弱,身体单薄,占据的宽度比较小。它是em之六分之一宽。

&zwnj;

它叫零宽不连字,全称是Zero Width Non Joiner,简称“ZWNJ”,是一个不打印字符,放在电子文本的两个字符之间,抑制本来会发生的连字,而是以这两个字符原本的字形来绘制。Unicode中的零宽不连字字符映射为“”(zero width non-joiner,U+200C),HTML字符值引用为: ‌

&zwj;

它叫零宽连字,全称是Zero Width Joiner,简称“ZWJ”,是一个不打印字符,放在某些需要复杂排版语言(如阿拉伯语、印地语)的两个字符之间,使得这两个本不会发生连字的字符产生了连字效果。零宽连字符的Unicode码位是U+200D (HTML: ‍ ‍)。

此外,浏览器还会把以下字符当作空白进行解析:空格( )、制表位( )、换行( )和回车( )还有( )等等。

213.举例说明css中颜色的表示方法有几种

  • 颜色单词: blue / lightblue / skyblue / transparent(透明)
  • rgb(0-255, 0-255, 0-255) / rgba(0-255, 0-255, 0-255, 0-1)
  • hsl色相: hsl(色调,饱和度,明度) hsla( 色调,饱和度,亮度,不透明度 ) (兼容性)
  • 十六进制: #000000- #FFFFFF ( #000 - #fff ) ( 0-9 a-f | [A-F] )

214.如何让(a==1 && a==2 && a==3)的值为true,把”==”换成”===”后还能为true吗?

1
2
3
4
5
6
7
8
var val = 0;

Object.defineProperty(this, 'a', {
get: function(){
return ++val;
}
})
(a === 1 && a === 2 && a === 3) // true

=== 严格相等,会比较两个值的类型和值
== 抽象相等,比较时,会先进行类型转换,然后再比较值

“==” 转化规则:
首先通过valueOf 转换,即 obj.valueOf()方法的返回值
如果 obj.valueOf()方法的返回值是原始类型,那么直接返回
如果不是,再通过 obj.toString()方法转换
如果obj.toString()返回的是原始类型,直接返回该值
如果还不是原始类型,抛出不能转换异常。

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232