css 垂直水平居中
闭包
浏览器缓存相关
性能优化
css 垂直水平居中
第一种 position+transform
1 | <style> |
第二种 flex
1 | <style> |
第三种 padding + margin
1 | <style> |
以上三种代码显示效果均为
闭包
闭包可以从内部函数访问到外部函数作用域。
模拟私有方法
Java有私有属性,
private
,而 js 也可以通过模拟来实现私有变量和方法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
27var makeCounter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
};
var Counter1 = makeCounter();
var Counter2 = makeCounter();
console.log(Counter1.value()); /* logs 0 */
Counter1.increment();
Counter1.increment();
console.log(Counter1.value()); /* logs 2 */
Counter1.decrement();
console.log(Counter1.value()); /* logs 1 */
console.log(Counter2.value()); /* logs 0 */经典闭包问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
var btns = document.getElementsByTagName('button')
for (var i = 0; i < btns.length; i++) {
var btn = btns[i]
btn.onclick = function () {
console.log('点击了第' + i + '个按钮')
}
}
</script>运行上面代码,点击会发现,输出的均为
这是因为虽形成了三个闭包作用域,但他们共享了一个词法作用域,在这个作用域中又只有一个变量
i
,var
的作用域数函数作用域,但定义i
外并未有函数,所以这里的i
是挂载在全局的。在循环后执行点击时间前,i
的值都已经指向了最后一个数5
了。解决方法(修改下列任何一种都可以)
将
var i=0;
换为let i=0;
,这种也是最简单的,let
是 ES6 修复var
的设计缺陷而出现的使用更多的闭包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
function handleClick(i) {
return function() {
console.log('点击了第' + i + '个按钮')
}
}
var btns = document.getElementsByTagName('button')
for (var i = 0; i < btns.length; i++) {
var btn = btns[i]
btn.onclick = handleClick(i)
}
</script>匿名闭包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
var btns = document.getElementsByTagName('button')
for (var i = 0; i < btns.length; i++) {
;(function (i) {
var btn = btns[i]
btn.onclick = function () {
console.log('点击了第' + i + '个按钮')
}
})(i)
}
</script>
性能
在处理速度和内存消耗方面都是有负面影响,所以原则是少用,别再不必要的地方使用。
缓存相关
浏览器缓存机制
强缓存
浏览器加载资源前,会根据请求头 expires
和 cache-control
判断是否命中强缓存,如果命中,则不会发送请求到服务器。
Expires
http1.0 提出,表示资源过期时间的 header,描述为一个绝对时间,服务器返回。(如果修改本地时间,可能会造成缓存失效。)
1 | expires: Tue, 14 Jul 2020 13:13:53 GMT |
Cache-Control
http1.1 提出,优先级高于 Expires
,表示相对时间
缓存请求指令
1 | Cache-Control: max-age=<seconds> |
缓存响应指令
1 | Cache-control: must-revalidate |
协商缓存
如果没有命中强缓存,浏览器会发送一个请求到服务器,通过 last-modified
和 etag
验证资源是否命中协商缓存,如果命中,会将这个请求返回,但不返回资源的数据,依旧从缓存中读取资源。
Last-Modified 和 If-Modified-Since
http1.0 引入,Last-Modified
是响应头中的属性,表示资源的修改时间。浏览器请求时会在请求头上加上 If-Modified-Since
(上次返回的Last-Modified
的值),询问是否资源有更新,如有立刻将新的资源返回。
准确性不如 Etag
,所以这个为备用机制。
ETag 和 If-None-Match
http1.1 引入,Etag
就像一个指纹,资源变化都会导致ETag变化,跟最后修改时间没有关系,ETag
可以保证每一个资源是唯一的。优先级高于 Last-Modified
。
If-None-Match
的header会将上次返回的Etag
发送给服务器,询问该资源的Etag
是否有更新,有变动就会发送新的资源回来
异同点总结
- 相同点,都是从客户端缓存中加载资源,而不是从服务器加载资源。
- 不同点,强缓存不发送请求到服务器,协商缓存会发送请求到服务器。
缓存优先级顺序(由低到高)
强缓存
- Expire
- Cache-Control
协商缓存
- Last-Modified 和 If-Modified-Since
- ETag 和 If-None-Match
用户操作和行为
- 普通F5刷新,强缓存失效,只进行协商缓存
- Ctrl+F5刷新,强缓存和协商缓存均失效
性能优化
图片优化,可以减少 http
请求数量
- 雪碧图、精灵图
- Base64
- 字体图标
压缩资源大小
- HTML压缩
- css 压缩
- js 压缩与混淆
- 图片压缩,(可以尝试webp格式)
- 开启 gzip
缓存
- DNS 缓存
- http 缓存
- 浏览器缓存
其他优化
数据校验,避免无用数据重复发送
不使用
css @import
比如你使用空的 src 和 href(会重定向到当前页面地址)
使用CDN
减少重绘回流
webpack 打包使用优化插件
参考
闭包
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
缓存
https://github.com/amandakelake/blog/issues/41
https://segmentfault.com/a/1190000021248694
性能优化