1.深浅拷贝(in the works)
2.异常处理:try-catch-finally
try {
// 可能抛出异常的代码
const result = riskyOperation();
console.log(result);
} catch (error) {
// 捕获异常并处理
console.error('Error caught:', error.message);
} finally {
// 无论是否抛出异常都会执行
console.log('Cleanup completed');
}
3.普通函数的 this 绑定
非严格模式下,普通函数未指定调用者时 this 指向全局对象(浏览器中为 window):
function showThis() {
console.log(this); // window (非严格模式)
}
showThis();
严格模式下为 undefined:
'use strict';
function showThis() {
console.log(this); // undefined
}
showThis();
4.箭头函数的 this 指向
箭头函数继承外层作用域的 this:
const obj = {
value: 'test',
getValue: () => {
console.log(this); // 继承外层this(此处为window或undefined)
}
};
obj.getValue();
5.改变 this 指向的方法
call 和 apply
立即调用函数并指定 this 和参数。
function greet(message) {
console.log(`${message}, ${this.name}`);
}
const person = { name: 'Alice' };
// call:参数逐个传递
greet.call(person, 'Hello'); // Hello, Alice
// apply:参数以数组传递
greet.apply(person, ['Hi']); // Hi, Alice
bind
返回一个绑定 this 的新函数,不立即执行。
const boundGreet = greet.bind(person, 'Welcome');
boundGreet(); // Welcome, Alice
6.防抖和节流(in the works)
7.DOM-获取元素(获取元素、修改属性)
DOM 文档对象模型概述
DOM(Document Object Model)是一种跨平台的编程接口,用于表示和操作HTML、XML等结构化文档。它将文档解析为由节点和对象组成的树状结构。
DOM 树结构
DOM 将文档视为节点树,每个节点代表文档的一部分(如元素、属性、文本)。主要节点类型包括:
- 文档节点:整个文档的根节点(document)。
- 元素节点:HTML标签(如 <div>、<p>)。
- 属性节点:元素的属性(如 class、id)。
- 文本节点:元素内的文本内容。
示例树结构:
<html>
<head>
<title>示例</title>
</head>
<body>
<div class="container">文本内容</div>
</body>
</html>
querySelector() 和 querySelectorAll()
querySelector() 方法返回文档中匹配指定 CSS 选择器的第一个元素。如果没有找到匹配的元素,则返回 null。
querySelectorAll() 方法返回文档中匹配指定 CSS 选择器的所有元素,返回的是一个 NodeList 集合。如果没有找到匹配的元素,返回空的 NodeList。
// 获取第一个匹配的元素
const firstElement = document.querySelector('.className');
// 获取所有匹配的元素
const allElements = document.querySelectorAll('.className');
其他获取 DOM 元素的方法
getElementById() 通过元素的 id 属性获取单个元素。id 在文档中应该是唯一的。
const elementById = document.getElementById('elementId');
getElementsByClassName() 通过元素的 class 属性获取所有匹配的元素,返回的是一个 HTMLCollection。
const elementsByClass = document.getElementsByClassName('className');
getElementsByTagName() 通过元素的标签名获取所有匹配的元素,返回的是一个 HTMLCollection。
const elementsByTag = document.getElementsByTagName('div');
修改属性
innerText 与 innerHTML 的区别
- innerText:获取或设置元素的文本内容,自动忽略 HTML 标签,仅显示纯文本。
- innerHTML:获取或设置元素的 HTML 内容,包含标签和文本,可直接插入 HTML 结构。
// 示例
element.innerText = "纯文本内容";
element.innerHTML = "<strong>加粗文本</strong>";
通过 style 属性操作 CSS
直接修改元素的 style 属性,仅影响行内样式:
element.style.color = "red";
element.style.fontSize = "16px";
// 注意:属性名需转换为驼峰写法(如 fontSize)
操作类名控制 CSS
通过修改 className 或 classList 切换预定义的 CSS 类:
- className:直接替换整个类名字符串。
element.className = "new-class";
- classList:提供更灵活的类操作方法(推荐):
element.classList.add("active");
element.classList.remove("inactive");
element.classList.toggle("hidden");
操作表单元素属性
表单元素(如 input、select)可通过标准属性直接访问:
const input = document.querySelector("input");
input.value = "新值";
input.disabled = true;
// 特殊属性如 checked、selected
checkbox.checked = true;
自定义属性操作
- HTML5 标准:使用 data-* 属性,通过 dataset 访问:
<div data-id="123" data-user-name="John"></div>
const div = document.querySelector("div");
console.log(div.dataset.id); // "123"
console.log(div.dataset.userName); // "John" - 非标准属性:通过 getAttribute/setAttribute 操作:
element.setAttribute("custom-attr", "value");
const value = element.getAttribute("custom-attr");
8.DOM-事件基础(注册事件、tab栏切换)
事件监听基础概念
事件监听指通过JavaScript在DOM元素上绑定特定事件类型(如点击、键盘输入等),当事件触发时执行预设的回调函数。核心方法为addEventListener(eventType, callback),支持多种事件类型以满足交互需求。
常见事件类型及用途
click
用户点击元素时触发(鼠标左键或键盘回车)。适用于按钮、链接等交互控件。
button.addEventListener('click', () => console.log('Clicked!'));
mouseenter / mouseleave
鼠标指针进入或离开元素时触发。常用于悬停效果(如显示提示信息)。
element.addEventListener('mouseenter', () => element.style.backgroundColor = 'yellow');
element.addEventListener('mouseleave', () => element.style.backgroundColor = '');
focus / blur
元素获得或失去焦点时触发(如表单输入框)。适用于输入验证或UI反馈。
input.addEventListener('focus', () => input.placeholder = '输入用户名');
input.addEventListener('blur', () => input.placeholder = '');
keydown / keyup
键盘按键按下或释放时触发。用于实时响应键盘操作(如快捷键、输入限制)。
document.addEventListener('keydown', (e) => {
if (e.key === 'Enter') console.log('Enter pressed');
});
input
表单元素值变化时实时触发(如<input>、<textarea>)。适合即时搜索或字符计数。
searchInput.addEventListener('input', (e) => {
console.log(`当前输入: ${e.target.value}`);
});
注意事项
- 事件冒泡:默认情况下事件会向上冒泡,可通过e.stopPropagation()阻止。
- 事件委托:利用冒泡机制在父元素监听子元素事件,优化性能。
- 移除监听:使用removeEventListener时需传入与绑定相同的回调函数引用。
事件对象
事件对象的概念
事件对象是编程中用于描述事件信息的结构化数据。它包含事件的类型、触发元素、时间戳等属性,以及阻止默认行为、停止冒泡等方法。
事件对象的常见属性
- type:事件类型(如 "click"、"keydown")。
- target:触发事件的DOM元素。获取此元素的标签名 target.tagName 返回值为大写字符串。
- currentTarget:当前处理事件的元素(可能与 target 不同,例如事件冒泡时)。
- key:键盘事件的键名(如 "Enter")。
事件对象的核心方法
- preventDefault():阻止事件的默认行为(如阻止表单提交)。
- stopPropagation():停止事件冒泡或捕获的进一步传播。
9.DOM-事件进阶(事件对象、事件委托)
事件流和两个阶段说明
事件流描述事件在DOM中的传播过程,分为捕获阶段和冒泡阶段:
- 捕获阶段:事件从根节点向下传播到目标元素。
- 冒泡阶段:事件从目标元素向上冒泡到根节点。
document.addEventListener('click', function(e) {
console.log('捕获阶段', e.eventPhase); // 1: 捕获阶段
}, true);
document.addEventListener('click', function(e) {
console.log('冒泡阶段', e.eventPhase); // 3: 冒泡阶段
}, false);
事件委托
通过将事件监听器绑定到父元素,利用事件冒泡处理子元素的事件,适合动态添加元素的场景。
document.getElementById('parent').addEventListener('click', function(e) {
if (e.target.tagName === 'BUTTON') {
console.log('按钮被点击:', e.target.textContent);
}
});
案例:动态列表项点击
<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
</ul>
<script>
document.getElementById('list').addEventListener('click', function(e) {
if (e.target.tagName === 'LI') {
alert('点击了: ' + e.target.textContent);
}
});
</script>
页面加载事件
- DOMContentLoaded:DOM树构建完成时触发。
- load:页面所有资源(如图片)加载完成后触发。
document.addEventListener('DOMContentLoaded', function() {
console.log('DOM已加载');
});
window.addEventListener('load', function() {
console.log('页面完全加载');
});
页面滚动事件
监听滚动事件并获取滚动位置:
window.addEventListener('scroll', function() {
console.log('当前滚动位置:', window.pageYOffset);
});
案例:滚动到一定位置显示按钮
const backToTop = document.getElementById('backToTop');
window.addEventListener('scroll', function() {
backToTop.style.display = window.pageYOffset > 500 ? 'block' : 'none';
});
页面尺寸属性
常用属性:
- window.innerWidth/innerHeight:视口尺寸。
- document.documentElement.clientWidth/clientHeight:可视区域尺寸。
- document.documentElement.scrollWidth/scrollHeight:整个文档尺寸。
console.log('视口宽度:', window.innerWidth);
console.log('文档高度:', document.documentElement.scrollHeight);
案例:响应式布局调整
window.addEventListener('resize', function() {
if (window.innerWidth < 768) {
document.body.style.backgroundColor = 'lightblue';
} else {
document.body.style.backgroundColor = 'white';
}
});
scrollLeft 和 scrollTop
scrollLeft 和 scrollTop 是用于设置获取或元素内容区域在水平和垂直方向上被卷去的距离(以像素为单位)。
- scrollLeft:表示元素内容水平滚动的距离。如果内容未滚动,值为 0;如果向右滚动,值增加。
- scrollTop:表示元素内容垂直滚动的距离。如果内容未滚动,值为 0;如果向下滚动,值增加。
示例:
// 获取滚动距离
const leftScroll = element.scrollLeft;
const topScroll = element.scrollTop;
// 设置滚动距离
element.scrollLeft = 100;
element.scrollTop = 200;
clientWidth 和 clientHeight
clientWidth 和 clientHeight 表示元素的可见内容区域大小,包括 padding,但不包括滚动条、边框(border)和外边距(margin)。
- clientWidth = 内容宽度 + 左右 padding
- clientHeight = 内容高度 + 上下 padding
示例:
const width = element.clientWidth; // 包含 padding 的宽度
const height = element.clientHeight; // 包含 padding 的高度
offsetWidth 和 offsetHeight
offsetWidth 和 offsetHeight 表示元素的整体布局尺寸,包括 padding、border 和滚动条(如果有),但不包括 margin。
- offsetWidth = 内容宽度 + 左右 padding + 左右 border
- offsetHeight = 内容高度 + 上下 padding + 上下 border
示例:
const totalWidth = element.offsetWidth; // 包含 padding 和 border 的宽度
const totalHeight = element.offsetHeight; // 包含 padding 和 border 的高度
offsetTop 和 offsetLeft
offsetTop 和 offsetLeft 表示元素相对于其最近定位祖先(position 不为 static)的垂直和水平偏移距离(以像素为单位)。
- offsetTop:元素上边缘相对于定位父元素上边缘的距离。
- offsetLeft:元素左边缘相对于定位父元素左边缘的距离。
示例:
const topOffset = element.offsetTop; // 相对于定位父元素的垂直距离
const leftOffset = element.offsetLeft; // 相对于定位父元素的水平距离
总结对比
| scrollLeft / scrollTop | 滚动距离 | – | – | – |
| clientWidth / clientHeight | 内容 + padding | 否 | 否 | 否 |
| offsetWidth / offsetHeight | 内容 + padding + border | 是(若存在) | 是 | 否 |
| offsetTop / offsetLeft | 相对于定位父元素的偏移 | – | – | – |
日期对象
日期对象实例化
在JavaScript中,Date对象用于处理日期和时间。可以通过多种方式实例化一个Date对象:
// 当前日期和时间
const now = new Date();
// 指定日期和时间(年月日时分秒)
const specificDate = new Date(2023, 11, 31, 23, 59, 59);
// 通过时间戳(毫秒)
const timestampDate = new Date(1672473599000);
// 通过日期字符串
const stringDate = new Date('2023-12-31T23:59:59');
常用时间方法
Date对象提供了一系列方法用于获取或设置日期和时间的各个部分:
const date = new Date();
// 获取年份
const year = date.getFullYear();
// 获取月份(0-11)
const month = date.getMonth();
// 获取日期(1-31)
const day = date.getDate();
// 获取小时(0-23)
const hours = date.getHours();
// 获取分钟(0-59)
const minutes = date.getMinutes();
// 获取秒(0-59)
const seconds = date.getSeconds();
// 获取毫秒(0-999)
const milliseconds = date.getMilliseconds();
// 获取星期(0-6,0表示星期日)
const weekday = date.getDay();
时间戳操作
时间戳表示从1970年1月1日(UTC)到指定时间的毫秒数:
// 获取当前时间戳
const timestamp = Date.now();
// 从Date对象获取时间戳
const date = new Date();
const timestampFromDate = date.getTime();
+new Date() 转换为时间戳
// 时间戳转换为日期
const timestamp = 1672473599000;
const dateFromTimestamp = new Date(timestamp);
日期格式化
将日期格式化为字符串:
const date = new Date();
// 本地日期字符串
const localDateString = date.toLocaleDateString();
// 本地时间字符串
const localTimeString = date.toLocaleTimeString();
// 自定义格式化
function formatDate(date) {
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
}
10.DOM-节点操作(节点的增删改查)
查找节点
parentNode
parentNode 是 DOM 中的一个属性,用于获取当前节点的父节点。它返回一个表示父节点的对象,如果没有父节点则返回 null。例如:
const childElement = document.getElementById('child');
const parentElement = childElement.parentNode;
children
children 是 DOM 元素的一个属性,返回一个包含所有子元素的 HTMLCollection(仅包含元素节点,不包括文本节点或注释节点)伪数组。例如:
const parentElement = document.getElementById('parent');
const childElements = parentElement.children;
nextElementSibling
nextElementSibling 返回当前元素的下一个兄弟元素节点(忽略文本节点和注释节点)。如果不存在下一个兄弟元素,则返回 null。例如:
const currentElement = document.getElementById('current');
const nextElement = currentElement.nextElementSibling;
previousElementSibling
previousElementSibling 返回当前元素的前一个兄弟元素节点(忽略文本节点和注释节点)。如果不存在前一个兄弟元素,则返回 null。例如:
const currentElement = document.getElementById('current');
const previousElement = currentElement.previousElementSibling;
示例代码
以下是一个综合示例,展示如何使用这些属性:
<div id="parent">
<div id="child1">Child 1</div>
<div id="child2">Child 2</div>
<div id="child3">Child 3</div>
</div>
const child2 = document.getElementById('child2');
// 获取父节点
const parent = child2.parentNode; // 返回 id="parent" 的 div
// 获取所有子元素
const children = parent.children; // 返回包含 child1, child2, child3 的 HTMLCollection
// 获取下一个兄弟元素
const nextSibling = child2.nextElementSibling; // 返回 id="child3" 的 div
// 获取前一个兄弟元素
const previousSibling = child2.previousElementSibling; // 返回 id="child1" 的 div
注意事项
- parentNode 可以返回任何类型的父节点(包括元素节点、文本节点等),而 parentElement 仅返回元素类型的父节点。
- children 仅包含元素节点,而 childNodes 包含所有类型的子节点(包括文本节点和注释节点)。
- nextElementSibling 和 previousElementSibling 仅返回元素节点,而 nextSibling 和 previousSibling 可能返回文本节点或注释节点。
创建节点
可以使用document.createElement()方法创建新的DOM节点。该方法接受一个参数,即要创建的元素的标签名。
const newNode = document.createElement('div');
增加节点
要将新创建的节点添加到DOM中,可以使用以下几种方法:
- appendChild():将节点添加为父节点的最后一个子节点
- prepend():将节点添加为父节点的第一个子节点
使用 cloneNode 方法克隆 DOM 节点
cloneNode 是 JavaScript 中用于复制 DOM 节点的方法。它创建一个与原始节点相同的新节点,可以选择是否深度克隆子节点。
语法:
const newNode = originalNode.cloneNode(deep);
参数说明:
- deep:布尔值,可选参数
- true:深度克隆,复制节点及其所有子节点
- false:浅克隆,仅复制节点本身,不包含子节点
浅克隆示例
浅克隆仅复制节点本身,不包含子节点内容:
const originalElement = document.getElementById('original');
const clonedElement = originalElement.cloneNode(false);
document.body.appendChild(clonedElement);
深度克隆示例
深度克隆会复制节点及其所有子节点:
const originalElement = document.getElementById('original');
const clonedElement = originalElement.cloneNode(true);
document.body.appendChild(clonedElement);
const form = document.getElementById('myForm');
const input = form.querySelector('input');
const newInput = input.cloneNode(false);
newInput.value = '';
form.appendChild(newInput);
删除指定节点
removeChild 是 DOM(文档对象模型)操作中用于删除指定子节点的方法。该方法属于 Node 接口,所有 DOM 节点均可调用。
语法与参数
parentNode.removeChild(childNode);
- parentNode:需要删除子节点的父节点。
- childNode:需要被删除的子节点。
使用示例
// 获取父节点和子节点
const parent = document.getElementById("parent");
const child = document.getElementById("child");
// 删除子节点
parent.removeChild(child);
11.DOM-操作浏览器(BOM、插件、本地存储)(in the works)
BOM(浏览器对象模型)
定时器–延时函数
setTimeout 的基本用法
setTimeout 是用于延迟执行代码的函数。它接受一个回调函数和一个以毫秒为单位的延迟时间作为参数。回调函数会在指定的延迟时间后执行。
语法:
setTimeout(callback, delay, arg1, arg2, …)
- callback:延迟结束后执行的函数。
- delay:延迟时间(毫秒),默认为 0。
- arg1, arg2, …:可选参数,传递给回调函数的额外参数。
示例:
setTimeout(() => {
console.log('This message will appear after 2 seconds');
}, 2000);
清除 setTimeout
setTimeout 返回一个唯一的计时器 ID,可以通过 clearTimeout 取消尚未执行的延迟操作。
示例:
const timerId = setTimeout(() => {
console.log('This will not run');
}, 1000);
clearTimeout(timerId);
js执行机制
JavaScript 执行机制
JavaScript 是单线程语言,意味着同一时间只能执行一个任务。为了避免阻塞,JavaScript 通过事件循环(Event Loop)机制实现异步操作。
单线程特性
JavaScript 的单线程设计意味着所有任务需要排队执行。如果一个任务耗时过长,后续任务会被阻塞。为了解决这个问题,JavaScript 引入了异步回调机制,将耗时操作(如 I/O、网络请求)交给其他线程处理,主线程继续执行后续任务。
事件循环机制
事件循环是 JavaScript 实现异步的核心机制,由以下几个部分组成:
- 调用栈(Call Stack):存储正在执行的函数调用,遵循后进先出(LIFO)原则。
- 任务队列(Task Queue):存放异步任务的回调函数,分为宏任务(macro task)和微任务(micro task)。
- 事件循环(Event Loop):持续检查调用栈是否为空,若为空则从任务队列中取出任务执行。
宏任务与微任务
- 宏任务:包括 setTimeout、setInterval、I/O 操作、UI 渲染等。
- 微任务:包括 Promise.then、MutationObserver、process.nextTick(Node.js)。
事件循环的优先级规则:
代码示例
console.log("Start");
setTimeout(() => {
console.log("Timeout");
}, 0);
Promise.resolve().then(() => {
console.log("Promise");
});
console.log("End");
输出顺序:
Start
End
Promise
Timeout
关键点总结
- 同步任务优先执行,异步任务进入队列。
- 微任务优先级高于宏任务。
- 事件循环持续运行,确保非阻塞执行。
这种机制使得 JavaScript 在单线程环境下高效处理并发任务。
location对象
location.href 跳转地址
location.href 是 window.location 对象的属性,用于获取或设置当前页面的完整 URL。通过修改 location.href 可以跳转到新的页面。
// 跳转到指定 URL
location.href = 'https://example.com';
// 获取当前页面 URL
console.log(location.href); // 输出当前页面的完整地址
location.search 获取查询参数
location.search 返回 URL 中 ? 及其后面的查询字符串部分,通常用于解析 GET 请求参数。
// 假设当前 URL 是 https://example.com?name=test&id=123
console.log(location.search); // 输出 "?name=test&id=123"
// 解析查询参数
const params = new URLSearchParams(location.search);
console.log(params.get('name')); // 输出 "test"
console.log(params.get('id')); // 输出 "123"
location.hash 获取锚点部分
location.hash 返回 URL 中 # 及其后面的部分,常用于单页面应用(SPA)的路由或页面内跳转。
// 假设当前 URL 是 https://example.com/#section1
console.log(location.hash); // 输出 "#section1"
// 修改 hash 触发页面滚动或路由变化
location.hash = '#section2';
reload 方法刷新页面
location.reload() 用于重新加载当前页面,可接受一个布尔参数:
- true:强制从服务器重新加载(跳过缓存)。
- false(默认):可能从缓存加载。
// 普通刷新(可能使用缓存)
location.reload();
// 强制从服务器重新加载
location.reload(true);
navigator对象(in the works)
histroy对象(in the works)
本地存储
本地存储包括 localStorage 和 sessionStorage,用于在浏览器端持久化或会话级存储数据。
localStorage(持久化存储)
// 存储数据
localStorage.setItem('key', 'value');
// 读取数据
const value = localStorage.getItem('key');
// 删除数据
localStorage.removeItem('key');
// 清空所有数据
localStorage.clear();
sessionStorage(会话级存储)
// 存储数据(标签页关闭后失效)
sessionStorage.setItem('sessionKey', 'sessionValue');
// 读取数据
const sessionValue = sessionStorage.getItem('sessionKey');
12.正则表达式(in the works)
test 方法
test 方法用于检测字符串中是否存在匹配正则表达式的部分,返回布尔值(true 或 false)。
语法:
regexObj.test(str)
示例:
const regex = /hello/;
console.log(regex.test("hello world")); // true
console.log(regex.test("hi there")); // false
exec 方法
exec 方法用于在字符串中执行正则表达式搜索,返回一个数组(包含匹配信息)或 null(无匹配时)。
语法:
regexObj.exec(str)
返回的数组包含以下属性:
- [0]:匹配的完整字符串。
- [1] 到 [n]:捕获组匹配的内容。
- index:匹配的起始位置。
- input:原始字符串。
示例:
const regex = /hello (\\w+)/;
const result = regex.exec("hello world");
console.log(result[0]); // "hello world"
console.log(result[1]); // "world"
console.log(result.index); // 0
console.log(result.input); // "hello world"
主要区别
- test 返回布尔值,仅检查是否存在匹配。
- exec 返回详细匹配信息,适用于需要提取匹配内容的情况。
- 全局正则表达式(/g)下,exec 可以多次调用以遍历所有匹配,而 test 仅检查下一个匹配是否存在。
元字符的定义
元字符(Metacharacter)是正则表达式中具有特殊含义的字符,用于匹配或控制文本模式。
常见元字符及其功能
基本元字符
- .:匹配除换行符外的任意单个字符。
- ^:匹配字符串的开头(或在多行模式下匹配行首)。
- $:匹配字符串的结尾(或在多行模式下匹配行尾)。
- *:匹配前一个字符或子表达式零次或多次。
- +:匹配前一个字符或子表达式一次或多次。
- ?:匹配前一个字符或子表达式零次或一次(或表示非贪婪匹配)。
- |:逻辑“或”,匹配左右任意一个表达式。
字符类元字符
- []:定义字符集合,匹配其中任意一个字符。例如 [aeiou] 匹配任意元音字母。
- [^]:否定字符集合,匹配不在括号内的字符。例如 [^0-9] 匹配非数字字符。
- -:在字符类中表示范围,如 [a-z] 匹配小写字母。
转义元字符
- \\:将特殊字符转义为字面意义,或赋予普通字符特殊功能。例如 \\. 匹配句点,\\d 匹配数字。
预定义字符类
- \\d:匹配数字(等价于 [0-9])。
- \\D:匹配非数字(等价于 [^0-9])。
- \\w:匹配单词字符(字母、数字、下划线)。
- \\W:匹配非单词字符。
- \\s:匹配空白字符(空格、制表符等)。
- \\S:匹配非空白字符。




