备战校招第三天

  1. css 垂直水平居中

  2. 闭包

  3. 浏览器缓存相关

  4. 性能优化


css 垂直水平居中

第一种 position+transform

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 {
width: 800px;
height: 800px;
background-color: gray;

position: relative;
}
#cbox {
width: 300px;
height: 300px;
background-color: orange;

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
<body>
<div id="box">
<div id="cbox"></div>
</div>
</body>

第二种 flex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<style>
#box {
width: 800px;
height: 800px;
background-color: gray;

display: flex;
align-items: center;
justify-content: center;
}
#cbox {
width: 300px;
height: 300px;
background-color: orange;
}
</style>
<body>
<div id="box">
<div id="cbox"></div>
</div>
</body>

第三种 padding + margin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
#box {
width: 800px;
height: 800px;
background-color: gray;

box-sizing: border-box;
padding: 250px 0;
}
#cbox {
width: 300px;
height: 300px;
background-color: orange;

margin: 0 auto;
}
</style>
<body>
<div id="box">
<div id="cbox"></div>
</div>
</body>

以上三种代码显示效果均为

image-20200626093651504

闭包

闭包可以从内部函数访问到外部函数作用域。

  • 模拟私有方法

    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
    27
    var 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>

    运行上面代码,点击会发现,输出的均为

    image-20200626101322509

    这是因为虽形成了三个闭包作用域,但他们共享了一个词法作用域,在这个作用域中又只有一个变量 ivar 的作用域数函数作用域,但定义 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>
  • 性能

    在处理速度和内存消耗方面都是有负面影响,所以原则是少用,别再不必要的地方使用。

缓存相关

缓存

浏览器缓存机制

强缓存

浏览器加载资源前,会根据请求头 expirescache-control 判断是否命中强缓存,如果命中,则不会发送请求到服务器。

Expires

http1.0 提出,表示资源过期时间的 header,描述为一个绝对时间,服务器返回。(如果修改本地时间,可能会造成缓存失效。)

1
expires: Tue, 14 Jul 2020 13:13:53 GMT

Cache-Control

http1.1 提出,优先级高于 Expires ,表示相对时间

缓存请求指令

1
2
3
4
5
Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>] // 表示客户端接受一个已过期的资源
Cache-Control: min-fresh=<seconds> // 表示客户端获取一个在指定的秒数内保持最新状态的响应
Cache-control: no-cache // 在发布缓存前,强制要求把缓存提交给服务器进行验证(协商缓存验证)
Cache-control: no-store // 不存储和不使用任何缓存

缓存响应指令

1
2
3
4
5
6
7
Cache-control: must-revalidate
Cache-control: no-cache // 如缓存请求指令
Cache-control: no-store // 如缓存请求指令
Cache-control: public // 表示响应可以为任何对象(客户端、代理服务器等,包括通常不可缓存的
Cache-control: private // 只能被单个用户缓存(私有缓存)
Cache-Control: max-age=<seconds> // 缓存存储最大周期,单位秒
Cache-control: s-maxage=<seconds> // 覆盖 max-age或 expires 头,仅在共享缓存中有效

协商缓存

如果没有命中强缓存,浏览器会发送一个请求到服务器,通过 last-modifiedetag 验证资源是否命中协商缓存,如果命中,会将这个请求返回,但不返回资源的数据,依旧从缓存中读取资源。

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

用户操作和行为

img

  • 普通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

性能优化

https://www.cnblogs.com/xiaohuochai/p/9178390.html