JavaScript的基础、型别
JavaScript 的资料型别是什么?如何判断?
- 两大类:Primitive 与 Object
- Primitive(原始型别,不可变)
string、number、boolean、null、undefined、bigint、symbol
原始型别 不可变:修改变量 = 重新赋值,而不是修改原值。
Object(物件,可变) • 一般 Object • Array • Array.isArray([1, 2, 3]) // true • Function • Object.prototype.toString.call(fn) // [object Function]
- 为什么 typeof 容易误导? • typeof null === “object” → 历史遗留 bug • typeof [] === “object” → 分不出数组
- 最稳的判断:Object.prototype.toString.call(value) 可区分几乎所有类型。
在 JavaScript 当中,==、=== 与 Object.is()的区别
整体结论:
- 实际开发主用 ===。
- 需要区分 +0 / -0 和 NaN 时,选 Object.is()。
- 避免 ==。
console.log(Object.is(+0, -0)); // false
console.log(Object.is(NaN, NaN)); // true
JavaScript null、undefined 与 undeclared 的区别?
- undefined:已声明,未赋值 → 尚未
- null:已声明,值为空 → 没有
- undeclared:未声明 → 不存在
在 JavaScript 中,Map 与 object 的差别?为什么有 object 还需要 Map?
- Map 不是 Object 的一种。两者用途不一样:Object 表示数据;Map 表示关联。
- 需要大量查找/删除/任意类型 key → 用 Map。做映射(ID → 对象,DOM → 状态,缓存、图结构、计数器)
- 结构化数据 → 用 Object。描述数据结构(用户、订单、配置、表单等)
Object 的 key 是“名字”(string/symbol),Map 的 key 是“真实的引用”(any type)
原始物件不支援迭代 (iteration),但 Map 物件有
- forEach(callback)遍历所有键值对。forEach 的本质就是“对每一项执行副作用”。
const users = [
{ first: 'Tom', last: 'Smith' },
{ first: 'Jane', last: 'Doe' },
{ first: 'Lily', last: 'Deng' }
];
users.forEach((user) => {
user.fullName = `${user.first} ${user.last}`;
});
console.log(users);
输出
[
{ first: 'Tom', last: 'Smith', fullName: 'Tom Smith' },
{ first: 'Jane', last: 'Doe', fullName: 'Jane Doe' },
{ first: 'Lily', last: 'Deng', fullName: 'Lily Deng' }
]
- for…of,按顺序执行异步任务,并且一旦出错就提前中断。
const urls = [
'/api/user',
'/api/orders',
'/api/notifications'
];
async function fetchSequential() {
for (const url of urls) {
try {
const res = await fetch(url); // for...of 支持 await
if (!res.ok) {
console.log('Failed at:', url);
break; // 可提前中断
}
const data = await res.json();
console.log('Success:', url, data);
} catch (error) {
console.log('Error:', url, error);
break; // 可提前中断
}
}
}
fetchSequential();
原始物件的元素没有顺序性,Map 物件则有顺序
Map 提供许多键值对常用的方法,但原始物件没有。因为在 JS 里,“API”指的不是 HTTP API,而是对象提供给你的可调用方法(public interface)map.forEach() 是 Map 的 API
- set / get / has / delete / clear / size
- keys / values / entries
- for…of 直接遍历 Map
请解释 Set、Map、WeakSet 和 WeakMap 的区别?
- 内存(Memory, RAM)是程序运行时放数据的地方,是你的应用读写最快的存储资源。
- 带宽(Bandwidth) = 搬运文件的速度
- DOM = 浏览器呈现网页时生成的一棵“可操作的对象树”。
Set类似数组,但值唯一。接受所有类型(primitive + object)。常用方法:add、delete、has、size。遍历返回
[value, value]。WeakSet(Set 的弱引用版本)核心区别:只能存 object。弱引用:对象如果外部没有引用,会被垃圾回收。因此适合做:记录 DOM 节点状态、避免内存泄漏。
Map类似 Object,但:键可以是任何类型。有序。方法丰富:set、get、has、delete、size。遍历方法:keys、values、entries。
WeakMap(Map 的弱引用版本)核心区别:key 只能是 object 或 Symbol。key 也是弱引用:外部引用断开 → 自动被 GC 清理。Map 则不会自动清理(强引用)。用途:存放与 DOM 相关的状态,而不污染 DOM 本体。避免内存泄漏(当 DOM 被移除后,可自动 GC)
- 弱引用的适用情境在于,如果引用的物件在未来可能会被删除的情况、且不想防止被垃圾回收时,就适合用 WeakMap 或 WeakSet。例如,如果我们想要记录一些与 DOM 节点相关的数据,有一种方法是使用 Expando 扩充节点上的资讯,但坏处是会直接修改到这个 DOM 节点、且如果未来这个节点被移除时,相关资讯不会被垃圾回收掉,这时如果是使用 WeakMap 就会是很好的替代方案。
- 解释:DOM 需要存状态,因为 UI 有状态。理想做法:把 DOM 当 key,把业务状态放 WeakMap。节点消失 → 状态自动清理,不污染 DOM,也不泄漏内存。
在 JavaScript 中 0.1 + 0.2 会是多少?为什么?如何避免相关问题?
- 会是 0.30000000000000004
- 解决方法参考:nstr
//Step 1: Convert to fixed decimal
0.14499999582767487.toFixed(10) // "0.1449999958"
//Step 2: Detect consecutive patterns
"0.1449999958"
// ^^^^^
// 5 consecutive "9"s detected (≥ threshold of 4)
//Step 3: Truncate and clean up
"0.1449999958" → "0.145"
严格模式 (use strict) 的用途?有什么好处?
- 在脚本或函数开头写 “use strict”,让 JavaScript 用更严格、更规范的方式执行。
- 禁止未声明变量
"use strict";
x = 10; // 报错:x 未声明
- 禁止重复的函数参数名
"use strict";
function sum(a, a) {} // 报错
- 禁止删除不可删除的标识符,在 JavaScript 里,变量(var / let / const 声明的东西)本质上都属于不可删除的标识符。
"use strict";
var y = 20;
delete y; // 报错
写程式时该用三元运算子 (ternary operator) 吗?
- 三元运算子适合“简单条件分支”,不适合“复杂决策树”。一旦逻辑超过一行看不懂,就不要用它。
- 短路运算
&&:如果左边为 falsy → 直接返回左边。如果左边为 truthy → 返回右边