方括号[]

  • 动态属性访问 obj[key] 表达式计算键名
  • 数组访问 arr[0] 索引本质是字符串
  • 计算属性名{ [key]: value }动态生成属性名(ES6)
  • 解构赋值 const [a] = [1] 提取数组或对象的值
  • 正则表达式字符集合/[aeiou]/匹配一组字符
  • 类数组操作arguments[0] 类似数组的访问方式

Symbol

Symbol 是 ES6 引入的一种 ​​ 基本数据类型,用于表示 ​​ 唯一的、不可变的值 ​​。

同步循环阻塞微队列:无限循环问题分析

问题代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function* generator() {
const value = yield Promise.resolve(1);
const value2 = yield Promise.resolve(value);
const value3 = yield Promise.resolve(value2);
return value3;
}

function run(generator) {
const iterator = generator();
const result = iterator.next(); // { value: Promise(1), done: false }

while (!result.done) {
if (result.value instanceof Promise) {
result.value.then((value) => {
result = iterator.next(value); // 🚨 永远无法执行
});
}
// result 未改变还是{ value: Promise(1), done: false } ,while 循环永远不会结束
// 🔁 无限循环开始!
}
// 🚫 永远无法到达
}

问题根源

事件循环被完全阻塞:

1
同步代码执行 → 微任务队列 → 宏任务队列 → 页面渲染 → ...

while 循环永不结束,事件循环卡在同步执行阶段,微任务队列中的回调永远得不到执行机会。

执行流程分析

  1. 首次进入循环result.done = false
  2. Promise 处理.then() 回调被加入微队列
  3. 立即回到循环开始result 状态未改变
  4. 无限循环开始:同步循环持续运行,阻塞事件循环
  5. 微队列积压:Promise 回调永远无法执行

核心问题

  • 同步循环不结束 → 事件循环完全停滞
  • 变量更新无效 → 回调中的赋值无法影响同步循环
  • 微任务被阻塞 → Promise.then() 回调无法执行
  • 程序可能崩溃 → 长时间同步操作阻塞 UI 线程

异步递归:

在异步操作中实现递归调用时,需要通过 Promise 链和微任务队列来维持执行流程和返回值传递。由于递归调用被放入微任务队列中,而同步代码执行完毕后微任务尚未执行,因此无法直接获取返回值。此时,必须将递归调用的返回值包装为 Promise,并通过 .then() 方法获取最终结果。

可选链?.

在访问对象的深层属性时,如果中间某个属性不存在(null 或 undefined),直接访问会抛出错误,使用可选链?.可以避免这种错误,会短路返回 undefined

空值合并??

  • 空值合并符??:在 JavaScript 中,逻辑或操作符 || 常用于设置默认值,但它会 ​​ 将所有“假值”(Falsy Values)视为无效 ​​(如 0、’’、false、NaN 等),导致意外覆盖有效值(“假值”作为有效值)
  • 空值合并符??:只在左侧值为 null 或 undefined 时返回右侧值,其他情况下返回左侧值

代理Proxy

反射Reflect

Class

integrity 属性

当你在 HTML 文件中通过 <script><link> 标签加载外部资源时,浏览器会使用 integrity 属性指定的哈希值与实际加载的文件内容进行对比。如果文件内容与指定的哈希值不一致,浏览器会拒绝加载这个文件。

1
2
3
4
5
<script
src="https://cdn.example.com/script.js"
integrity="sha384-xyz123..."
crossorigin="anonymous"
></script>

页面请求资源会携带发送资源方的路径

“一个页面请求另一个资源时,会携带 Referer,Referer 是一个 URL,根据不同的策略决定携带的程度”

  • 时机:页面请求资源时
  • 内容:Referer 是一个 URL
  • 控制:通过策略决定详细程度
  • 目的:平衡隐私保护和功能需求

📊 具体完整程度对比

策略 Referer URL 完整程度 示例
no-referrer 🚫 无 URL (完全不发送)
origin 🔵 仅协议+域名+端口 https://news.com:443
unsafe-url 🔴 完整 URL https://news.com/article.html?id=123&source=fb#section
strict-origin-when-cross-origin 🟡 智能选择 同源时完整,跨源时仅源

