# ES6+

# map 与 weakmap 的区别

点击
  • Map 对象的键可以是任何类型,但 WeakMap 对象中的键只能是对象引用。
  • WeakMap 不能包含无引用的对象,否则会被自动清除出集合(垃圾回收机制)。
  • WeakMap 不支持对键和值进行遍历
  • WeakMap 不会阻止在没有对键的引用时对键进行垃圾收集,而 Map 无限期地维护对键和值的引用。
  • Map 的键可以是任意类型,WeakMap 只接受对象作为键(null 除外),不接受其他类型的值作为键。

# Symbol

点击

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它属于 JavaScript 语言的原生数据类型之一. undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、大整数(BigInt)、对象(Object)

如果 Symbol 的参数是一个对象,就会调用该对象的 toString()方法,将其转为字符串,然后才生成一个 Symbol 值。

const obj = {
  toString() {
    return "abc";
  },
};
const sym = Symbol(obj);
sym; // Symbol(abc)
1
2
3
4
5
6
7

Symbol 值作为属性名,遍历对象的时候,该属性不会出现在 for...in、for...of 循环中,也不会被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。

  1. 可以通过 Object.getOwnPropertySymbols(obj) 获取
  2. Reflect.ownKeys(obj)

有时,我们希望重新使用同一个 Symbol 值,Symbol.for()方法可以做到这一点

let s1 = Symbol.for("foo");
let s2 = Symbol.for("foo");
s1 === s2; // true
Symbol.keyFor(s1); // foo
1
2
3
4

Symbol.for()的这个全局登记特性,可以用在不同的 iframe 或 service worker 中取到同一个值。

# css 文件在加载的过程种出现了阻塞会怎样, 加载 html 文档 10ms、加载 css10s 会出现什么现象

点击

css 文件在加载的过程种出现了阻塞 不会阻塞 DOM 的解析, 但是会阻塞 DOM 的渲染.

简单阐述一下浏览器的解析渲染过程,解析 DOM 生成 DOM Tree,解析 CSS 生成 CSSOM Tree,两者结合生成 render tree 渲染树,最后浏览器根据渲染树渲染至页面。由此可以看出 DOM Tree 的解析和 CSSOM Tree 的解析是互不影响的,两者是并行的。因此 CSS 不会阻塞页面 DOM 的解析,但是由于 render tree 的生成是依赖 DOM Tree 和 CSSOM Tree 的,因此 CSS 必然会阻塞 DOM 的渲染。

JS 会阻塞 DOM 解析

  • CSS 不会阻塞 DOM 解析,但是会阻塞 DOM 渲染,严谨一点则是 CSS 会阻塞 render tree 的生成,进而会阻塞 DOM 的渲染
  • JS 会阻塞 DOM 解析
  • CSS 会阻塞 JS 的执行
  • 浏览器遇到<script>标签且没有 defer 或 async 属性时会触发页面渲染
  • Body 内部的外链 CSS 较为特殊,会形成 (FOUC (opens new window),Flash of Unstyled Content) 现象,请慎用

# Reflect

点击

Reflect 对象与 Proxy 对象一样,也是 ES6 为了操作对象而提供的新 API。

Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。这就让 Proxy 对象可以方便地调用对应的 Reflect 方法,

# async await 如何实现的

点击
function awaitFn(backData) {
  return new Promise((rj) => {
    setTimeout(() => {
      rj(++backData);
    }, 1000);
  });
}
function* asyncFn() {
  let res = yield awaitFn(0);
  console.log(res, "第1次");
  res = yield awaitFn(res);
  console.log(res, "第2次");
  res = yield awaitFn(res);
  console.log(res, "第3次");
  res = yield awaitFn(res);
  console.log(res, "第4次");
}
function init(fn) {
  const f = fn();
  function next(data) {
    const res = f.next(data);
    if (res.done) return res.value;
    Promise.resolve(res.value).then((r) => {
      next(r);
    });
  }

  next();
}
init(asyncFn); // 然后执行init,把之前的asyncFn当形参传入
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
Last Updated: 10/20/2023, 12:10:22 AM