1.let、var、const
- var 存在变量提升,只提升声明,不提升赋值;
变量提升:var 有变量提升;let/const 同样提升,但存在暂时性死区,声明前无法访问;
作用域:var 仅函数 / 全局作用域,无块级作用域;let/const 拥有块级作用域;
重复声明:var 允许重复定义;let、const 同一作用域不可重复声明;
全局挂载:全局 var 会绑定 window,let/const 不会;
赋值规则:var/let 可声明不赋值;const 声明必须初始化赋值;
修改权限:var/let 可重新赋值;const 禁止重新赋值,引用类型内部属性可修改
const 保存的是内存地址,基本类型值不可变;对象、数组这类引用类型,地址不变,内部属性、数组元素可以随意修改
2.解构赋值
- q:解构默认值什么时候才会触发生效?
a:只有对应值严格等于 undefined 时默认值才生效;null、空字符串、数字 0 都属于有值,不会启用默认值。 q:解构赋值能不能用于基本数据类型?比如 const [a] = 123 会报错吗,为什么?
a:会报错。解构底层要求右侧可迭代,数字、布尔、null、undefined 不可迭代,数组解构只能接收数组、字符串、Set 等可迭代类型。undefined
* 变量声明了,但从未赋值
* 对象访问不存在的属性
* 函数无返回值,默认返回 undefined
* 函数少传参数,形参为 undefined
* 数组解构空位无匹配值
null
* 空值,表示一个空对象指针
* 只能手动赋值,JS 不会自动生成 null
* undefined == null → true
* undefined === null → false
3.扩展运算符 ... + rest 剩余参数
rest 和 arguments 区别?
*rest 是真正数组,可以直接调用 reduce/map 等数组方法;arguments 是类数组,需转数组才能用数组 API;*rest 仅收集剩余参数,arguments 包含函数所有实参;
*rest 是 ES6 语法,箭头函数不支持 arguments,但可以用 rest;
*rest 语义清晰,现代开发优先使用。
扩展运算符 ... 只是浅拷贝,只拷贝一层;如果对象 / 数组存在多层嵌套,内层引用类型和原数据共用同一个地址,修改内层会影响原对象。
Set的用法?
* Set 是集合,元素唯一,自动去重;
* 内部判断相等使用 SameValueZero,认为 NaN === NaN、+0 === -0;
* 只能存值,没有键值对;
* 可遍历,支持 for...of
4.字符串的方法
- includes 与 indexOf 的区别
* includes
- 作用:查找目标字符串首次出现的下标
- 匹配到:返回对应数字下标(0、1、2…)
- 未匹配到:固定返回
-1 - 判断存在需要额外写判断:
str.indexOf('xx') !== -1
* indexOf
- 作用:单纯判断字符串是否包含目标片段
- 匹配到:
true - 未匹配到:
false - 无需额外判断,语义直观
2.repeat 完整用法
str.repeat(count) : <1> count:重复次数,参数要求非负整数;<2>返回:重复拼接后的新字符串,不修改原字符串
特殊:
① count = 0 :返回空字符串
② 小数参数 :自动向下取整,舍弃小数部分,不会四舍五入
③ 负数 / Infinity: 直接抛出RangeError报错
④ 参数会自动转数字
5.函数的拓展
- 箭头函数可以使用 arguments 获取全部实参吗?
箭头函数没有 arguments,只能用 rest 参数接收所有参数
6.数组的拓展
- Array.from的用法
* 基础语法 Array.from(类数组/可迭代对象, 映射函数?, this指向?)
* 返回全新数组,不会修改原数据
三大核心作用
| 核心作用 | 特征 | 示列 |
| 将类数组对象转为数组 | 类数组特征:包含数字下标 + length 属性,不能直接调用数组方法 常见类数组:DOM 节点集合、arguments、自定义类数组{0: 'a', 1: 'b', length: 2} | // 自定义类数组 const likeArr = { 0: "x", 1: "y", length: 2 }; const arr = Array.from(likeArr); console.log(arr); // ["x","y"] |
| 将可迭代对象转为数组 | 实现了 Iterator 接口的数据:字符串、Set、Map | // 字符串转数组 Array.from("es6"); // ["e","s","6"] // Set去重转数组 const s = new Set([1,2,2]); Array.from(s); // [1,2] // Map提取值 const m = new Map([["a",1],["b",2]]); Array.from(m); // [["a",1],["b",2]] |
| 快速生成指定长度数组 | 普通new Array(n)生成空空位数组,无法直接 map;Array.from生成填满内容的数组。 | // 生成5个0 Array.from({ length: 5 }, () => 0); // [0,0,0,0,0] / / 生成 0,1,2,3,4 有序数组 Array.from({ length: 5 }, (item, index) => index); // [0,1,2,3,4] |
2.第二个参数:映射回调(等同 map) ; 优势:转换 + 遍历映射一步完成,少一次循环。
3.第三个参数:修改回调内 this 指向
7.对象的拓展
1.Object.entries 完整用法 + 场景
- 接收一个对象,返回二维数组,格式
[[key1, value1], [key2, value2]] - 只提取对象自身可枚举属性,原型上的属性不会获取。
- Map 支持二维数组初始化,是对象快速转 Map 的标准写法
const map = new Map(Object.entries(obj));
2.Object.freeze用法
- 冻结一个对象,让对象无法新增、删除、修改属性,也不能修改属性描述符,浅层次完全只读。
Object.freeze仅冻结第一层,如果属性是引用类型(数组、对象),内层依然可以修改。
//实现深冻结 function deepFreeze(obj) { Object.keys(obj).forEach(key => { const val = obj[key]; if (typeof val === "object" && val !== null) { deepFreeze(val); } }); return Object.freeze(obj); }8.promise
1. 四个静态方法标准定义
Promise.all:全部成功才 resolve;任意一个 reject,立刻 rejectPromise.race:第一个落定(成功 / 失败)的为准Promise.allSettled:全部完成才返回,无论成功失败Promise.any:第一个成功的为准;全部失败才进入 catch