💡 实际意义

  • 隐私保护:防止敏感页面 URL 泄露给第三方
  • 安全考虑:防止 HTTPS 页面的 Referer 泄露到 HTTP
  • 开发控制:开发者可以精确控制信息共享程度

JavaScript 中的数组与伪数组

1. 真正的数组特征

要被称为真正的数组,JavaScript 对象需要具备以下特征:

  • length 属性:表示数组的元素个数,动态变化。
  • 数字索引:通过数字索引(从 0 开始)访问元素。
  • 数组方法:支持数组相关的方法,如 .push().pop().shift().unshift().map().forEach() 等。
  • 继承自 Array.prototype:数组实例继承自 Array.prototype,因此可以使用数组的内建方法。
  • constructor 属性是 Array:数组对象的 constructor 属性指向 Array 构造函数。
  • 可遍历:可以使用 for...of.forEach() 等方法遍历。
  • typeof 返回 "object":虽然数组的 typeof 运算符返回 "object",但通过 Array.isArray() 可以验证它是一个数组。
  • 支持动态大小:可以随时增加或删除元素,数组的长度会自动更新。
  • 包含任意类型的数据:数组的元素可以是任何类型的数据,包括数字、字符串、对象或其他数组。

例子:

1
2
3
4
let arr = [1, "two", { name: "three" }];
console.log(Array.isArray(arr)); // true
arr.push(4);
console.log(arr.length); // 4

2. 伪数组特征

伪数组(Array-like Object)是类似数组的对象,虽然它看起来像数组,但它并不是一个真正的数组。常见的伪数组包括:

  • arguments 对象
  • NodeList(如 document.querySelectorAll() 返回的节点列表)
  • HTMLCollection(如 document.getElementsByTagName() 返回的集合)

伪数组的特点:

  • 具有 length 属性,表示伪数组的元素个数。
  • 数字索引,可以通过索引访问元素(例如 pseudoArray[0])。
  • 没有数组方法:伪数组不能调用如 .push().pop() 等数组方法。

伪数组的限制:

  • constructor 不是 Array,而是 Object
  • 无法直接使用数组方法,如 .forEach().map() 等。

例子:

1
2
3
4
5
6
7
8
function demo() {
console.log(arguments instanceof Array); // false
console.log(Array.isArray(arguments)); // false
console.log(arguments.length); // 3
console.log(arguments[0]); // 1
}

demo(1, 2, 3);

3. 区别:真正数组 vs 伪数组

  • Array vs Array-like:真正的数组具有完整的数组方法,继承自 Array.prototype;伪数组只是具有数组的部分特性,不能使用数组方法。
  • constructor:真正的数组的 constructorArray,伪数组的 constructorObject
  • 方法支持:真正的数组支持 .push().map() 等,而伪数组则不支持这些方法。

4. 跨越伪数组与数组的界限

伪数组不能直接使用数组方法,但可以通过 Array.from() 或扩展运算符(...)将伪数组转换为真正的数组,从而可以使用数组的所有方法。

例子:

1
2
3
4
5
let pseudoArray = { 0: "a", 1: "b", length: 2 };
let arr = Array.from(pseudoArray);
console.log(Array.isArray(arr)); // true
arr.push("c");
console.log(arr); // ['a', 'b', 'c']

总结

  • 数组(Array) 是一种特殊的对象,具备完整的数组方法和特性,能够动态增加或删除元素,且具备 length 属性和 Array.prototype 的方法。
  • 伪数组 是一种类数组对象,具有 length 和索引属性,但缺少数组方法和 Array.prototype 的继承,不能直接使用数组的方法。

window 对象的部分属性

核心概念:window 对象的层级

浏览器中有一个窗口对象的层级关系:

  • window.self: 指向当前窗口自身。这是我们最常使用的,平时写 window.location 其实就是 window.self.location 的简写。
  • window.parent: 指向直接包含当前框架的父窗口。
    • 如果当前窗口就是顶级窗口,那么 window.parent 就等于 window.self
  • window.top: 指向最顶层的浏览器窗口。它刨开了所有的框架嵌套,直接指向浏览器标签页本身。
    • 如果页面中没有框架,那么 window.top 也等于 window.self

load 和 error 事件是浏览器用于 HTML 标签显式加载的外部资源触发的。然而,出于安全考虑,