关于Web APIs总结第三篇(完)
五.Bom操作
1.Window对象
1.1BOM(浏览器对象模型)
#mermaid-svg-0rFR2n6BJKWN5bvQ {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-0rFR2n6BJKWN5bvQ .error-icon{fill:#552222;}#mermaid-svg-0rFR2n6BJKWN5bvQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0rFR2n6BJKWN5bvQ .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-0rFR2n6BJKWN5bvQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0rFR2n6BJKWN5bvQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0rFR2n6BJKWN5bvQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0rFR2n6BJKWN5bvQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0rFR2n6BJKWN5bvQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0rFR2n6BJKWN5bvQ .marker.cross{stroke:#333333;}#mermaid-svg-0rFR2n6BJKWN5bvQ svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0rFR2n6BJKWN5bvQ .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0rFR2n6BJKWN5bvQ .cluster-label text{fill:#333;}#mermaid-svg-0rFR2n6BJKWN5bvQ .cluster-label span{color:#333;}#mermaid-svg-0rFR2n6BJKWN5bvQ .label text,#mermaid-svg-0rFR2n6BJKWN5bvQ span{fill:#333;color:#333;}#mermaid-svg-0rFR2n6BJKWN5bvQ .node rect,#mermaid-svg-0rFR2n6BJKWN5bvQ .node circle,#mermaid-svg-0rFR2n6BJKWN5bvQ .node ellipse,#mermaid-svg-0rFR2n6BJKWN5bvQ .node polygon,#mermaid-svg-0rFR2n6BJKWN5bvQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0rFR2n6BJKWN5bvQ .node .label{text-align:center;}#mermaid-svg-0rFR2n6BJKWN5bvQ .node.clickable{cursor:pointer;}#mermaid-svg-0rFR2n6BJKWN5bvQ .arrowheadPath{fill:#333333;}#mermaid-svg-0rFR2n6BJKWN5bvQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0rFR2n6BJKWN5bvQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0rFR2n6BJKWN5bvQ .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-0rFR2n6BJKWN5bvQ .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-0rFR2n6BJKWN5bvQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0rFR2n6BJKWN5bvQ .cluster text{fill:#333;}#mermaid-svg-0rFR2n6BJKWN5bvQ .cluster span{color:#333;}#mermaid-svg-0rFR2n6BJKWN5bvQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0rFR2n6BJKWN5bvQ :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} window navigater loaction document history screen
window对象是一个全局对象,也可以说是JavaScript中的顶级对象
像document、alert()、console.log()这些都是window的属性,基本BOM的属性和方法都是window的。
所有通过var定义在全局作用域中的变量、函数都会变成window对象的属性和方法
window对象下的属性和方法调用的时候可以省略window
1.2定时器-延时函数
JavaScript 内置的一个用来让代码延迟执行的函数,叫 setTimeout
语法:
setTimeout(回调函数,等待的毫秒数)
setTimeout 仅仅只执行一次,所以可以理解为就是把一段代码延迟执行, 平时省略window
清除延时函数:
let timer = setTimeout(回调函数,等待的毫秒数)
clearTimeout(timer)
注意点
- 延时器需要等待,所以后面的代码先执行
- 每一次调用延时器都会产生一个新的延时器
1.3JS执行机制
JavaScript 的执行机制是其核心特性之一,涉及单线程、事件循环(Event Loop)、调用栈、任务队列等概念。以下是详细解析:
1.3.1 单线程与异步
JavaScript 是单线程语言,但通过异步非阻塞机制处理并发操作(如网络请求、定时器等)。
关键点:
- 单线程:同一时间只能执行一个任务,避免多线程的复杂性(如死锁)。
- 异步任务:通过回调函数、Promise、async/await 实现非阻塞操作。
1.3.2执行上下文(Execution Context)
代码执行时的环境,分为:
- 全局执行上下文:代码首次执行时创建。
- 函数执行上下文:每次调用函数时创建。
- Eval 执行上下文(较少用)。
每个上下文包含:
- 变量对象(VO):存储变量、函数声明。
- 作用域链(Scope Chain):用于变量查找。
- this 绑定:指向当前执行环境。
1.3.3. 调用栈(Call Stack)
- **后进先出(LIFO)**结构,记录函数的调用顺序。
- 函数执行时入栈,执行完毕出栈。
- 栈溢出:递归过深时抛出
RangeError
。
示例:
function foo() { console.log(\"foo\"); bar();}function bar() { console.log(\"bar\");}foo(); // 调用栈顺序: foo → bar
1.3.4. 事件循环(Event Loop)
协调调用栈和任务队列的机制,分为以下步骤:
(1) 任务分类
-
同步任务:立即执行,进入调用栈。
-
异步任务
:分为两类:
- 宏任务(Macro Task):
setTimeout
、setInterval
、DOM 事件、I/O 操作。 - 微任务(Micro Task):
Promise.then
、MutationObserver
、queueMicrotask
。
- 宏任务(Macro Task):
(2) 执行流程
- 执行全局同步代码(调用栈)。
- 遇到异步任务:
- 宏任务 → 交给 Web API 处理,完成后回调放入宏任务队列。
- 微任务 → 回调放入微任务队列。
- 调用栈为空时:
- 优先清空微任务队列(全部执行)。
- 取出宏任务队列的第一个任务执行。
- 重复步骤 3(事件循环)。
示例:
console.log(\"1\"); // 同步setTimeout(() => console.log(\"2\"), 0); // 宏任务Promise.resolve().then(() => console.log(\"3\")); // 微任务console.log(\"4\"); // 同步// 输出顺序: 1 → 4 → 3 → 2
1.3.5任务队列(Task Queues)
- 宏任务队列:每次事件循环处理一个宏任务。
- 微任务队列:必须在当前宏任务结束后立即清空(优先级更高)。
执行顺序:
同步代码 → 微任务 → 宏任务 → (下一轮循环)
1.3.6. 关键概念对比
setTimeout
、setInterval
Promise.then
、queueMicrotask
1.3.7. 常见面试题分析
题目 1
setTimeout(() => console.log(\"A\"), 0);Promise.resolve().then(() => console.log(\"B\"));console.log(\"C\");
答案:C → B → A
解析:同步代码 C
最先执行;微任务 B
优先于宏任务 A
。
题目 2
console.log(\"Start\");setTimeout(() => console.log(\"Timeout\"), 0);Promise.resolve().then(() => { console.log(\"Promise\"); setTimeout(() => console.log(\"Inner Timeout\"), 0);});console.log(\"End\");
答案:Start → End → Promise → Timeout → Inner Timeout
解析:
- 同步代码
Start
、End
。 - 微任务
Promise
执行,其内部的setTimeout
作为新宏任务加入队列。 - 执行初始宏任务
Timeout
,最后执行Inner Timeout
。
1.3.8. 总结
- 调用栈处理同步任务,任务队列管理异步任务。
- 微任务优先级高于宏任务。
- 事件循环是 JS 实现非阻塞的核心机制。
理解这些机制能有效避免异步编程中的常见问题(如执行顺序错误)。
1.4location对象
location
对象是浏览器提供的 JavaScript 内置对象,它包含了当前文档的 URL 信息,并提供了操作浏览器地址的方法。
1.4.1. location
对象属性
location
对象包含以下属性,这些属性都是可读写的(修改它们会导致浏览器导航到新的 URL):
href
\"https://example.com:8080/path/?query=string#hash\"
protocol
\"https:\"
host
\"example.com:8080\"
hostname
\"example.com\"
port
\"8080\"
pathname
\"/path/\"
search
\"?query=string\"
hash
\"#hash\"
origin
\"https://example.com:8080\"
1.4.2. location
对象方法
assign(url)
location.assign(\"https://new.com\")
replace(url)
location.replace(\"https://new.com\")
reload()
location.reload()
reload(forceGet)
location.reload(true)
toString()
location.toString()
1.4.3. 使用示例
获取当前 URL 信息
console.log(\"完整URL:\", location.href);console.log(\"协议:\", location.protocol);console.log(\"主机:\", location.host);console.log(\"路径:\", location.pathname);console.log(\"查询参数:\", location.search);console.log(\"锚点:\", location.hash);
修改 URL
// 导航到新页面(会添加到历史记录)location.href = \"https://new.com\";// 替换当前页面(不会添加到历史记录)location.replace(\"https://new.com\");// 修改查询字符串location.search = \"?page=2\";// 修改锚点(不会重新加载页面)location.hash = \"#section2\";
解析查询参数
function getQueryParams() { const params = {}; const queryString = location.search.substring(1); const pairs = queryString.split(\"&\"); pairs.forEach(pair => { const [key, value] = pair.split(\"=\"); params[decodeURIComponent(key)] = decodeURIComponent(value || \"\"); }); return params;}console.log(getQueryParams());
页面重定向
// 3秒后重定向setTimeout(() => { location.href = \"https://new.com\";}, 3000);// 条件重定向if (!userLoggedIn) { location.replace(\"/login\");}
1.4.4. 注意事项
- 修改
location
属性(除hash
外)会导致页面重新加载 replace()
方法不会在浏览器历史记录中创建新条目reload(true)
会绕过缓存,从服务器强制重新加载- 现代前端框架(如 React、Vue)通常使用客户端路由,直接操作
location
可能会干扰框架的路由系统
1.4.5. 与 window.location
的关系
location
对象是 window
对象的属性,因此以下两种写法是等价的:
window.location.href;location.href;
在大多数情况下,可以省略 window.
前缀直接使用 location
。
1.5navigator对象
navigator
对象是浏览器提供的 JavaScript 内置对象,它包含了有关浏览器的信息,包括浏览器名称、版本、平台、用户代理字符串等。
1.5.1. navigator
对象常用属性
appName
\"Netscape\"
(大多数现代浏览器返回此值)appVersion
\"5.0 (Windows NT 10.0; Win64; x64)\"
userAgent
\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36\"
platform
\"Win32\"
language
\"zh-CN\"
languages
[\"zh-CN\", \"zh\", \"en-US\", \"en\"]
cookieEnabled
true
onLine
true
hardwareConcurrency
8
deviceMemory
8
maxTouchPoints
5
1.5.2. navigator
对象常用方法
javaEnabled()
navigator.javaEnabled()
sendBeacon()
navigator.sendBeacon(url, data)
vibrate()
navigator.vibrate(200)
getBattery()
navigator.getBattery().then(...)
getUserMedia()
navigator.mediaDevices.getUserMedia(...)
share()
navigator.share({title: \'分享标题\', url: \'https://example.com\'})
1.5.3. 使用示例
检测浏览器基本信息
console.log(\'浏览器名称:\', navigator.appName);console.log(\'浏览器版本:\', navigator.appVersion);console.log(\'用户代理:\', navigator.userAgent);console.log(\'操作系统:\', navigator.platform);console.log(\'是否在线:\', navigator.onLine);console.log(\'是否启用cookie:\', navigator.cookieEnabled);
检测浏览器类型
function detectBrowser() { const ua = navigator.userAgent; if (ua.indexOf(\'Chrome\') > -1) return \'Chrome\'; if (ua.indexOf(\'Firefox\') > -1) return \'Firefox\'; if (ua.indexOf(\'Safari\') > -1) return \'Safari\'; if (ua.indexOf(\'Opera\') > -1) return \'Opera\'; if (ua.indexOf(\'Edge\') > -1) return \'Edge\'; if (ua.indexOf(\'MSIE\') > -1 || ua.indexOf(\'Trident/\') > -1) return \'IE\'; return \'Unknown\';}console.log(\'当前浏览器:\', detectBrowser());
使用sendBeacon发送数据
// 在页面卸载时可靠地发送数据window.addEventListener(\'unload\', function() { const data = JSON.stringify({event: \'page_exit\', time: Date.now()}); navigator.sendBeacon(\'/analytics\', data);});
检测设备特性
console.log(\'CPU核心数:\', navigator.hardwareConcurrency);console.log(\'设备内存(GB):\', navigator.deviceMemory);// 检测是否移动设备const isMobile = /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);console.log(\'是否移动设备:\', isMobile);
使用Web Share API
if (navigator.share) { document.getElementById(\'share-btn\').addEventListener(\'click\', async () => { try { await navigator.share({ title: \'Web分享示例\', text: \'看看这个有趣的网站\', url: \'https://example.com\' }); console.log(\'分享成功\'); } catch (err) { console.log(\'分享取消:\', err); } });} else { console.log(\'Web Share API不支持\');}
1.5.4. 注意事项
- 用户代理字符串不可靠:
userAgent
可以被修改,不应仅依赖它来做关键功能检测 - 隐私考虑:某些属性如
deviceMemory
可能涉及隐私,浏览器可能限制访问 - 兼容性问题:新API如
share()
、getBattery()
等不是所有浏览器都支持 - 特性检测:推荐使用特性检测而非浏览器嗅探
1.5.5. 现代API扩展
现代navigator
对象还包含许多新API:
- 媒体设备:
navigator.mediaDevices
(摄像头/麦克风访问) - 地理位置:
navigator.geolocation
- 剪贴板:
navigator.clipboard
- 蓝牙:
navigator.bluetooth
- USB:
navigator.usb
- 网络信息:
navigator.connection
这些API通常需要用户授权才能使用。
1.6histroy对象
history
对象是浏览器提供的 JavaScript 内置对象,它允许开发者操作浏览器的会话历史记录(即当前标签页访问过的 URL 历史)。
1.6.1. history
对象属性
length
history.length
scrollRestoration
auto
/manual
)history.scrollRestoration = \'manual\'
state
history.state
1.6.2. history
对象方法
- 核心导航方法
back()
history.back()
forward()
history.forward()
go(n)
history.go(-2)
(后退2页)- 现代 HTML5 History API
pushState(state, title, url)
history.pushState({page: 1}, \"Page 1\", \"?page=1\")
replaceState(state, title, url)
history.replaceState({page: 2}, \"Page 2\", \"?page=2\")
1.6.3. 使用示例
- 基本导航控制
// 后退一页document.getElementById(\'back-btn\').addEventListener(\'click\', () => { history.back();});// 前进一页document.getElementById(\'forward-btn\').addEventListener(\'click\', () => { history.forward();});// 前进或后退多页document.getElementById(\'go-btn\').addEventListener(\'click\', () => { history.go(-2); // 后退2页});
- 使用 History API 实现 SPA 路由
// 添加新历史记录function navigateTo(page) { const state = { page }; const title = `Page ${page}`; const url = `?page=${page}`; history.pushState(state, title, url); updateContent(page);}// 替换当前历史记录function replaceCurrentPage(page) { const state = { page }; const title = `Page ${page}`; const url = `?page=${page}`; history.replaceState(state, title, url); updateContent(page);}// 处理浏览器前进/后退window.addEventListener(\'popstate\', (event) => { const page = event.state?.page || 1; updateContent(page);});function updateContent(page) { document.getElementById(\'content\').textContent = `当前页面: ${page}`;}
- 状态管理示例
// 保存状态到历史记录history.pushState({ formData: { username: \'user123\', progress: 75 }}, \"Form Page\", \"/form\");// 恢复状态window.addEventListener(\'popstate\', (event) => { const savedState = event.state; if (savedState && savedState.formData) { console.log(\'恢复的表单数据:\', savedState.formData); // 填充表单... }});
- 禁止滚动恢复
// 禁用页面刷新后的自动滚动恢复if (history.scrollRestoration) { history.scrollRestoration = \'manual\';}
1.6.4. 注意事项
- 安全限制:
- 只能操作同源的历史记录
- 不能直接查看历史记录中的具体URL(隐私保护)
- URL 参数:
pushState
和replaceState
的 URL 参数必须同源- 修改 URL 不会触发页面加载,但会改变地址栏显示
- SEO 考虑:
- 使用 History API 的单页应用需要配置服务器端渲染
- 兼容性:
- HTML5 History API 在现代浏览器中完全支持
- IE 10+ 支持,但旧版 IE 支持有限
- 最佳实践:
- 总是与
popstate
事件一起使用 - 确保状态对象是可序列化的(不包含函数、循环引用等)
- 状态对象大小不宜过大(某些浏览器限制为 640k 字符)
- 总是与
1.6.5 与 window.history
的关系
history
对象是 window
对象的属性,以下两种写法等价:
window.history.back();history.back();
在大多数情况下,可以省略 window.
前缀直接使用 history
。
2.本地存储
2.1本地存储分类
2.1.1Cookie
-
特点:
-
存储大小约4KB
-
会随HTTP请求自动发送到服务器
-
可设置过期时间
-
-
使用场景:用户身份验证、会话管理
// 设置Cookiedocument.cookie = \"username=John; expires=Thu, 18 Dec 2025 12:00:00 UTC; path=/\";// 读取Cookieconst cookies = document.cookie.split(\';\');
2.1.2Web Storage
(1) localStorage
- 特点:
- 持久化存储(除非手动清除)
- 存储大小5-10MB(各浏览器不同)
- 同源策略限制
(2) sessionStorage
- 特点:
- 会话级存储(标签页关闭即清除)
- 存储大小5-10MB
- 同源策略限制
// localStorage使用localStorage.setItem(\'theme\', \'dark\');const theme = localStorage.getItem(\'theme\');// sessionStorage使用sessionStorage.setItem(\'tempData\', JSON.stringify({id: 1}));const data = JSON.parse(sessionStorage.getItem(\'tempData\'));
2.1.3IndexedDB
- 特点:
- 客户端数据库,存储大量结构化数据
- 支持事务、索引查询
- 异步API
- 使用场景:离线应用、大数据量存储
// 打开/创建数据库const request = indexedDB.open(\'myDatabase\', 1);request.onsuccess = (event) => { const db = event.target.result; // 数据库操作...};
2.1.4Cache API
- 特点:
- 用于缓存网络请求响应
- Service Worker配合使用
- 使用场景:PWA应用、离线资源缓存
caches.open(\'my-cache\').then(cache => { cache.add(\'/api/data\');});
2.2存储复杂数据类型
2.2.1JSON序列化方法
适用于Web Storage存储对象/数组
const user = { name: \"张三\", preferences: { theme: \"dark\", fontSize: 16 }};// 存储localStorage.setItem(\'user\', JSON.stringify(user));// 读取const storedUser = JSON.parse(localStorage.getItem(\'user\'));
2.2.2IndexedDB存储复杂对象
直接支持存储JavaScript对象
const transaction = db.transaction(\'users\', \'readwrite\');const store = transaction.objectStore(\'users\');store.put({ id: 1, name: \"李四\", tags: [\"vip\", \"admin\"], meta: { lastLogin: new Date() }});
2.2.3特殊数据类型处理
(1) Date对象
// 存储localStorage.setItem(\'lastUpdated\', new Date().toISOString());// 读取const date = new Date(localStorage.getItem(\'lastUpdated\'));
(2) Map/Set
const map = new Map([[\'key1\', \'value1\'], [\'key2\', \'value2\']]);// 存储localStorage.setItem(\'myMap\', JSON.stringify(Array.from(map.entries())));// 读取const mapData = new Map(JSON.parse(localStorage.getItem(\'myMap\')));
2.3实践建议
-
数据安全:
- 敏感信息不要存储在客户端
- 考虑使用加密库对数据进行加密
-
容量管理:
// 检查localStorage剩余空间function getLocalStorageRemainingSpace() { const testKey = \'test\'; let data = \'\'; try { // 填充数据直到超出限制 while(true) { data += \'xxxxxxxxxx\'; localStorage.setItem(testKey, data); } } catch (e) { localStorage.removeItem(testKey); return data.length; }}
-
错误处理:
try { localStorage.setItem(\'key\', largeData);} catch (e) { if (e.name === \'QuotaExceededError\') { console.error(\'存储空间不足\'); // 清理旧数据或提示用户 }}
-
数据版本控制:
const storageVersion = \'v2.1\';if(localStorage.getItem(\'version\') !== storageVersion) { localStorage.clear(); localStorage.setItem(\'version\', storageVersion);}
-
性能优化:
- 大数据量优先使用IndexedDB
- 频繁读写的数据可以先用内存缓存,再批量写入存储
2.4现代存储方案对比
根据应用需求选择合适的存储方案,对于现代Web应用,通常需要组合使用多种存储技术。
六.正则&阶段案例
1.正则表达式介绍
正则表达式(Regular Expression,简称 regex)是用于匹配字符串中字符组合的模式,它是一种强大的字符串处理工具,主要用于:
- 字符串搜索
- 字符串替换
- 数据验证
- 字符串提取和分割
在 JavaScript 中,正则表达式通过 RegExp
对象实现,有两种创建方式:
// 字面量形式const regex1 = /pattern/flags;// 构造函数形式const regex2 = new RegExp(\'pattern\', \'flags\');
2.正则表达式语法
2.1. 基础语法
literal
/abc/
匹配 “abc”[]
[abc]
匹配 “a”、“b” 或 “c”[^]
[^abc]
匹配非 “a”、“b”、“c” 的字符()
(abc)+
匹配 “abc” 一次或多次2.2.量词
*
a*
匹配 “”, “a”, “aa”, …+
a+
匹配 “a”, “aa”, …?
a?
匹配 “”, “a”{n}
a{2}
匹配 “aa”{n,}
a{2,}
匹配 “aa”, “aaa”, …{n,m}
a{2,4}
匹配 “aa”, “aaa”, “aaaa”2.3元字符(特殊字符)
.
[^\\n\\r]
\\d
[0-9]
\\D
[^0-9]
\\w
[A-Za-z0-9_]
\\W
[^A-Za-z0-9_]
\\s
[\\t\\n\\v\\f\\r ]
\\S
[^\\t\\n\\v\\f\\r ]
\\b
\\B
^
$
2.3修饰符(标志)
i
/abc/i
匹配 “ABC”g
/a/g
在 “aaa” 中找到3个匹配m
/^a/gm
在多行中匹配每行开头的as
.
匹配换行符/a.b/s
匹配 “a\\nb”u
/\\u{1F600}/u
匹配😀y
/a/y
从指定位置匹配3.五个实用案例
案例1:邮箱验证
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/;console.log(emailRegex.test(\'user@example.com\')); // trueconsole.log(emailRegex.test(\'invalid.email@\')); // false
案例2:提取URL中的域名
const url = \'https://www.example.com/path?query=string\';const domainRegex = /^(https?:\\/\\/)?([^\\/\\?]+)/i;const match = url.match(domainRegex);console.log(match[2]); // www.example.com
案例3:密码强度验证
// 至少8字符,包含大小写字母和数字const passwordRegex = /^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{8,}$/;console.log(passwordRegex.test(\'StrongPass1\')); // trueconsole.log(passwordRegex.test(\'weak\')); // false
案例4:格式化电话号码
const phone = \'1234567890\';const formatted = phone.replace(/^(\\d{3})(\\d{3})(\\d{4})$/, \'($1) $2-$3\');console.log(formatted); // (123) 456-7890
案例5:移除HTML标签
const html = \'Hello World\';const cleanText = html.replace(/]*>/g, \'\');console.log(cleanText); // Hello World
4.高级技巧
1. 非捕获组
// 使用 (?:...) 表示不捕获的分组const dateRegex = /(\\d{4})-(?:\\d{2})-(\\d{2})/;const dateMatch = \'2023-05-15\'.match(dateRegex);console.log(dateMatch); // [\"2023-05-15\", \"2023\", \"15\"]
2. 回溯引用
// 匹配重复单词const repeatRegex = /\\b(\\w+)\\s+\\1\\b/;console.log(repeatRegex.test(\'hello hello\')); // trueconsole.log(repeatRegex.test(\'hello world\')); // false
3. 正向/负向预查
// 正向肯定预查 (?=...)const hasNumberRegex = /^(?=.*\\d).+$/;// 正向否定预查 (?!...)const noSpecialCharRegex = /^(?!.*[@#$%]).+$/;
5.常见问题解决
1. 贪婪匹配 vs 惰性匹配
const greedyRegex = //; // 匹配整个 ...const lazyRegex = //; // 只匹配单个标签
2. 多行匹配
const multiLineText = `Line 1Line 2Line 3`;// 不使用m修饰符console.log(/^Line/g.test(multiLineText)); // false// 使用m修饰符console.log(/^Line/gm.test(multiLineText)); // true
3. Unicode字符匹配
// 不使用u修饰符console.log(/^.$/.test(\'😀\')); // false// 使用u修饰符console.log(/^.$/u.test(\'😀\')); // true
正则表达式是JavaScript中非常强大的工具,掌握它可以极大提高字符串处理的效率和灵活性。建议从简单模式开始练习,逐步掌握更复杂的表达式。