请注意:本书已迁移至独立站点,请移步访问:[前端面试宝典](https://www.mianshibook.com/)
## 事件机制
### 事件触发三阶段
事件触发有三个阶段
* `window`往事件触发处传播,遇到注册的捕获事件会触发
* 传播到事件触发处时触发注册的事件
* 从事件触发处往`window`传播,遇到注册的冒泡事件会触发
事件触发一般来说会按照上面的顺序进行,但是也有特例,如果给一个目标节点同时注册冒泡和捕获事件,事件触发会按照注册的顺序执行。
~~~
// 以下会先打印冒泡然后是捕获
node.addEventListener(
'click',
event => {
console.log('冒泡')
},
false
)
node.addEventListener(
'click',
event => {
console.log('捕获 ')
},
true
)
~~~
### 注册事件
通常我们使用`addEventListener`注册事件,该函数的第三个参数可以是布尔值,也可以是对象。对于布尔值`useCapture`参数来说,该参数默认值为`false`。`useCapture`决定了注册的事件是捕获事件还是冒泡事件。对于对象参数来说,可以使用以下几个属性
* `capture`,布尔值,和`useCapture`作用一样
* `once`,布尔值,值为`true`表示该回调只会调用一次,调用后会移除监听
* `passive`,布尔值,表示永远不会调用`preventDefault`
一般来说,我们只希望事件只触发在目标上,这时候可以使用`stopPropagation`来阻止事件的进一步传播。通常我们认为`stopPropagation`是用来阻止事件冒泡的,其实该函数也可以阻止捕获事件。`stopImmediatePropagation`同样也能实现阻止事件,但是还能阻止该事件目标执行别的注册事件。
~~~
node.addEventListener(
'click',
event => {
event.stopImmediatePropagation()
console.log('冒泡')
},
false
)
// 点击 node 只会执行上面的函数,该函数不会执行
node.addEventListener(
'click',
event => {
console.log('捕获 ')
},
true
)
~~~
### 事件代理
如果一个节点中的子节点是动态生成的,那么子节点需要注册事件的话应该注册在父节点上
~~~
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
let ul = document.querySelector('##ul')
ul.addEventListener('click', event => {
console.log(event.target)
})
</script>
~~~
事件代理的方式相对于直接给目标注册事件来说,有以下优点
* 节省内存
* 不需要给子节点注销事件
## 跨域
因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就是跨域,Ajax 请求会失败。
我们可以通过以下几种常用方法解决跨域的问题
### JSONP
JSONP 的原理很简单,就是利用`<script>`标签没有跨域限制的漏洞。通过`<script>`标签指向一个需要访问的地址并提供一个回调函数来接收数据当需要通讯时。
~~~
<script src="http://domain/api?param1=a¶m2=b&callback=jsonp"></script>
<script>
function jsonp(data) {
console.log(data)
}
</script>
~~~
JSONP 使用简单且兼容性不错,但是只限于`get`请求。
在开发中可能会遇到多个 JSONP 请求的回调函数名是相同的,这时候就需要自己封装一个 JSONP,以下是简单实现
~~~
function jsonp(url, jsonpCallback, success) {
let script = document.createElement('script')
script.src = url
script.async = true
script.type = 'text/javascript'
window[jsonpCallback] = function(data) {
success && success(data)
}
document.body.appendChild(script)
}
jsonp('http://xxx', 'callback', function(value) {
console.log(value)
})
~~~
### CORS
CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过`XDomainRequest`来实现。
浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。
服务端设置`Access-Control-Allow-Origin`就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
### document.domain
该方式只能用于二级域名相同的情况下,比如`a.test.com`和`b.test.com`适用于该方式。
只需要给页面添加`document.domain = 'test.com'`表示二级域名都相同就可以实现跨域
### postMessage
这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息
~~~
// 发送消息端
window.parent.postMessage('message', 'http://test.com')
// 接收消息端
var mc = new MessageChannel()
mc.addEventListener('message', event => {
var origin = event.origin || event.originalEvent.origin
if (origin === 'http://test.com') {
console.log('验证通过')
}
})
~~~
## Event loop
众所周知 JS 是门非阻塞单线程语言,因为在最初 JS 就是为了和浏览器交互而诞生的。如果 JS 是门多线程的语言话,我们在多个线程中处理 DOM 就可能会发生问题(一个线程中新加节点,另一个线程中删除节点),当然可以引入读写锁解决这个问题。
JS 在执行的过程中会产生执行环境,这些执行环境会被顺序的加入到执行栈中。如果遇到异步的代码,会被挂起并加入到 Task(有多种 task) 队列中。一旦执行栈为空,Event Loop 就会从 Task 队列中拿出需要执行的代码并放入执行栈中执行,所以本质上来说 JS 中的异步还是同步行为。
~~~
console.log('script start')
setTimeout(function() {
console.log('setTimeout')
}, 0)
console.log('script end')
~~~
以上代码虽然`setTimeout`延时为 0,其实还是异步。这是因为 HTML5 标准规定这个函数第二个参数不得小于 4 毫秒,不足会自动增加。所以`setTimeout`还是会在`script end`之后打印。
不同的任务源会被分配到不同的 Task 队列中,任务源可以分为 微任务(microtask) 和 宏任务(macrotask)。在 ES6 规范中,microtask 称为`jobs`,macrotask 称为`task`。
~~~
console.log('script start')
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})
console.log('script end')
// script start => Promise => script end => promise1 => promise2 => setTimeout
~~~
以上代码虽然`setTimeout`写在`Promise`之前,但是因为`Promise`属于微任务而`setTimeout`属于宏任务,所以会有以上的打印。
微任务包括`process.nextTick`,`promise`,`Object.observe`,`MutationObserver`
宏任务包括`script`,`setTimeout`,`setInterval`,`setImmediate`,`I/O`,`UI rendering`
很多人有个误区,认为微任务快于宏任务,其实是错误的。因为宏任务中包括了`script`,浏览器会先执行一个宏任务,接下来有异步代码的话就先执行微任务。
所以正确的一次 Event loop 顺序是这样的
1. 执行同步代码,这属于宏任务
2. 执行栈为空,查询是否有微任务需要执行
3. 执行所有微任务
4. 必要的话渲染 UI
5. 然后开始下一轮 Event loop,执行宏任务中的异步代码
通过上述的 Event loop 顺序可知,如果宏任务中的异步代码有大量的计算并且需要操作 DOM 的话,为了更快的 界面响应,我们可以把操作 DOM 放入微任务中。
### Node 中的 Event loop
Node 中的 Event loop 和浏览器中的不相同。
Node 的 Event loop 分为 6 个阶段,它们会按照顺序反复运行
~~~
┌───────────────────────┐
┌─>│ timers │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ I/O callbacks │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
│ │ idle, prepare │
│ └──────────┬────────────┘ ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │
│ │ poll │<──connections─── │
│ └──────────┬────────────┘ │ data, etc. │
│ ┌──────────┴────────────┐ └───────────────┘
│ │ check │
│ └──────────┬────────────┘
│ ┌──────────┴────────────┐
└──┤ close callbacks │
└───────────────────────┘
~~~
### timer
timers 阶段会执行`setTimeout`和`setInterval`
一个`timer`指定的时间并不是准确时间,而是在达到这个时间后尽快执行回调,可能会因为系统正在执行别的事务而延迟。
下限的时间有一个范围:`[1, 2147483647]`,如果设定的时间不在这个范围,将被设置为 1。
### I/O
I/O 阶段会执行除了 close 事件,定时器和`setImmediate`的回调
### idle, prepare
idle, prepare 阶段内部实现
### poll
poll 阶段很重要,这一阶段中,系统会做两件事情
1. 执行到点的定时器
2. 执行 poll 队列中的事件
并且当 poll 中没有定时器的情况下,会发现以下两件事情
* 如果 poll 队列不为空,会遍历回调队列并同步执行,直到队列为空或者系统限制
* 如果 poll 队列为空,会有两件事发生
* 如果有`setImmediate`需要执行,poll 阶段会停止并且进入到 check 阶段执行`setImmediate`
* 如果没有`setImmediate`需要执行,会等待回调被加入到队列中并立即执行回调
如果有别的定时器需要被执行,会回到 timer 阶段执行回调。
### check
check 阶段执行`setImmediate`
### close callbacks
close callbacks 阶段执行 close 事件
并且在 Node 中,有些情况下的定时器执行顺序是随机的
~~~
setTimeout(() => {
console.log('setTimeout')
}, 0)
setImmediate(() => {
console.log('setImmediate')
})
// 这里可能会输出 setTimeout,setImmediate
// 可能也会相反的输出,这取决于性能
// 因为可能进入 event loop 用了不到 1 毫秒,这时候会执行 setImmediate
// 否则会执行 setTimeout
~~~
当然在这种情况下,执行顺序是相同的
~~~
var fs = require('fs')
fs.readFile(__filename, () => {
setTimeout(() => {
console.log('timeout')
}, 0)
setImmediate(() => {
console.log('immediate')
})
})
// 因为 readFile 的回调在 poll 中执行
// 发现有 setImmediate ,所以会立即跳到 check 阶段执行回调
// 再去 timer 阶段执行 setTimeout
// 所以以上输出一定是 setImmediate,setTimeout
~~~
上面介绍的都是 macrotask 的执行情况,microtask 会在以上每个阶段完成后立即执行。
~~~
setTimeout(() => {
console.log('timer1')
Promise.resolve().then(function() {
console.log('promise1')
})
}, 0)
setTimeout(() => {
console.log('timer2')
Promise.resolve().then(function() {
console.log('promise2')
})
}, 0)
// 以上代码在浏览器和 node 中打印情况是不同的
// 浏览器中一定打印 timer1, promise1, timer2, promise2
// node 中可能打印 timer1, timer2, promise1, promise2
// 也可能打印 timer1, promise1, timer2, promise2
~~~
Node 中的`process.nextTick`会先于其他 microtask 执行。
~~~
setTimeout(() => {
console.log('timer1')
Promise.resolve().then(function() {
console.log('promise1')
})
}, 0)
process.nextTick(() => {
console.log('nextTick')
})
// nextTick, timer1, promise1
~~~
## 存储
### cookie,localStorage,sessionStorage,indexDB
| 特性 | cookie | localStorage | sessionStorage | indexDB |
| --- | --- | --- | --- | --- |
| 数据生命周期 | 一般由服务器生成,可以设置过期时间 | 除非被清理,否则一直存在 | 页面关闭就清理 | 除非被清理,否则一直存在 |
| 数据存储大小 | 4K | 5M | 5M | 无限 |
| 与服务端通信 | 每次都会携带在 header 中,对于请求性能影响 | 不参与 | 不参与 | 不参与 |
从上表可以看到,`cookie`已经不建议用于存储。如果没有大量数据存储需求的话,可以使用`localStorage`和`sessionStorage`。对于不怎么改变的数据尽量使用`localStorage`存储,否则可以用`sessionStorage`存储。
对于`cookie`,我们还需要注意安全性。
| 属性 | 作用 |
| --- | --- |
| value | 如果用于保存用户登录态,应该将该值加密,不能使用明文的用户标识 |
| http-only | 不能通过 JS 访问 Cookie,减少 XSS 攻击 |
| secure | 只能在协议为 HTTPS 的请求中携带 |
| same-site | 规定浏览器不能在跨域请求中携带 Cookie,减少 CSRF 攻击 |
### Service Worker
> Service workers 本质上充当 Web 应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。他们还允许访问推送通知和后台同步 API。
目前该技术通常用来做缓存文件,提高首屏速度,可以试着来实现这个功能。
~~~
// index.js
if (navigator.serviceWorker) {
navigator.serviceWorker
.register('sw.js')
.then(function(registration) {
console.log('service worker 注册成功')
})
.catch(function(err) {
console.log('servcie worker 注册失败')
})
}
// sw.js
// 监听 `install` 事件,回调中缓存所需文件
self.addEventListener('install', e => {
e.waitUntil(
caches.open('my-cache').then(function(cache) {
return cache.addAll(['./index.html', './index.js'])
})
)
})
// 拦截所有请求事件
// 如果缓存中已经有请求的数据就直接用缓存,否则去请求数据
self.addEventListener('fetch', e => {
e.respondWith(
caches.match(e.request).then(function(response) {
if (response) {
return response
}
console.log('fetch source')
})
)
})
~~~
打开页面,可以在开发者工具中的`Application`看到 Service Worker 已经启动了![](https://user-gold-cdn.xitu.io/2018/3/28/1626b1e8eba68e1c?w=1770&h=722&f=png&s=192277)
在 Cache 中也可以发现我们所需的文件已被缓存
![](https://user-gold-cdn.xitu.io/2018/3/28/1626b20dfc4fcd26?w=1118&h=728&f=png&s=85610)
当我们重新刷新页面可以发现我们缓存的数据是从 Service Worker 中读取的
![](https://user-gold-cdn.xitu.io/2018/3/28/1626b20e4f8f3257?w=2818&h=298&f=png&s=74833)
## 渲染机制
浏览器的渲染机制一般分为以下几个步骤
1. 处理 HTML 并构建 DOM 树。
2. 处理 CSS 构建 CSSOM 树。
3. 将 DOM 与 CSSOM 合并成一个渲染树。
4. 根据渲染树来布局,计算每个节点的位置。
5. 调用 GPU 绘制,合成图层,显示在屏幕上。
![](https://user-gold-cdn.xitu.io/2018/4/11/162b2ab2ec70ac5b?w=900&h=352&f=png&s=49983)
在构建 CSSOM 树时,会阻塞渲染,直至 CSSOM 树构建完成。并且构建 CSSOM 树是一个十分消耗性能的过程,所以应该尽量保证层级扁平,减少过度层叠,越是具体的 CSS 选择器,执行速度越慢。
当 HTML 解析到 script 标签时,会暂停构建 DOM,完成后才会从暂停的地方重新开始。也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件。并且 CSS 也会影响 JS 的执行,只有当解析完样式表才会执行 JS,所以也可以认为这种情况下,CSS 也会暂停构建 DOM。
![](https://user-gold-cdn.xitu.io/2018/7/8/1647838a3b408372?w=1676&h=688&f=png&s=154480)
![](https://user-gold-cdn.xitu.io/2018/7/8/16478388e773b16a?w=1504&h=760&f=png&s=123231)
### Load 和 DOMContentLoaded 区别
Load 事件触发代表页面中的 DOM,CSS,JS,图片已经全部加载完毕。
DOMContentLoaded 事件触发代表初始的 HTML 被完全加载和解析,不需要等待 CSS,JS,图片加载。
### 图层
一般来说,可以把普通文档流看成一个图层。特定的属性可以生成一个新的图层。**不同的图层渲染互不影响**,所以对于某些频繁需要渲染的建议单独生成一个新图层,提高性能。**但也不能生成过多的图层,会引起反作用。**
通过以下几个常用属性可以生成新图层
* 3D 变换:`translate3d`、`translateZ`
* `will-change`
* `video`、`iframe`标签
* 通过动画实现的`opacity`动画转换
* `position: fixed`
### 重绘(Repaint)和回流(Reflow)
重绘和回流是渲染步骤中的一小节,但是这两个步骤对于性能影响很大。
* 重绘是当节点需要更改外观而不会影响布局的,比如改变`color`就叫称为重绘
* 回流是布局或者几何属性需要改变就称为回流。
回流必定会发生重绘,重绘不一定会引发回流。回流所需的成本比重绘高的多,改变深层次的节点很可能导致父节点的一系列回流。
所以以下几个动作可能会导致性能问题:
* 改变 window 大小
* 改变字体
* 添加或删除样式
* 文字改变
* 定位或者浮动
* 盒模型
很多人不知道的是,重绘和回流其实和 Event loop 有关。
1. 当 Event loop 执行完 Microtasks 后,会判断 document 是否需要更新。因为浏览器是 60Hz 的刷新率,每 16ms 才会更新一次。
2. 然后判断是否有`resize`或者`scroll`,有的话会去触发事件,所以`resize`和`scroll`事件也是至少 16ms 才会触发一次,并且自带节流功能。
3. 判断是否触发了 media query
4. 更新动画并且发送事件
5. 判断是否有全屏操作事件
6. 执行`requestAnimationFrame`回调
7. 执行`IntersectionObserver`回调,该方法用于判断元素是否可见,可以用于懒加载上,但是兼容性不好
8. 更新界面
9. 以上就是一帧中可能会做的事情。如果在一帧中有空闲时间,就会去执行`requestIdleCallback`回调。
以上内容来自于[HTML 文档](https://html.spec.whatwg.org/multipage/webappapis.html##event-loop-processing-model)
### 减少重绘和回流
* 使用`translate`替代`top`
~~~
<div class="test"></div>
<style>
.test {
position: absolute;
top: 10px;
width: 100px;
height: 100px;
background: red;
}
</style>
<script>
setTimeout(() => {
// 引起回流
document.querySelector('.test').style.top = '100px'
}, 1000)
</script>
~~~
* 使用`visibility`替换`display: none`,因为前者只会引起重绘,后者会引发回流(改变了布局)
* 把 DOM 离线后修改,比如:先把 DOM 给`display:none`(有一次 Reflow),然后你修改 100 次,然后再把它显示出来
* 不要把 DOM 结点的属性值放在一个循环里当成循环里的变量
~~~
for (let i = 0; i < 1000; i++) {
// 获取 offsetTop 会导致回流,因为需要去获取正确的值
console.log(document.querySelector('.test').style.offsetTop)
}
~~~
* 不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局
* 动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用`requestAnimationFrame`
* CSS 选择符从右往左匹配查找,避免 DOM 深度过深
* 将频繁运行的动画变为图层,图层能够阻止该节点回流影响别的元素。比如对于`video`标签,浏览器会自动将该节点变为图层。
- 介绍
- HTML
- 1. DOCTYPE 的作用是什么?
- 2. 标准模式与兼容模式各有什么区别?
- 3. HTML5 为什么只需要写 <!DOCTYPE HTML>,而不需要引入 DTD?
- 4. SGML 、 HTML 、XML 和 XHTML 的区别?
- 5. DTD 介绍
- 6. 行内元素定义
- 7. 块级元素定义
- 8. 行内元素与块级元素的区别?
- 9. HTML5 元素的分类
- 10. 空元素定义
- 11. link 标签定义
- 12. 页面导入样式时,使用 link 和 @import 有什么区别?
- 13. 你对浏览器的理解?
- 14. 介绍一下你对浏览器内核的理解?
- 15. 常见的浏览器内核比较
- 16. 常见浏览器所用内核
- 17. 浏览器的渲染原理?
- 18. 渲染过程中遇到 JS 文件怎么处理?(浏览器解析过程)
- 19. async 和 defer 的作用是什么?有什么区别?(浏览器解析过程)
- 20. 什么是文档的预解析?(浏览器解析过程)
- 21. CSS 如何阻塞文档解析?(浏览器解析过程)
- 22. 渲染页面时常见哪些不良现象?(浏览器渲染过程)
- 23. 如何优化关键渲染路径?(浏览器渲染过程)
- 24. 什么是重绘和回流?(浏览器绘制过程)
- 25. 如何减少回流?(浏览器绘制过程)
- 26. 为什么操作 DOM 慢?(浏览器绘制过程)
- 27. DOMContentLoaded 事件和 Load 事件的区别?
- 28. HTML5 有哪些新特性、移除了那些元素?
- 29. 如何处理 HTML5 新标签的浏览器兼容问题?
- 30. 简述一下你对 HTML 语义化的理解?
- 31. b 与 strong 的区别和 i 与 em 的区别?
- 32. 前端需要注意哪些 SEO ?
- 33. HTML5 的离线储存怎么使用,工作原理能不能解释一下?
- 34. 浏览器是怎么对 HTML5 的离线储存资源进行管理和加载的呢?
- 35. 常见的浏览器端的存储技术有哪些?
- 36. 请描述一下 cookies,sessionStorage 和 localStorage 的区别?
- 37. iframe 有那些缺点?
- 38. Label 的作用是什么?是怎么用的?
- 39. HTML5 的 form 的自动完成功能是什么?
- 40. 如何实现浏览器内多个标签页之间的通信?
- 41. webSocket 如何兼容低版本浏览器?
- 42. 页面可见性(Page Visibility API) 可以有哪些用途?
- 43. 如何在页面上实现一个圆形的可点击区域?
- 44. 实现不使用 border 画出 1 px 高的线,在不同浏览器的标准模式与怪异模式下都能保持一致的效果。
- 45. title 与 h1 的区别?
- 46. <img> 的 title 和 alt 有什么区别?
- 47. Canvas 和 SVG 有什么区别?
- 48. 网页验证码是干嘛的,是为了解决什么安全问题?
- 49. 渐进增强和优雅降级的定义
- 50. attribute 和 property 的区别是什么?
- 51. 对 web 标准、可用性、可访问性的理解
- 52. IE 各版本和 Chrome 可以并行下载多少个资源?
- 53. Flash、Ajax 各自的优缺点,在使用中如何取舍?
- 54. 怎么重构页面?
- 55. 浏览器架构
- 56. 常用的 meta 标签
- 57. css reset 和 normalize.css 有什么区别?
- 58. 用于预格式化文本的标签是?
- 59. DHTML 是什么?
- 60. head 标签中必不少的是?
- 61. HTML5 新增的表单元素有?
- 62. 在 HTML5 中,哪个方法用于获得用户的当前位置?
- 63. 文档的不同注释方式?
- 64. disabled 和 readonly 的区别?
- 65. 主流浏览器内核私有属性 css 前缀?
- 66. 前端性能优化?
- 67. Chrome 中的 Waterfall ?
- 68. 扫描二维码登录网页是什么原理,前后两个事件是如何联系的?
- 69. Html 规范中为什么要求引用资源不加协议头http或者https?
- CSS
- 1. 介绍一下标准的 CSS 的盒子模型?低版本 IE 的盒子模型有什么不同的?
- 2. CSS 选择符有哪些?
- 3. ::before 和:after 中双冒号和单冒号有什么区别?解释一下这 2 个伪元素的作用。
- 4. 伪类与伪元素的区别
- 5. CSS 中哪些属性可以继承?
- 6. CSS 优先级算法如何计算?
- 7. 关于伪类 LVHA 的解释?
- 8. CSS3 新增伪类有那些?
- 9. 如何居中 div?
- 10. display 有哪些值?说明他们的作用。
- 11. position 的值 relative 和 absolute 定位原点是?
- 12. CSS3 有哪些新特性?(根据项目回答)
- 13. 请解释一下 CSS3 的 Flex box(弹性盒布局模型),以及适用场景?
- 14. 用纯 CSS 创建一个三角形的原理是什么?
- 15. 一个满屏品字布局如何设计?
- 16. CSS 多列等高如何实现?
- 17. 经常遇到的浏览器的兼容性有哪些?原因,解决方法是什么,常用 hack 的技巧?
- 18. li 与 li 之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
- 19. 为什么要初始化 CSS 样式?
- 20. 什么是包含块,对于包含块的理解?
- 21. CSS 里的 visibility 属性有个 collapse 属性值是干嘛用的?在不同浏览器下以后什么区别?
- 22. width:auto 和 width:100\x 的区别
- 23. 绝对定位元素与非绝对定位元素的百分比计算的区别
- 24. 简单介绍使用图片 base64 编码的优点和缺点。
- 25. 'display'、'position'和'float'的相互关系?
- 26. margin 重叠问题的理解。
- 27. 对 BFC 规范(块级格式化上下文:block formatting context)的理解?
- 28. IFC 是什么?
- 29. 请解释一下为什么需要清除浮动?清除浮动的方式
- 30. 使用 clear 属性清除浮动的原理?
- 31. zoom:1 的清除浮动原理?
- 32. 移动端的布局用过媒体查询吗?
- 33. 使用 CSS 预处理器吗?喜欢哪个?
- 34. CSS 优化、提高性能的方法有哪些?
- 35. 浏览器是怎样解析 CSS 选择器的?
- 36. 在网页中应该使用奇数还是偶数的字体?为什么呢?
- 37. margin 和 padding 分别适合什么场景使用?
- 38. 抽离样式模块怎么写,说出思路,有无实践经验?
- 39. 简单说一下 css3 的 all 属性。
- 40. 为什么不建议使用统配符初始化 css 样式。
- 41. absolute 的 containingblock(包含块)计算方式跟正常流有什么不同?
- 42. 对于 hasLayout 的理解?
- 43. 元素竖向的百分比设定是相对于容器的高度吗?
- 44. 全屏滚动的原理是什么?用到了 CSS 的哪些属性?(待深入实践)
- 45. 什么是响应式设计?响应式设计的基本原理是什么?如何兼容低版本的 IE?(待深入了解)
- 46. 视差滚动效果,如何给每页做不同的动画?(回到顶部,向下滑动要再次出现,和只出现一次分别怎么做?)
- 47. 如何修改 chrome 记住密码后自动填充表单的黄色背景?
- 48. 怎么让 Chrome 支持小于 12px 的文字?
- 49. 让页面里的字体变清晰,变细用 CSS 怎么做?
- 50. font-style 属性中 italic 和 oblique 的区别?
- 51. 设备像素、css 像素、设备独立像素、dpr、ppi 之间的区别?
- 52. layout viewport、visual viewport 和 ideal viewport 的区别?
- 53. position:fixed;在 android 下无效怎么处理?
- 54. 如果需要手动写动画,你认为最小时间间隔是多久,为什么?(阿里)
- 55. 如何让去除 inline-block 元素间间距?
- 56. overflow:scroll 时不能平滑滚动的问题怎么处理?
- 57. 有一个高度自适应的 div,里面有两个 div,一个高度 100px,希望另一个填满剩下的高度。
- 58. png、jpg、gif 这些图片格式解释一下,分别什么时候用。有没有了解过 webp?
- 59. 浏览器如何判断是否支持 webp 格式图片
- 60. 什么是 Cookie 隔离?(或者说:请求资源的时候不要让它带 cookie 怎么做)
- 61. style 标签写在 body 后与 body 前有什么区别?
- 62. 什么是 CSS 预处理器/后处理器?
- 63. 阐述一下 CSSSprites
- 64. 使用 rem 布局的优缺点?
- 65. 几种常见的 CSS 布局
- 66. 画一条 0.5px 的线
- 67. transition 和 animation 的区别
- 68. 什么是首选最小宽度?
- 69. 为什么 height:100\x 会无效?
- 70. min-width/max-width 和 min-height/max-height 属性间的覆盖规则?
- 71. 内联盒模型基本概念
- 72. 什么是幽灵空白节点?
- 73. 什么是替换元素?
- 74. 替换元素的计算规则?
- 75. content 与替换元素的关系?
- 76. margin:auto 的填充规则?
- 77. margin 无效的情形
- 78. border 的特殊性?
- 79. 什么是基线和 x-height?
- 80. line-height 的特殊性?
- 81. vertical-align 的特殊性?
- 82. overflow 的特殊性?
- 83. 无依赖绝对定位是什么?
- 84. absolute 与 overflow 的关系?
- 85. clip 裁剪是什么?
- 86. relative 的特殊性?
- 87. 什么是层叠上下文?
- 88. 什么是层叠水平?
- 89. 元素的层叠顺序?
- 90. 层叠准则?
- 91. font-weight 的特殊性?
- 92. text-indent 的特殊性?
- 93. letter-spacing 与字符间距?
- 94. word-spacing 与单词间距?
- 95. white-space 与换行和空格的控制?
- 96. 隐藏元素的 background-image 到底加不加载?
- 97. 如何实现单行/多行文本溢出的省略(...)?
- 98. 常见的元素隐藏方式?
- 99. css 实现上下固定中间自适应布局?
- 100. css 两栏布局的实现?
- 101. css 三栏布局的实现?
- 102. 实现一个宽高自适应的正方形
- 103. 实现一个三角形
- 104. 一个自适应矩形,水平垂直居中,且宽高比为 2:1
- 105. 你知道 CSS 中不同属性设置为百分比\x 时对应的计算基准?
- JavaScript基础
- 1. 介绍 js 的基本数据类型
- 2. JavaScript 有几种类型的值?你能画一下他们的内存图吗?
- 3. 什么是堆?什么是栈?它们之间有什么区别和联系?
- 4. 内部属性 [[Class]] 是什么?
- 5. 介绍 js 有哪些内置对象?
- 6. undefined 与 undeclared 的区别?
- 7. null 和 undefined 的区别?
- 8. 如何获取安全的 undefined 值?
- 9. 说几条写 JavaScript 的基本规范?
- 10. JavaScript 原型,原型链? 有什么特点?
- 11. js 获取原型的方法?
- 12. 在 js 中不同进制数字的表示方式
- 13. js 中整数的安全范围是多少?
- 14. typeof NaN 的结果是什么?
- 15. isNaN 和 Number.isNaN 函数的区别?
- 16. Array 构造函数只有一个参数值时的表现?
- 17. 其他值到字符串的转换规则?
- 18. 其他值到数字值的转换规则?
- 19. 其他值到布尔类型的值的转换规则?
- 20. {} 和 [] 的 valueOf 和 toString 的结果是什么?
- 21. 什么是假值对象?
- 22. ~ 操作符的作用?
- 23. 解析字符串中的数字和将字符串强制类型转换为数字的返回结果都是数字,它们之间的区别是什么?
- 24. 操作符什么时候用于字符串的拼接?
- 25. 什么情况下会发生布尔值的隐式强制类型转换?
- 26. || 和 && 操作符的返回值?
- 27. Symbol 值的强制类型转换?
- 28. == 操作符的强制类型转换规则?
- 29. 如何将字符串转化为数字,例如 '12.3b'?
- 30. 如何将浮点数点左边的数每三位添加一个逗号,如 12000000.11 转化为『12,000,000.11』?
- 31. 常用正则表达式
- 32. 生成随机数的各种方法?
- 33. 如何实现数组的随机排序?
- 34. javascript 创建对象的几种方式?
- 35. JavaScript 继承的几种实现方式?
- 36. 寄生式组合继承的实现?
- 37. Javascript 的作用域链?
- 38. 谈谈 This 对象的理解。
- 39. eval 是做什么的?
- 40. 什么是 DOM 和 BOM?
- 41. 写一个通用的事件侦听器函数。
- 42. 事件是什么?IE 与火狐的事件机制有什么区别? 如何阻止冒泡?
- 43. 三种事件模型是什么?
- 44. 事件委托是什么?
- 45. ["1", "2", "3"].map(parseInt) 答案是多少?
- 46. 什么是闭包,为什么要用它?
- 47. javascript 代码中的 "use strict"; 是什么意思 ? 使用它区别是什么?
- 48. 如何判断一个对象是否属于某个类?
- 49. instanceof 的作用?
- 50. new 操作符具体干了什么呢?如何实现?
- 51. Javascript 中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?
- 52. 对于 JSON 的了解?
- 53. [].forEach.call($$("<em>"),function(a){a.style.outline="1px solid #" (~~(Math.random()</em>(1<<24))).toString(16)}) 能解释一下这段代码的意思吗?
- 54. js 延迟加载的方式有哪些?
- 55. Ajax 是什么? 如何创建一个 Ajax?
- 56. 谈一谈浏览器的缓存机制?
- 57. Ajax 解决浏览器缓存问题?
- 58. 同步和异步的区别?
- 59. 什么是浏览器的同源政策?
- 60. 如何解决跨域问题?
- 61. 服务器代理转发时,该如何处理 cookie?
- 62. 简单谈一下 cookie ?
- 63. 模块化开发怎么做?
- 64. js 的几种模块规范?
- 65. AMD 和 CMD 规范的区别?
- 66. ES6 模块与 CommonJS 模块、AMD、CMD 的差异。
- 67. requireJS 的核心原理是什么?(如何动态加载的?如何避免多次加载的?如何 缓存的?)
- 68. JS 模块加载器的轮子怎么造,也就是如何实现一个模块加载器?
- 69. ECMAScript6 怎么写 class,为什么会出现 class 这种东西?
- 70. documen.write 和 innerHTML 的区别?
- 71. DOM 操作——怎样添加、移除、移动、复制、创建和查找节点?
- 72. innerHTML 与 outerHTML 的区别?
- 73. .call() 和 .apply() 的区别?
- 74. JavaScript 类数组对象的定义?
- 75. 数组和对象有哪些原生方法,列举一下?
- 76. 数组的 fill 方法?
- 77. [,,,] 的长度?
- 78. JavaScript 中的作用域与变量声明提升?
- 79. 如何编写高性能的 Javascript ?
- 80. 简单介绍一下 V8 引擎的垃圾回收机制
- 81. 哪些操作会造成内存泄漏?
- 82. 需求:实现一个页面操作不会整页刷新的网站,并且能在浏览器前进、后退时正确响应。给出你的技术实现方案?
- 83. 如何判断当前脚本运行在浏览器还是 node 环境中?(阿里)
- 84. 把 script 标签放在页面的最底部的 body 封闭之前和封闭之后有什么区别?浏览器会如何解析它们?
- 85. 移动端的点击事件的有延迟,时间是多久,为什么会有? 怎么解决这个延时?
- 86. 什么是“前端路由”?什么时候适合使用“前端路由”?“前端路由”有哪些优点和缺点?
- 87. 如何测试前端代码么? 知道 BDD, TDD, Unit Test 么? 知道怎么测试你的前端工程么(mocha, sinon, jasmin, qUnit..)?
- 88. 检测浏览器版本版本有哪些方式?
- 89. 什么是 Polyfill ?
- 90. 使用 JS 实现获取文件扩展名?
- 91. 介绍一下 js 的节流与防抖?
- 92. Object.is() 与原来的比较操作符 “===”、“==” 的区别?
- 93. escape,encodeURI,encodeURIComponent 有什么区别?
- 94. Unicode 和 UTF-8 之间的关系?
- 95. js 的事件循环是什么?
- 96. js 中的深浅拷贝实现?
- 97. 手写 call、apply 及 bind 函数
- 98. 函数柯里化的实现
- 99. 为什么 0.1 0.2 != 0.3?如何解决这个问题?
- 100. 原码、反码和补码的介绍
- 101. toPrecision 和 toFixed 和 Math.round 的区别?
- 102. 什么是 XSS 攻击?如何防范 XSS 攻击?
- 103. 什么是 CSP?
- 104. 什么是 CSRF 攻击?如何防范 CSRF 攻击?
- 105. 什么是 Samesite Cookie 属性?
- 106. 什么是点击劫持?如何防范点击劫持?
- 107. SQL 注入攻击?
- 108. 什么是 MVVM?比之 MVC 有什么区别?什么又是 MVP ?
- 109. vue 双向数据绑定原理?
- 110. Object.defineProperty 介绍?
- 111. 使用 Object.defineProperty() 来进行数据劫持有什么缺点?
- 112. 什么是 Virtual DOM?为什么 Virtual DOM 比原生 DOM 快?
- 113. 如何比较两个 DOM 树的差异?
- 114. 什么是 requestAnimationFrame ?
- 115. 谈谈你对 webpack 的看法
- 116. offsetWidth/offsetHeight,clientWidth/clientHeight 与 scrollWidth/scrollHeight 的区别?
- 117. 谈一谈你理解的函数式编程?
- 118. 异步编程的实现方式?
- 119. Js 动画与 CSS 动画区别及相应实现
- 120. get 请求传参长度的误区
- 121. URL 和 URI 的区别?
- 122. get 和 post 请求在缓存方面的区别
- 123. 图片的懒加载和预加载
- 124. mouseover 和 mouseenter 的区别?
- 125. js 拖拽功能的实现
- 126. 为什么使用 setTimeout 实现 setInterval?怎么模拟?
- 127. let 和 const 的注意点?
- 128. 什么是 rest 参数?
- 129. 什么是尾调用,使用尾调用有什么好处?
- 130. Symbol 类型的注意点?
- 131. Set 和 WeakSet 结构?
- 132. Map 和 WeakMap 结构?
- 133. 什么是 Proxy ?
- 134. Reflect 对象创建目的?
- 135. require 模块引入的查找方式?
- 136. 什么是 Promise 对象,什么是 Promises/A 规范?
- 137. 手写一个 Promise
- 138. 如何检测浏览器所支持的最小字体大小?
- 139. 怎么做 JS 代码 Error 统计?
- 140. 单例模式模式是什么?
- 141. 策略模式是什么?
- 142. 代理模式是什么?
- 143. 中介者模式是什么?
- 144. 适配器模式是什么?
- 145. 观察者模式和发布订阅模式有什么不同?
- 146. Vue 的生命周期是什么?
- 147. Vue 的各个生命阶段是什么?
- 148. Vue 组件间的参数传递方式?
- 149. computed 和 watch 的差异?
- 150. vue-router 中的导航钩子函数
- 151. $route 和 $router 的区别?
- 152. vue 常用的修饰符?
- 153. vue 中 key 值的作用?
- 154. computed 和 watch 区别?
- 155. keep-alive 组件有什么作用?
- 156. vue 中 mixin 和 mixins 区别?
- 157. 开发中常用的几种 Content-Type ?
- 158. 如何封装一个 javascript 的类型判断函数?
- 159. 如何判断一个对象是否为空对象?
- 160. 使用闭包实现每隔一秒打印 1,2,3,4
- 161. 手写一个 jsonp
- 162. 手写一个观察者模式?
- 163. EventEmitter 实现
- 164. 一道常被人轻视的前端 JS 面试题
- 165. 如何确定页面的可用性时间,什么是 Performance API?
- 166. js 中的命名规则
- 167. js 语句末尾分号是否可以省略?
- 168. Object.assign()
- 169. Math.ceil 和 Math.floor
- 170. js for 循环注意点
- 171. 一个列表,假设有 100000 个数据,这个该怎么办?
- 172. js 中倒计时的纠偏实现?
- 173. 进程间通信的方式?
- 174. 如何查找一篇英文文章中出现频率最高的单词?
- 框架
- Vue 常考基础知识点
- Vue 常考进阶知识点
- 对于MVVM的理解
- Vue的生命周期
- Vue实现数据双向绑定的原理
- Vue组件间的参数传递
- Vue的路由实现:hash模式 和 history模式
- Vue与Angular以及React的区别
- Vue路由的钩子函数
- Vuex是什么?怎么使用?哪种功能场景使用它?
- Vue-cli如何新增自定义指令
- Vue如何自定义一个过滤器
- 对keep-alive 的了解
- 一句话就能回答的Vue面试题
- React 常考基础知识点
- React 常考进阶知识点
- 浏览器
- 性能与安全
- 性能
- 安全
- 网络与操作系统
- 计算机网络知识总结
- 计算机操作系统
- 设计模式
- 算法
- 排序
- 冒泡排序
- 选择排序
- 插入排序
- 希尔排序
- 归并排序
- 快速排序
- 堆排序
- 基数排序
- 快速排序相对于其他排序效率更高的原因
- 系统自带排序实现
- 稳定性
- 排序面试题目总结
- 树
- 二叉树相关性质
- 满二叉树
- 完全二叉树
- 平衡二叉查找树(AVL)
- B-树
- B+树
- 数据库索引
- 红黑树
- Huffman 树
- 二叉查找树
- 求解二叉树中两个节点的最近公共祖先节点
- 链表
- 反转单向链表
- 动态规划
- 爬楼梯问题
- 递归方法分析
- 备忘录方法
- 迭代法
- 经典笔试题
- 1. js 实现一个函数,完成超过范围的两个大整数相加功能
- 2. js 如何实现数组扁平化?
- 3. js 如何实现数组去重?
- 4. 如何求数组的最大值和最小值?
- 5. 如何求两个数的最大公约数?
- 6. 如何求两个数的最小公倍数?
- 7. 实现 IndexOf 方法?
- 8. 判断一个字符串是否为回文字符串?
- 9. 实现一个累加函数的功能比如 sum(1,2,3)(2).valueOf()
- 10. 使用 reduce 方法实现 forEach、map、filter
- 11. 设计一个简单的任务队列,要求分别在 1,3,4 秒后打印出 "1", "2", "3"
- 12. 如何查找一篇英文文章中出现频率最高的单词?