内置对象 - 知蛛网全局对象与值
1. 全局对象(Global Object)
// 浏览器环境:window、self、globalThis
// Node.js环境:global、globalThis
// ES2020 引入了 globalThis
console.log(globalThis); // 在所有环境中都指向全局对象
// 全局属性
console.log(Infinity); // 无穷大
console.log(NaN); // 非数字
console.log(undefined); // 未定义
console.log(null); // 空值
// 全局函数
console.log(eval("2 + 2")); // 4(慎用)
console.log(parseInt("42px")); // 42
console.log(parseFloat("3.14em")); // 3.14
console.log(isNaN("hello")); // true
console.log(isFinite(Infinity)); // false
console.log(decodeURI("%E4%BD%A0%E5%A5%BD")); // "你好"
console.log(encodeURI("你好世界")); // "%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C"
2. 值属性
// Infinity
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(Infinity > 1000); // true
console.log(Infinity + Infinity); // Infinity
console.log(Infinity * 0); // NaN
// NaN
console.log(0 / 0); // NaN
console.log(Math.sqrt(-1)); // NaN
console.log(NaN === NaN); // false(特殊)
console.log(isNaN(NaN)); // true
console.log(Number.isNaN(NaN)); // true(ES6 更安全)
// undefined 和 null
let x;
console.log(x); // undefined
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object"(历史遗留)
console.log(null == undefined); // true
console.log(null === undefined); // false
基本包装对象
1. Boolean 对象
// 布尔值 vs Boolean对象
const bool = true; // 原始值
const boolObj = new Boolean(true); // 对象
console.log(typeof bool); // "boolean"
console.log(typeof boolObj); // "object"
console.log(bool instanceof Boolean); // false
console.log(boolObj instanceof Boolean); // true
// 自动装箱
const str = "hello";
console.log(str.length); // 5(自动创建 String 对象)
// Boolean 转换规则
console.log(Boolean(0)); // false
console.log(Boolean(1)); // true
console.log(Boolean("")); // false
console.log(Boolean("hello")); // true
console.log(Boolean([])); // true
console.log(Boolean({})); // true
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
2. Number 对象
// 数值常量
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
console.log(Number.MIN_VALUE); // 5e-324
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
console.log(Number.POSITIVE_INFINITY); // Infinity
console.log(Number.NEGATIVE_INFINITY); // -Infinity
console.log(Number.EPSILON); // 2.220446049250313e-16
console.log(Number.NaN); // NaN
// Number 方法
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite(42)); // true
console.log(Number.isInteger(42.0)); // true
console.log(Number.isInteger(42.5)); // false
console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER)); // true
console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false
console.log(Number.parseFloat("3.14px")); // 3.14
console.log(Number.parseInt("1010", 2)); // 10(二进制转换)
// 数值格式化
const num = 123456.789;
console.log(num.toFixed(2)); // "123456.79"
console.log(num.toExponential(2)); // "1.23e+5"
console.log(num.toPrecision(4)); // "1.235e+5"
console.log(num.toLocaleString("zh-CN")); // "123,456.789"
console.log(num.toLocaleString("de-DE")); // "123.456,789"
// 特殊数值处理
console.log((0.1 + 0.2).toFixed(10)); // "0.3000000000"
console.log(Number.EPSILON); // 最小精度值
3. String 对象
// 字符串创建
const str1 = "Hello"; // 字面量
const str2 = String("Hello"); // 构造函数
const str3 = new String("Hello"); // String对象(不推荐)
// 字符串属性
const str = "Hello World";
console.log(str.length); // 11
console.log(str[0]); // "H"(ES5)
console.log(str.charAt(0)); // "H"
console.log(str.charCodeAt(0)); // 72(ASCII)
console.log(str.codePointAt(0)); // 72(ES6,支持Unicode)
// 字符串查询
console.log(str.includes("World")); // true(ES6)
console.log(str.startsWith("Hello")); // true(ES6)
console.log(str.endsWith("World")); // true(ES6)
console.log(str.indexOf("o")); // 4
console.log(str.lastIndexOf("o")); // 7
console.log(str.search(/world/i)); // 6(正则搜索)
// 字符串操作
console.log(str.slice(0, 5)); // "Hello"
console.log(str.substring(0, 5)); // "Hello"
console.log(str.substr(6, 5)); // "World"(已废弃)
console.log(str.split(" ")); // ["Hello", "World"]
console.log(str.split(/(?= )/)); // ["Hello", " World"](正向预查)
// 字符串修改
console.log(str.toLowerCase()); // "hello world"
console.log(str.toUpperCase()); // "HELLO WORLD"
console.log(str.trim()); // "Hello World"(去掉两端空白)
console.log(str.trimStart()); // "Hello World"(ES2019)
console.log(str.trimEnd()); // "Hello World"(ES2019)
console.log(str.replace("World", "JavaScript")); // "Hello JavaScript"
console.log(str.replace(/[aeiou]/g, "*")); // "H*ll* W*rld"
// 字符串填充
console.log("5".padStart(3, "0")); // "005"(ES2017)
console.log("5".padEnd(3, "0")); // "500"(ES2017)
// 模板字符串(ES6)
const name = "John";
const age = 30;
console.log(`My name is ${name} and I'm ${age} years old.`);
console.log(String.raw`Hello\nWorld`); // "Hello\\nWorld"(原始字符串)
集合对象
1. Array 对象
// 数组创建
const arr1 = [1, 2, 3]; // 字面量
const arr2 = new Array(1, 2, 3); // 构造函数
const arr3 = Array.of(1, 2, 3); // ES6
const arr4 = Array.from("123"); // ES6,从可迭代对象创建
const sparse = new Array(5); // 创建长度为5的空数组
const filled = Array(5).fill(0); // [0, 0, 0, 0, 0]
// 数组属性
const arr = [1, 2, 3, 4, 5];
console.log(arr.length); // 5
arr.length = 3; // 截断数组
console.log(arr); // [1, 2, 3]
// 数组检测
console.log(Array.isArray(arr)); // true
console.log(arr instanceof Array); // true
// 数组访问和修改
console.log(arr[0]); // 1
console.log(arr.at(-1)); // 3(ES2022,负索引)
arr[1] = 20; // 修改元素
// 数组遍历
arr.forEach((item, index) => {
console.log(item, index);
});
const doubled = arr.map(x => x * 2); // [2, 40, 6]
const filtered = arr.filter(x => x > 2); // [20, 3]
const sum = arr.reduce((acc, cur) => acc + cur, 0); // 24
// 数组查找
console.log(arr.includes(20)); // true(ES2016)
console.log(arr.find(x => x > 10)); // 20(ES6)
console.log(arr.findIndex(x => x > 10)); // 1(ES6)
console.log(arr.indexOf(20)); // 1
console.log(arr.lastIndexOf(3)); // 2
// 数组操作
const newArr = arr.concat([4, 5]); // [1, 20, 3, 4, 5]
console.log(arr.slice(1, 3)); // [20, 3]
console.log(arr.splice(1, 1, 99)); // 返回删除的元素:[20]
console.log(arr); // [1, 99, 3]
// 数组排序
const nums = [3, 1, 4, 1, 5, 9];
console.log(nums.sort()); // [1, 1, 3, 4, 5, 9]
console.log(nums.sort((a, b) => b - a)); // 降序:[9, 5, 4, 3, 1, 1]
console.log(nums.reverse()); // [1, 1, 3, 4, 5, 9]
// 数组转换
console.log(arr.join("-")); // "1-99-3"
console.log(arr.toString()); // "1,99,3"
// 数组解构(ES6)
const [first, ...rest] = arr;
console.log(first, rest); // 1 [99, 3]
2. Map 对象
// Map 创建
const map = new Map();
// 基本操作
map.set("name", "John");
map.set("age", 30);
map.set({ id: 1 }, "object key"); // 对象作为键
console.log(map.get("name")); // "John"
console.log(map.has("age")); // true
console.log(map.size); // 3
map.delete("age");
console.log(map.size); // 2
map.clear();
console.log(map.size); // 0
// 初始化
const map2 = new Map([
["key1", "value1"],
["key2", "value2"],
["key3", "value3"],
]);
// 遍历
map2.forEach((value, key) => {
console.log(key, value);
});
for (const [key, value] of map2) {
console.log(key, value);
}
// 获取键值
console.log([...map2.keys()]); // ["key1", "key2", "key3"]
console.log([...map2.values()]); // ["value1", "value2", "value3"]
console.log([...map2.entries()]); // 键值对数组
// 对象转Map
const obj = { a: 1, b: 2, c: 3 };
const map3 = new Map(Object.entries(obj));
// Map转对象
const obj2 = Object.fromEntries(map3);
3. Set 对象
// Set 创建
const set = new Set();
// 基本操作
set.add(1);
set.add(2);
set.add(2); // 重复,不会添加
set.add("text");
set.add({ a: 1 });
console.log(set.has(1)); // true
console.log(set.size); // 4
set.delete(1);
console.log(set.size); // 3
// 初始化
const set2 = new Set([1, 2, 3, 4, 4, 5]);
console.log(set2.size); // 5(去重)
// 遍历
set2.forEach(value => {
console.log(value);
});
for (const value of set2) {
console.log(value);
}
// 集合运算
const setA = new Set([1, 2, 3]);
const setB = new Set([2, 3, 4]);
// 并集
const union = new Set([...setA, ...setB]);
console.log([...union]); // [1, 2, 3, 4]
// 交集
const intersection = new Set([...setA].filter(x => setB.has(x)));
console.log([...intersection]); // [2, 3]
// 差集
const difference = new Set([...setA].filter(x => !setB.has(x)));
console.log([...difference]); // [1]
// 数组去重
const arr = [1, 2, 2, 3, 4, 4, 5];
const unique = [...new Set(arr)];
console.log(unique); // [1, 2, 3, 4, 5]
4. WeakMap 和 WeakSet
// WeakMap - 键必须是对象,弱引用
const wm = new WeakMap();
let obj = { id: 1 };
wm.set(obj, "secret data");
console.log(wm.get(obj)); // "secret data"
obj = null; // obj被垃圾回收时,WeakMap中的条目也会被自动移除
// 无法遍历WeakMap,也没有size属性
// WeakSet - 值必须是对象,弱引用
const ws = new WeakSet();
let obj1 = { a: 1 };
let obj2 = { b: 2 };
ws.add(obj1);
ws.add(obj2);
console.log(ws.has(obj1)); // true
obj1 = null; // obj1被垃圾回收时,自动从WeakSet中移除
日期与时间
1. Date 对象
// 创建日期
const now = new Date(); // 当前时间
const specific = new Date(2024, 0, 1); // 2024年1月1日(月份0-11)
const fromString = new Date("2024-01-01T00:00:00");
const fromTimestamp = new Date(1704067200000); // 时间戳
// 获取日期组件
const date = new Date();
console.log(date.getFullYear()); // 2024
console.log(date.getMonth()); // 0-11
console.log(date.getDate()); // 1-31
console.log(date.getDay()); // 0-6(0=周日)
console.log(date.getHours()); // 0-23
console.log(date.getMinutes()); // 0-59
console.log(date.getSeconds()); // 0-59
console.log(date.getMilliseconds()); // 0-999
// UTC 方法
console.log(date.getUTCFullYear()); // UTC年份
console.log(date.getUTCHours()); // UTC小时
// 设置日期
date.setFullYear(2025);
date.setMonth(11); // 12月
date.setDate(25);
date.setHours(12, 30, 0, 0); // 12:30:00.000
// 日期格式化
console.log(date.toString()); // "Tue Dec 25 2024 12:30:00 GMT+0800"
console.log(date.toDateString()); // "Tue Dec 25 2024"
console.log(date.toTimeString()); // "12:30:00 GMT+0800"
console.log(date.toISOString()); // "2024-12-25T04:30:00.000Z"
console.log(date.toUTCString()); // "Wed, 25 Dec 2024 04:30:00 GMT"
console.log(date.toLocaleString()); // 本地化格式
console.log(date.toLocaleDateString("zh-CN")); // "2024/12/25"
console.log(date.toLocaleTimeString("en-US")); // "12:30:00 PM"
// 时间戳
console.log(date.getTime()); // 时间戳(毫秒)
console.log(Date.now()); // 当前时间戳
console.log(date.valueOf()); // 同getTime()
// 日期运算
const start = new Date();
// ... 执行一些操作
const end = new Date();
const duration = end - start; // 毫秒差
// 日期比较
const d1 = new Date(2024, 0, 1);
const d2 = new Date(2024, 0, 2);
console.log(d1 < d2); // true
console.log(d1.getTime() === d2.getTime()); // 精确比较
2. 国际化 API(Intl)
// 数字格式化
const number = 1234567.89;
const formatter = new Intl.NumberFormat("zh-CN", {
style: "currency",
currency: "CNY",
minimumFractionDigits: 2,
});
console.log(formatter.format(number)); // "¥1,234,567.89"
const percent = new Intl.NumberFormat("en-US", {
style: "percent",
minimumFractionDigits: 1,
});
console.log(percent.format(0.123)); // "12.3%"
// 日期格式化
const date = new Date();
const dateFormatter = new Intl.DateTimeFormat("zh-CN", {
year: "numeric",
month: "long",
day: "numeric",
weekday: "long",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
timeZone: "Asia/Shanghai",
});
console.log(dateFormatter.format(date)); // "2024年1月1日星期一 12:30:00"
// 相对时间格式化
const rtf = new Intl.RelativeTimeFormat("zh-CN", {
numeric: "auto",
});
console.log(rtf.format(-1, "day")); // "昨天"
console.log(rtf.format(2, "week")); // "2周后"
// 列表格式化
const list = ["苹果", "香蕉", "橙子"];
const listFormatter = new Intl.ListFormat("zh-CN", {
style: "long",
type: "conjunction",
});
console.log(listFormatter.format(list)); // "苹果、香蕉和橙子"
// 排序
const words = ["张三", "李四", "王五"];
const collator = new Intl.Collator("zh-CN");
console.log(words.sort(collator.compare)); // 按中文拼音排序
数学与数字
1. Math 对象
// 数学常数
console.log(Math.PI); // 3.141592653589793
console.log(Math.E); // 2.718281828459045
console.log(Math.LN2); // 0.6931471805599453
console.log(Math.LN10); // 2.302585092994046
console.log(Math.LOG2E); // 1.4426950408889634
console.log(Math.LOG10E); // 0.4342944819032518
console.log(Math.SQRT2); // 1.4142135623730951
console.log(Math.SQRT1_2); // 0.7071067811865476
// 舍入方法
console.log(Math.round(4.7)); // 5
console.log(Math.ceil(4.1)); // 5
console.log(Math.floor(4.9)); // 4
console.log(Math.trunc(4.9)); // 4(ES6)
console.log(Math.round(-4.5)); // -4
console.log(Math.floor(-4.5)); // -5
// 随机数
console.log(Math.random()); // 0-1之间的随机数
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 最大值/最小值
console.log(Math.max(1, 2, 3, 4, 5)); // 5
console.log(Math.min(1, 2, 3, 4, 5)); // 1
console.log(Math.max(...[1, 2, 3, 4, 5])); // 5(使用扩展运算符)
// 绝对值
console.log(Math.abs(-10)); // 10
// 指数和对数
console.log(Math.pow(2, 3)); // 8
console.log(2 ** 3); // 8(ES7)
console.log(Math.sqrt(16)); // 4
console.log(Math.cbrt(27)); // 3(立方根,ES6)
console.log(Math.exp(1)); // Math.E
console.log(Math.log(Math.E)); // 1
console.log(Math.log10(100)); // 2(ES6)
console.log(Math.log2(8)); // 3(ES6)
// 三角函数
console.log(Math.sin(Math.PI / 2)); // 1
console.log(Math.cos(Math.PI)); // -1
console.log(Math.tan(Math.PI / 4)); // 0.9999999999999999
console.log(Math.asin(1)); // π/2
console.log(Math.acos(0)); // π/2
console.log(Math.atan(1)); // π/4
console.log(Math.atan2(1, 1)); // π/4
// 双曲函数
console.log(Math.sinh(0)); // 0
console.log(Math.cosh(0)); // 1
console.log(Math.tanh(0)); // 0
// 其他
console.log(Math.sign(-5)); // -1(ES6)
console.log(Math.sign(0)); // 0
console.log(Math.sign(5)); // 1
console.log(Math.clz32(1)); // 31(前导0的个数,ES6)
console.log(Math.imul(2, 3)); // 6(32位乘法,ES6)
console.log(Math.fround(1.337)); // 单精度浮点数(ES6)
console.log(Math.hypot(3, 4)); // 5(欧几里得距离,ES6)
2. BigInt
// BigInt 创建
const big1 = 123456789012345678901234567890n;
const big2 = BigInt("123456789012345678901234567890");
const big3 = BigInt(Number.MAX_SAFE_INTEGER) + 1n;
console.log(typeof big1); // "bigint"
// 运算
console.log(big1 + big2); // 加法
console.log(big1 - big2); // 减法
console.log(big1 * big2); // 乘法
console.log(big1 / big2); // 除法(取整)
console.log(big1 % big2); // 取余
console.log(big1 ** 2n); // 幂运算
// 比较
console.log(1n < 2n); // true
console.log(1n == 1); // true(宽松相等)
console.log(1n === 1); // false(严格不相等)
// 位运算
console.log(5n & 3n); // 1n(按位与)
console.log(5n | 3n); // 7n(按位或)
console.log(5n ^ 3n); // 6n(按位异或)
console.log(~5n); // -6n(按位非)
console.log(5n << 2n); // 20n(左移)
console.log(5n >> 1n); // 2n(右移)
// 转换
console.log(Number(123n)); // 123
console.log(String(123n)); // "123"
console.log(Boolean(0n)); // false
console.log(Boolean(1n)); // true
正则表达式
1. RegExp 对象
// 创建正则表达式
const regex1 = /pattern/flags; // 字面量
const regex2 = new RegExp('pattern', 'flags'); // 构造函数
// 标志
// g - 全局匹配
// i - 不区分大小写
// m - 多行匹配
// s - 点号匹配所有字符(ES2018)
// u - Unicode模式
// y - 粘性匹配
// d - 生成索引(ES2022)
const regex = /hello/gi;
// 正则方法
const str = 'Hello hello HELLO';
console.log(regex.test(str)); // true
console.log(str.match(regex)); // ["Hello", "hello", "HELLO"]
console.log(str.search(regex)); // 0
console.log(str.replace(regex, 'Hi')); // "Hi Hi Hi"
console.log(str.split(/hello/i)); // ["", " ", " ", ""]
// 正则属性
console.log(regex.source); // "hello"
console.log(regex.flags); // "gi"
console.log(regex.global); // true
console.log(regex.ignoreCase); // true
console.log(regex.multiline); // false
// 捕获组
const dateRegex = /(\d{4})-(\d{2})-(\d{2})/;
const dateStr = '2024-01-01';
const match = dateRegex.exec(dateStr);
console.log(match[0]); // "2024-01-01"
console.log(match[1]); // "2024"
console.log(match[2]); // "01"
console.log(match[3]); // "01"
// 命名捕获组(ES2018)
const namedRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const namedMatch = namedRegex.exec(dateStr);
console.log(namedMatch.groups.year); // "2024"
console.log(namedMatch.groups.month); // "01"
console.log(namedMatch.groups.day); // "01"
// 后行断言(ES2018)
console.log(/(?<=\$)\d+/.exec('$100')[0]); // "100"(后行断言)
console.log(/\d+(?=%)/.exec('100%')[0]); // "100"(先行断言)
// Unicode 属性(ES2018)
console.log(/\p{Script=Han}/u.test('汉')); // true(匹配汉字)
console.log(/\p{Emoji}/u.test('😀')); // true(匹配表情符号)
// 索引捕获(ES2022)
const regexWithIndices = /(\d{4})-(\d{2})-(\d{2})/d;
const indicesMatch = regexWithIndices.exec('Date: 2024-01-01');
console.log(indicesMatch.indices);
// [[10, 20], [10, 14], [15, 17], [18, 20]]
// 粘性匹配(y标志)
const stickyRegex = /hello/y;
stickyRegex.lastIndex = 0;
console.log(stickyRegex.test('hello')); // true
console.log(stickyRegex.lastIndex); // 5
console.log(stickyRegex.test('hello')); // false(必须从lastIndex开始)
错误处理对象
1. Error 对象
// 内置错误类型
try {
throw new Error("普通错误");
} catch (e) {
console.log(e.name); // "Error"
console.log(e.message); // "普通错误"
console.log(e.stack); // 堆栈跟踪
}
// 特定错误类型
try {
throw new TypeError("类型错误");
} catch (e) {
console.log(e instanceof TypeError); // true
}
// 自定义错误
class CustomError extends Error {
constructor(message, code) {
super(message);
this.name = this.constructor.name;
this.code = code;
this.timestamp = new Date();
// 保持正确的堆栈跟踪
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
}
try {
throw new CustomError("自定义错误", "CUSTOM_001");
} catch (e) {
console.log(e.name); // "CustomError"
console.log(e.code); // "CUSTOM_001"
}
// AggregateError(ES2021)
try {
throw new AggregateError(
[new Error("错误1"), new Error("错误2"), new Error("错误3")],
"多个错误发生"
);
} catch (e) {
console.log(e.name); // "AggregateError"
console.log(e.message); // "多个错误发生"
console.log(e.errors.length); // 3
}
其他内置对象
1. JSON 对象
const obj = {
name: "John",
age: 30,
hobbies: ["reading", "coding"],
address: {
city: "New York",
zip: "10001",
},
date: new Date(),
score: 95.5,
isAdmin: true,
salary: null,
undefinedProp: undefined,
func: function () {
return "hi";
},
};
// JSON.stringify
const jsonStr = JSON.stringify(obj);
console.log(jsonStr);
// {"name":"John","age":30,"hobbies":["reading","coding"],"address":{...}}
// 自定义序列化
const customJson = JSON.stringify(
obj,
(key, value) => {
if (typeof value === "function") return undefined;
if (value instanceof Date) return value.toISOString();
if (typeof value === "number") return Math.round(value);
return value;
},
2
); // 缩进2个空格
// JSON.parse
const parsed = JSON.parse(jsonStr);
console.log(parsed.name); // "John"
// 自定义解析
const reviver = (key, value) => {
if (key === "date") return new Date(value);
return value;
};
const parsedWithDate = JSON.parse(jsonStr, reviver);
// 错误处理
try {
JSON.parse("invalid json");
} catch (e) {
console.error("JSON解析错误:", e.message);
}
2. Promise 对象
// Promise 创建
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() > 0.5 ? resolve("成功") : reject("失败");
}, 1000);
});
// Promise 使用
promise
.then(result => console.log("成功:", result))
.catch(error => console.error("失败:", error))
.finally(() => console.log("完成"));
// Promise 静态方法
Promise.resolve("立即解决").then(console.log);
Promise.reject("立即拒绝").catch(console.error);
// Promise.all - 所有成功
Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]).then(results =>
console.log("all:", results)
); // [1, 2, 3]
// Promise.allSettled - 所有完成(ES2020)
Promise.allSettled([Promise.resolve(1), Promise.reject("错误"), Promise.resolve(3)]).then(results =>
console.log("allSettled:", results)
);
// Promise.race - 第一个完成
Promise.race([
new Promise(resolve => setTimeout(() => resolve("快"), 100)),
new Promise(resolve => setTimeout(() => resolve("慢"), 200)),
]).then(console.log); // "快"
// Promise.any - 第一个成功(ES2021)
Promise.any([Promise.reject("错误1"), Promise.resolve("成功1"), Promise.resolve("成功2")]).then(
console.log
); // "成功1"
// async/await
async function fetchData() {
try {
const result = await promise;
console.log("获取结果:", result);
} catch (error) {
console.error("错误:", error);
}
}
3. Proxy 和 Reflect
// Proxy 示例
const target = { name: "John", age: 30 };
const handler = {
get(obj, prop) {
console.log(`获取属性: ${prop}`);
return prop in obj ? obj[prop] : "默认值";
},
set(obj, prop, value) {
console.log(`设置属性: ${prop} = ${value}`);
if (prop === "age" && value < 0) {
throw new Error("年龄不能为负");
}
obj[prop] = value;
return true;
},
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // "John"
console.log(proxy.unknown); // "默认值"
proxy.age = 25; // 正常
// proxy.age = -5; // 抛出错误
// Reflect 示例
const obj = { x: 1, y: 2 };
console.log(Reflect.get(obj, "x")); // 1
console.log(Reflect.set(obj, "z", 3)); // true
console.log(Reflect.has(obj, "x")); // true
console.log(Reflect.deleteProperty(obj, "y")); // true
console.log(Reflect.ownKeys(obj)); // ["x", "z"]
最佳实践
1. 对象选择指南
// 1. 数据存储
// - 简单对象:使用普通对象 {}
// - 键值对集合:使用 Map(键可以是任意类型)
// - 唯一值集合:使用 Set(自动去重)
// - 弱引用集合:使用 WeakMap/WeakSet
// 2. 数组处理
// - 基本操作:使用 Array 方法(map、filter、reduce等)
// - 高性能数值计算:使用 TypedArray
// - 大整数:使用 BigInt
// 3. 字符串操作
// - 基本操作:使用 String 方法
// - 模板字符串:使用反引号 ``
// - 复杂替换:使用正则表达式
// 4. 日期处理
// - 基本操作:使用 Date 对象
// - 复杂格式化:使用 Intl.DateTimeFormat
// - 时区处理:使用 moment.js 或 date-fns 库
// 5. 数学计算
// - 基本运算:使用 Math 对象
// - 复杂计算:考虑使用专门的数学库
// 6. 错误处理
// - 用户错误:使用内置 Error 类型
// - 自定义错误:继承 Error 类
// - 多个错误:使用 AggregateError
2. 性能优化建议
// 1. 避免不必要的对象创建
// ❌ 不好的做法
for (let i = 0; i < 1000; i++) {
const obj = new Object(); // 每次循环创建新对象
// ...
}
// ✅ 好的做法
let obj = {};
for (let i = 0; i < 1000; i++) {
// 重用对象
Object.assign(obj, { /* 新属性 */ });
// ...
}
// 2. 使用合适的数据结构
// 频繁查找:使用 Map 而不是对象
// 唯一值:使用 Set 而不是数组
// 数值数组:使用 TypedArray
// 3. 缓存计算结果
const cache = new Map();
function expensiveOperation(input) {
if (cache.has(input)) {
return cache.get(input);
}
const result = /* 计算 */;
cache.set(input, result);
return result;
}
// 4. 避免深度复制
// 使用浅复制:{...obj}, Object.assign(), slice()
// 必要时才使用深复制:JSON.parse(JSON.stringify()), structuredClone()
3. 兼容性考虑
// 特性检测
if (typeof BigInt !== "undefined") {
// 支持 BigInt
const big = 123n;
} else {
// 降级方案
console.warn("BigInt not supported");
}
// Polyfill 示例
if (!Array.prototype.flat) {
Array.prototype.flat = function (depth = 1) {
return this.reduce((acc, val) => {
if (Array.isArray(val) && depth > 0) {
acc.push(...val.flat(depth - 1));
} else {
acc.push(val);
}
return acc;
}, []);
};
}
// 使用 babel 或 core-js 进行 polyfill