1. HTTP 缓存相关的响应头信息
- Cache-Control // 控制缓存
- Expire // 控制缓存
- ETag // 校验缓存用
- Last-Modified // 校验缓存用
2. 浏览器缓存相关标识符
与浏览器缓存的字段有如下几种:
- Cache-Control (指定缓存机制,覆盖其它设置)
- Expires (http1.0字段,指定缓存的过期时间, 到了HTTP/1.1,Expire已经被Cache-Control替代)
- Last-Modified (资源最后一次的修改时间)
- ETag (唯一标识请求资源的字符串)
- If-Modified-Since (缓存校验字段, 值为资源最后一次的修改时间, 即上次收到的Last-Modified值)
- If-None-Match (同上, 处理方式与之相反)
3. 箭头函数和普通函数的区别
🌼 箭头函数的特点:
-
没有自己的
this,所以this从外部获取,继承外部的执行上下文中的this。 -
没有
prototype属性,没有原型和super,所以箭头函数也不能作为构造函数,也不能使用new。 -
通过
call()或apply()方法调用箭头函数时,只能传递参数,不能绑定this,第一个参数会被忽略。 -
不能使用
yield关键字,因此箭头函数不能用作Generator函数。
4. v-for 遍历,能否用 key 做数组下标?
可以,但不推荐。
key 的作用主要是为了高效的更新 虚拟DOM,使用 v-for 更新已渲染的元素列表时,默认 就地复用 策略,列表数据修改的时候,会根据 key 值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素。
如果我们使用了数组的下标来作为 key,而数据又恰好只在数组末尾新增元素的话,不会有影响;但是如果在数组中间插入新数据,就会使后面没有被修改的数据反复更新,就会很没效率。
所以我们要尽可能在使用 v-for 时使用 key 来给每个节点做一个唯一标识,Diff算法 就可以正确的识别此节点,在新增节点的同时复用原来的节点。
5. 为什么 vue2 不用 proxy?
vue2之前之所以不用 Proxy,是因为 Proxy 是 es6 提供的新特性,兼容性不好,最主要的是这个属性无法用 polyfill 来兼容。Polyfill 指的是用于实现浏览器并不支持的原生 API 的代码。
比如说 querySelectorAll 是很多现代浏览器都支持的原生 Web API, 但是有些古老的浏览器并不支持,那么假设有人写了一段代码来实现这个功能. 使这些浏览器也支持了这个功能,那么这就可以成为一个 Polyfill。
-
vue2的数据双向绑定原理使用的是es5的数据劫持object.defineProperty,如果读取数据就会触发get,修改数据就会触发set,达到数据和视图的响应和更新,但是因为js固有的特性,不能动态添加和删除属性,需要调用$set、$delete这些方法来实现动态添加双向绑定属性。 -
vue3的数据双向绑定使用的是es6的Proxy配合Reflect实现的,他比起数据劫持可以监听到对象添加属性和删除属性。
proxy的优势 Proxy 与 Object.defineProperty 优劣对比
- 响应式是惰性的。按需实现响应式,减少性能消耗。
在 Vue2 中,对于一个深层属性嵌套的对象,要劫持它内部深层次的变化,就需要递归遍历这个对象,执行 Object.defineProperty 把每一层对象数据都变成响应式的,这无疑会有很大的性能消耗。
在 Vue3 中,使用 Proxy API 并不能监听到对象内部深层次的属性变化,因此它的处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响应式,简单的可以说是按需实现响应式,减少性能消耗。
- Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的
为什么要用 Proxy 替代 defineProperty ?
-
defineProperty API 的局限性最大原因是它只能针对单例属性做监听。 Vue2.x中的响应式实现正是基于defineProperty中的descriptor,对 data 中的属性做了遍历 + 递归,为每个属性设置了 getter、setter。这也就是为什么 Vue 只能对 data 中预定义过的属性做出响应的原因。
-
Proxy API的监听是针对一个对象的,那么对这个对象的所有操作会进入监听操作, 这就完全可以代理所有属性,将会带来很大的性能提升和更优的代码。 Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
🌼 1. 什么是跨域访问,浏览器对哪些跨域访问是允许的,哪些是禁止的
(1)什么是跨域访问
跨域指的是浏览器不能执行其他网站的脚本,从一个域名的网页去请求另一个域名的资源时,协议、域名、端口任一不同,都是跨域。跨域是由浏览器的同源策略造成的,是浏览器对 JavaScript 施加的安全限制。
(2)浏览器对哪些跨域访问是允许的
带 src 的标签一般都是允许的,如 img、script 标签,还有 iframe、link 标签。
(3)哪些是禁止的
- Cookie、LocalStorage、IndexedDB 等存储性内容
- 操作DOM 节点
- Ajax请求发送后,结果被浏览器拦截了
(4)解决浏览器跨域限制的方法
- jsonp
- 代理服务器
- CORS 跨域资源共享
- 服务器 niginx 反向代理
- 后台语言处理
- websocket
🌼 2. localStorage 和 cookie 的区别
localstorage 和 cookie 都可以用来做本地存储,实现数据持久化。但它们的区别还是很多的,主要体现在以下几个方面:
1. 存储量不同。 cookie 的存储量在 4k 左右,而 localStorage 的存储量有 5M。
2. 有效时间不同。 cookie 的有效期可以自行设置,而 localstorage 可以一直生效。
3. 在向服务器请求时,cookie 会被携带,而 localstorage 不会。 同源的 cookie 信息会自动作为请求头的一部分发给服务器。而 localstorage 一般仅用作客户端的数据存储。
4. 存储类型。 cookie 存储的是字符串,而 localStorage 存储的是对象。
🌼 1. 编写形状类,编写一个子类正方形类,使可以计算周长和面积
class Shape {
constructor(length, width) {
this.length = length
this.width = width
}
}
class Square extends Shape {
constructor(length, width) {
super(length, width)
}
area() {
return this.length * this.length
}
circumference() {
return this.length * 4
}
}
var square1 = new Square(7)
console.log('正方形的面积是' + square1.area()); // 正方形的面积是49
console.log('正方形的周长是' + square1.circumference()); // 正方形的周长是28
🌼 2. 使用 Promise、async、await 实现红绿灯切换,并在控制台打印输出,红灯:30s,黄灯5s,绿灯20s
<style>
#light {
/* background:red; */
width: 50px;
height: 50px;
border-radius: 50%;
border: 1px solid #000;
}
</style>
<div id="light"></div>
<script>
function sleep(duration) {
return new Promise(function (resolve, reject) {
setTimeout(resolve, duration);
})
}
async function changeLightColor(duration, color) {
document.getElementById('light').style.background = color
console.log('color', color)
await sleep(duration)
}
async function act() {
while (true) {
await changeLightColor(3000, 'green');
await changeLightColor(1000, 'yellow');
await changeLightColor(2000, 'red');
}
}
act()
</script>