当前位置: 首页 > news >正文

学习:JavaScript(6)

Math(数学)对象

在 JavaScript 中, Math 对象提供了数学常数和函数的属性和方法。以下是 Math 对象的完整指南,涵盖常数、函数和实际应用。

1. Math 对象的基本特性

(1) 静态对象
  • Math 不是构造函数,不能创建实例
  • 所有属性和方法都是静态的,直接通过 Math 调用
(2) 常用数学常数
属性值(近似)说明
Math.PI3.14159圆周率 π
Math.E2.71828自然对数的底数 e
Math.LN20.693152的自然对数
Math.LN102.3025910的自然对数
Math.LOG2E1.44270以2为底e的对数
Math.LOG10E0.43429以10为底e的对数
Math.SQRT21.414212的平方根
Math.SQRT1_20.707111/2的平方根

2. Math 对象的常用方法

(1) 基本数学运算
方法说明示例
Math.abs(x)绝对值Math.abs(-5) → 5
Math.ceil(x)向上取整Math.ceil(4.2) → 5
Math.floor(x)向下取整Math.floor(4.8) → 4
Math.round(x)四舍五入Math.round(4.5) → 5
Math.trunc(x)去除小数部分Math.trunc(4.9) → 4

(2) 幂和开方运算
方法说明示例
Math.pow(x, y)x的y次幂Math.pow(2, 3) → 8
Math.sqrt(x)平方根Math.sqrt(16) → 4
Math.cbrt(x)立方根Math.cbrt(27) → 3
Math.exp(x)e的x次幂Math.exp(1) → 2.718
Math.log(x)自然对数Math.log(Math.E) → 1
Math.log10(x)以10为底的对数Math.log10(100) → 2
Math.log2(x)以2为底的对数Math.log2(8) → 3

(3) 三角函数
方法说明示例
Math.sin(x)正弦(弧度)Math.sin(Math.PI/2) → 1
Math.cos(x)余弦(弧度)Math.cos(Math.PI) → -1
Math.tan(x)正切(弧度)Math.tan(Math.PI/4) → 1
Math.asin(x)反正弦Math.asin(1) → π/2
Math.acos(x)反余弦Math.acos(0) → π/2
Math.atan(x)反正切Math.atan(1) → π/4
Math.atan2(y, x)从x轴到点(x,y)的角度Math.atan2(1, 1) → π/4

(4) 最大值和最小值
方法说明示例
Math.max(...values)返回最大值Math.max(1, 3, 2) → 3
Math.min(...values)返回最小值Math.min(1, 3, 2) → 1

(5) 随机数生成
方法说明示例
Math.random()生成0-1之间的随机数Math.random() → 

3. 角度和弧度转换

// 角度转弧度
function degreesToRadians(degrees) {return degrees * Math.PI / 180;
}// 弧度转角度  
function radiansToDegrees(radians) {return radians * 180 / Math.PI;
}console.log(degreesToRadians(90)); // 1.5708 (π/2)
console.log(radiansToDegrees(Math.PI)); // 180

4. 实际应用示例

(1) 生成随机数范围
// 生成 min-max 之间的随机整数
function randomInt(min, max) {return Math.floor(Math.random() * (max - min + 1)) + min;
}// 生成 min-max 之间的随机浮点数
function randomFloat(min, max) {return Math.random() * (max - min) + min;
}console.log(randomInt(1, 10)); // 1-10的随机整数
console.log(randomFloat(1.5, 3.5)); // 1.5-3.5的随机浮点数

(2) 数字格式化
// 保留小数位数
function formatNumber(num, decimals = 2) {return Math.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals);
}console.log(formatNumber(3.14159, 2)); // 3.14
console.log(formatNumber(123.456, 1)); // 123.5

(3) 距离计算(勾股定理)
// 计算两点之间的距离
function distance(x1, y1, x2, y2) {const dx = x2 - x1;const dy = y2 - y1;return Math.sqrt(dx * dx + dy * dy);
}console.log(distance(0, 0, 3, 4)); // 5

(4) 圆周运动
// 角度转弧度
function degreesToRadians(degrees) {return (degrees * Math.PI) / 180;
}function circularMotion(centerX, centerY, radius, angle) {const rad = degreesToRadians(angle);return {x: centerX + radius * Math.cos(rad),y: centerY + radius * Math.sin(rad)};
}const point = circularMotion(100, 100, 50, 45);
console.log(point); // { x: 135.36, y: 135.36 }

(5) 数值范围限制
// 将数值限制在指定范围内
function clamp(value, min, max) {return Math.min(Math.max(value, min), max);
}console.log(clamp(15, 0, 10)); // 10
console.log(clamp(-5, 0, 10)); // 0
console.log(clamp(7, 0, 10)); // 7

(6) 百分比计算
// 计算百分比
function percentage(value, total) {return Math.round((value / total) * 100);
}// 从百分比还原数值
function fromPercentage(percent, total) {return Math.round((percent / 100) * total);
}console.log(percentage(75, 150)); // 50
console.log(fromPercentage(50, 150)); // 75

(7) 斐波那契数列
// 使用黄金比例公式计算斐波那契数
function fibonacci(n) {const phi = (1 + Math.sqrt(5)) / 2;return Math.round(Math.pow(phi, n) / Math.sqrt(5));
}console.log(fibonacci(10)); // 55

(8) 正态分布随机数
// 生成正态分布随机数(Box-Muller变换)
function normalRandom(mean = 0, stdDev = 1) {let u = 0, v = 0;while (u === 0) u = Math.random();while (v === 0) v = Math.random();const z = Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);return z * stdDev + mean;
}console.log(normalRandom(100, 15)); // 近似正态分布的随机数

(9) 颜色转换(RGB ↔ HSL)
// RGB 转 HSL
function rgbToHsl(r, g, b) {r /= 255; g /= 255; b /= 255;const max = Math.max(r, g, b);const min = Math.min(r, g, b);const delta = max - min;let h = 0, s = 0, l = (max + min) / 2;if (delta !== 0) {s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min);switch (max) {case r: h = (g - b) / delta + (g < b ? 6 : 0); break;case g: h = (b - r) / delta + 2; break;case b: h = (r - g) / delta + 4; break;}h /= 6;}return {h: Math.round(h * 360),s: Math.round(s * 100),l: Math.round(l * 100)};
}console.log(rgbToHsl(255, 0, 0)); // { h: 0, s: 100, l: 50 } (红色)

(10) 动画缓动函数
// 常用缓动函数
const easingFunctions = {// 线性linear: t => t,// 二次缓动easeInQuad: t => t * t,easeOutQuad: t => t * (2 - t),easeInOutQuad: t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,// 正弦缓动easeInSine: t => 1 - Math.cos(t * Math.PI / 2),easeOutSine: t => Math.sin(t * Math.PI / 2),easeInOutSine: t => -(Math.cos(Math.PI * t) - 1) / 2,// 指数缓动easeInExpo: t => Math.pow(2, 10 * (t - 1)),easeOutExpo: t => 1 - Math.pow(2, -10 * t)
};// 使用示例
function animate(element, property, start, end, duration, easing = 'linear') {const startTime = Date.now();function update() {const elapsed = Date.now() - startTime;const progress = Math.min(elapsed / duration, 1);const eased = easingFunctions[easing](progress);const current = start + (end - start) * eased;element.style[property] = current + 'px';if (progress < 1) {requestAnimationFrame(update);}}update();
}

5. 最佳实践

  1. 使用 ** 运算符替代 Math.pow()

    // 推荐(ES6+)
    const result = 2 ** 3; // 8// 传统方式
    const result = Math.pow(2, 3); // 8
    
  2. 处理浮点数精度问题

    // 浮点数精度问题
    console.log(0.1 + 0.2); // 0.30000000000000004// 解决方案
    function preciseAdd(a, b) {const multiplier = Math.pow(10, Math.max(a.toString().split('.')[1]?.length || 0,b.toString().split('.')[1]?.length || 0));return (a * multiplier + b * multiplier) / multiplier;
    }
    

  3. 使用常量提高性能

    // 缓存常用数学常数
    const PI = Math.PI;
    const HALF_PI = PI / 2;
    const TWO_PI = PI * 2;

RegExp(正则表达式)对象

在 JavaScript 中, RegExp 对象用于模式匹配和文本处理。以下是正则表达式的完整指南,涵盖创建、语法、方法和实际应用。

1. RegExp 对象的基本特性

(1) 两种创建方式
// 字面量形式(推荐)
const regex1 = /pattern/flags;// 构造函数形式
const regex2 = new RegExp("pattern", "flags");
(2) 常用标志(flags)
标志说明示例
g全局匹配/a/g
i忽略大小写/a/i
m多行匹配/^a/m
s点号匹配所有字符/a.b/s
uUnicode 模式/\u{1F600}/u
y粘性匹配/a/y

2. 正则表达式语法

(1) 基本元字符
元字符说明示例
.匹配任意单个字符(除换行符)/.at/ 匹配 "cat", "hat"
\d数字字符/\d/ 匹配 "0"-"9"
\D非数字字符/\D/ 匹配非数字
\w单词字符(字母、数字、下划线)/\w/ 匹配 "a-z", "A-Z", "0-9", "_"
\W非单词字符/\W/ 匹配非字母数字下划线
\s空白字符/\s/ 匹配空格、制表符、换行符
\S非空白字符/\S/ 匹配非空白字符
(2) 字符类
// 字符集合
/[abc]/      // 匹配 a, b 或 c
/[a-z]/      // 匹配 a 到 z 的任意字符
/[^abc]/     // 匹配除 a, b, c 外的任意字符
/[0-9]/      // 匹配数字
(3) 量词
量词说明示例
*0次或多次/a*/ 匹配 "", "a", "aa"
+1次或多次/a+/ 匹配 "a", "aa"
?0次或1次/a?/ 匹配 "", "a"
{n}恰好n次/a{3}/ 匹配 "aaa"
{n,}至少n次/a{2,}/ 匹配 "aa", "aaa"
{n,m}n到m次/a{2,4}/ 匹配 "aa", "aaa", "aaaa"
(4) 边界和位置
符号说明示例
^字符串开始/^a/ 匹配以a开头的字符串
$字符串结束/a$/ 匹配以a结尾的字符串
\b单词边界/\bword\b/ 匹配独立的"word"
\B非单词边界/\Bword\B/ 匹配非独立的"word"
(5) 分组和捕获
// 分组
/(ab)+/      // 匹配 "ab", "abab", "ababab"// 捕获组
/(\d{4})-(\d{2})-(\d{2})/  // 捕获年月日// 非捕获组
/(?:ab)+/    // 分组但不捕获// 命名捕获组
/(?<year>\d{4})-(?<month>\d{2})/  // 命名分组
(6) 选择符和断言
// 选择符
/cat|dog/    // 匹配 "cat" 或 "dog"// 正向先行断言
/\d+(?=元)/  // 匹配后面是"元"的数字// 负向先行断言
/\d+(?!元)/  // 匹配后面不是"元"的数字// 正向后行断言
/(?<=\$)\d+/ // 匹配前面是"$"的数字// 负向后行断言
/(?<!\$)\d+/ // 匹配前面不是"$"的数字

3. RegExp 对象的常用方法

(1) test() - 测试匹配
const regex = /hello/i;
console.log(regex.test("Hello World")); // true
console.log(regex.test("Hi World"));    // false

(2) exec() - 执行匹配
const regex = /(\w+)\s(\w+)/;
const result = regex.exec("Hello World");console.log(result[0]); // "Hello World" (完整匹配)
console.log(result[1]); // "Hello" (第一个捕获组)
console.log(result[2]); // "World" (第二个捕获组)
console.log(result.index); // 0 (匹配开始位置)

(3) 字符串方法结合正则
const str = "Hello World";// match() - 查找匹配
console.log(str.match(/o/g)); // ["o", "o"]// search() - 返回匹配位置
console.log(str.search(/World/)); // 6// replace() - 替换匹配内容
console.log(str.replace(/World/, "JavaScript")); // "Hello JavaScript"// split() - 分割字符串
console.log(str.split(/\s/)); // ["Hello", "World"]

4. 实际应用示例

(1) 邮箱验证
function validateEmail(email) {const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;return regex.test(email);
}console.log(validateEmail("test@example.com")); // true
console.log(validateEmail("invalid.email"));    // false

(2) 手机号验证
function validatePhone(phone) {const regex = /^1[3-9]\d{9}$/;return regex.test(phone);
}console.log(validatePhone("13812345678")); // true
console.log(validatePhone("12345678901")); // false

(3) 密码强度验证
function checkPasswordStrength(password) {const patterns = {length: /.{8,}/,upper: /[A-Z]/,lower: /[a-z]/,number: /\d/,special: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/};let score = 0;for (const pattern of Object.values(patterns)) {if (pattern.test(password)) score++;}return {score,strength: score < 3 ? "弱" : score < 5 ? "中" : "强"};
}console.log(checkPasswordStrength("Password123!")); // { score: 5, strength: "强" }

(4) URL 解析
function parseURL(url) {const regex = /^(https?):\/\/([^\/:]+)(?::(\d+))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/;const match = url.match(regex);if (!match) return null;return {protocol: match[1],hostname: match[2],port: match[3] || (match[1] === "https" ? "443" : "80"),pathname: match[4] || "/",search: match[5] ? new URLSearchParams(match[5]) : null,hash: match[6] || ""};
}console.log(parseURL("https://example.com:8080/path?query=value#hash"));

(5) HTML 标签提取
function extractTags(html, tagName) {const regex = new RegExp(`<${tagName}\\b[^>]*>(.*?)<\\/${tagName}>`, "gis");const matches = [];let match;while ((match = regex.exec(html)) !== null) {matches.push({fullTag: match[0],content: match[1],attributes: match[0].match(/\b(\w+)=["']([^"']*)["']/g) || []});}return matches;
}const html = '<div class="test">Hello</div><div id="main">World</div>';
console.log(extractTags(html, "div"));

(6) 日期格式转换
function formatDate(dateStr, fromFormat, toFormat) {const formatPatterns = {"YYYY-MM-DD": /^(\d{4})-(\d{2})-(\d{2})$/,"MM/DD/YYYY": /^(\d{2})\/(\d{2})\/(\d{4})$/,"DD.MM.YYYY": /^(\d{2})\.(\d{2})\.(\d{4})$/};const match = dateStr.match(formatPatterns[fromFormat]);if (!match) return dateStr;const [, y, m, d] = match;const formats = {"YYYY-MM-DD": `${y}-${m}-${d}`,"MM/DD/YYYY": `${m}/${d}/${y}`,"DD.MM.YYYY": `${d}.${m}.${y}`};return formats[toFormat];
}console.log(formatDate("2024-11-05", "YYYY-MM-DD", "MM/DD/YYYY")); // "11/05/2024"

(7) 敏感词过滤
function filterSensitiveWords(text, sensitiveWords) {const regex = new RegExp(sensitiveWords.join("|"), "gi");return text.replace(regex, match => "*".repeat(match.length));
}const text = "这是一个包含敏感词和违规内容的文本";
const sensitive = ["敏感词", "违规内容"];
console.log(filterSensitiveWords(text, sensitive)); // "这是一个包含****和****的文本"

(8) 代码高亮
function highlightCode(code, language = "javascript") {const patterns = {javascript: {keyword: /\b(function|var|let|const|if|else|for|while|return)\b/g,string: /(["'`])(?:(?=(\\?))\2.)*?\1/g,comment: /\/\/.*$|\/\*[\s\S]*?\*\//gm,number: /\b\d+(\.\d+)?\b/g}};const langPatterns = patterns[language];if (!langPatterns) return code;let highlighted = code;for (const [type, pattern] of Object.entries(langPatterns)) {highlighted = highlighted.replace(pattern, match => `<span class="${type}">${match}</span>`);}return highlighted;
}const code = `function test() {// 这是一个注释const message = "Hello World";return message.length;
}`;console.log(highlightCode(code));

(9) 数据提取和清洗
function extractData(text, pattern) {const regex = new RegExp(pattern, "g");const results = [];let match;while ((match = regex.exec(text)) !== null) {results.push(match.groups || match.slice(1));}return results;
}const logText = `
2024-11-05 10:30:25 [INFO] User login: alice
2024-11-05 10:31:15 [ERROR] Database connection failed
2024-11-05 10:32:00 [INFO] User logout: alice
`;const logPattern = /(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[(?<level>\w+)\] (?<message>.+)/;
console.log(extractData(logText, logPattern));

(10) 模板引擎
function simpleTemplate(template, data) {return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {return data[key] !== undefined ? data[key] : match;});
}const template = "Hello, {{name}}! You have {{count}} new messages.";
const data = { name: "Alice", count: 5 };
console.log(simpleTemplate(template, data)); // "Hello, Alice! You have 5 new messages."

5. 最佳实践

  1. 使用字面量创建简单的正则表达式

    // 推荐
    const regex = /pattern/gi;// 不推荐(除非需要动态构建)
    const regex = new RegExp("pattern", "gi");
    
  2. 缓存正则表达式对象

    // 推荐(避免重复编译)
    const emailRegex = /^[^@]+@[^@]+\.[^@]+$/;// 不推荐(每次都会编译)
    function validateEmail(email) {return /^[^@]+@[^@]+\.[^@]+$/.test(email);
    }
    
  3. 使用非贪婪匹配避免性能问题

    // 贪婪匹配(可能匹配过多内容)
    const greedy = /<.*>/;// 非贪婪匹配(推荐)
    const nonGreedy = /<.*?>/;
    
  4. 处理特殊字符转义

    function escapeRegex(str) {return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    }const search = "file.txt";
    const regex = new RegExp(escapeRegex(search), "gi");
    

6. 常见问题解决

(1) 多行匹配
const text = `Line 1
Line 2
Line 3`;// 匹配每行开头的 "Line"
const regex = /^Line/gm;
console.log(text.match(regex)); // ["Line", "Line", "Line"]
(2) Unicode 字符匹配
// 匹配中文字符
const chineseRegex = /[\u4e00-\u9fa5]/g;
console.log("Hello 世界".match(chineseRegex)); // ["世", "界"]// 匹配表情符号
const emojiRegex = /\p{Emoji}/gu;
console.log("Hello 😀 World 🌍".match(emojiRegex)); // ["😀", "🌍"]
(3) 性能优化
// 避免灾难性回溯
// 不好的模式(可能造成性能问题)
const badRegex = /(a+)+b/;// 好的模式
const goodRegex = /a+b/;

DOM(文档对象模型)

在 JavaScript 中,DOM(文档对象模型) 是 HTML 和 XML 文档的编程接口,它将文档表示为树形结构。以下是 DOM 的完整指南,涵盖节点操作、事件处理、遍历和实际应用。

1. DOM 的基本概念

(1) DOM 树结构
Document
└── html├── head│   ├── meta│   └── title└── body├── h1├── p└── div
(2) 节点类型
节点类型数值常量说明
ELEMENT_NODE1元素节点
TEXT_NODE3文本节点
COMMENT_NODE8注释节点
DOCUMENT_NODE9文档节点

2. DOM 选择器

(1) 基本选择方法
// 单个元素选择
document.getElementById("myId");
document.querySelector(".myClass");// 多个元素选择
document.getElementsByClassName("myClass");
document.getElementsByTagName("div");
document.querySelectorAll("p.highlight");
(2) 选择器示例
// ID 选择器
const header = document.querySelector("#header");// 类选择器
const items = document.querySelectorAll(".item");// 属性选择器
const links = document.querySelectorAll("a[target='_blank']");// 组合选择器
const firstPara = document.querySelector("div.content > p:first-child");

3. DOM 节点操作

(1) 创建和添加节点
// 创建元素
const newDiv = document.createElement("div");
const newText = document.createTextNode("Hello World");// 添加节点
parentElement.appendChild(newDiv);
parentElement.insertBefore(newDiv, referenceElement);
parentElement.replaceChild(newDiv, oldChild);
(2) 修改节点内容
const element = document.getElementById("myElement");// 修改 HTML 内容
element.innerHTML = "<strong>新内容</strong>";// 修改文本内容
element.textContent = "纯文本内容";// 修改属性
element.setAttribute("class", "new-class");
element.className = "another-class";
element.id = "new-id";
(3) 删除节点
// 删除子节点
parentElement.removeChild(childElement);// 直接删除(现代方法)
element.remove();// 清空所有子节点
element.innerHTML = "";
while (element.firstChild) {element.removeChild(element.firstChild);
}

4. DOM 属性和样式

(1) 属性操作
 <a href="https://blog.csdn.net/" target="_blank">示例链接</a><script>const link = document.querySelector("a");// 获取和设置属性link.getAttribute("href");link.setAttribute("href", "https://example.com");link.removeAttribute("target");// 检查属性link.hasAttribute("class");// data-* 属性link.dataset.id = "123";console.log(link.dataset.id); // "123"</script>

(2) 样式操作
const element = document.getElementById("myElement");// 直接修改样式
element.style.color = "red";
element.style.backgroundColor = "#f0f0f0";
element.style.fontSize = "16px";// 批量修改样式
Object.assign(element.style, {color: "blue",fontSize: "18px",margin: "10px"
});// 类名操作
element.classList.add("active");
element.classList.remove("inactive");
element.classList.toggle("hidden");
element.classList.contains("active");

5. DOM 遍历

(1) 父子关系遍历
const element = document.querySelector(".child");// 父节点
element.parentNode;
element.parentElement;// 子节点
element.childNodes;        // 所有子节点(包括文本节点)
element.children;          // 所有子元素节点
element.firstChild;
element.lastChild;
element.firstElementChild;
element.lastElementChild;
(2) 兄弟关系遍历
const element = document.querySelector(".middle");// 兄弟节点
element.previousSibling;
element.nextSibling;
element.previousElementSibling;
element.nextElementSibling;
(3) 遍历示例
<div id="container"><p>段落1</p><span>文本</span><p>段落2</p>
</div><script>// 获取一个父元素const element = document.querySelector("div");// 遍历所有子元素const children = Array.from(element.children);children.forEach((child) => {console.log(child.tagName);});// 查找特定祖先function findAncestor(element, selector) {while (element) {if (element.matches(selector)) {return element;}element = element.parentElement;}return null;}// 使用示例:查找某个元素的body祖先const someElement = document.querySelector("a");const bodyAncestor = findAncestor(someElement, "body");</script>

6. DOM 事件处理

(1) 事件监听
<button id="myButton">点击我</button>
const button = document.getElementById("myButton");// 添加事件监听器
button.addEventListener("click", function(event) {console.log("按钮被点击了", event);
});// 移除事件监听器
const handler = function() { console.log("点击"); };
button.addEventListener("click", handler);
button.removeEventListener("click", handler);

(2) 事件对象
// 获取一个元素(可以使用之前创建的按钮)
const element = document.getElementById("myButton");
element.addEventListener("click", function(event) {// 事件目标console.log(event.target);        // 实际点击的元素console.log(event.currentTarget); // 绑定事件的元素// 阻止默认行为event.preventDefault();// 停止事件传播event.stopPropagation();// 事件信息console.log(event.clientX, event.clientY); // 鼠标位置console.log(event.key);                    // 键盘事件键名
});

(3) 事件委托
<ul id="list"><li class="item">项目 1</li><li class="item">项目 2</li><li class="item">项目 3</li>
</ul>
// 在父元素上监听,处理动态添加的子元素
document.getElementById("list").addEventListener("click", function(event) {if (event.target.matches("li.item")) {console.log("点击了列表项:", event.target.textContent);}
});

(4) 常用事件类型
// 鼠标事件
element.addEventListener("click", handler);
element.addEventListener("dblclick", handler);
element.addEventListener("mouseenter", handler);
element.addEventListener("mouseleave", handler);
element.addEventListener("mousemove", handler);// 键盘事件
element.addEventListener("keydown", handler);
element.addEventListener("keyup", handler);
element.addEventListener("keypress", handler);// 表单事件
element.addEventListener("focus", handler);
element.addEventListener("blur", handler);
element.addEventListener("change", handler);
element.addEventListener("submit", handler);// 窗口事件
window.addEventListener("load", handler);
window.addEventListener("resize", handler);
window.addEventListener("scroll", handler);

7. DOM 操作最佳实践

(1) 性能优化
<ul id="list"></ul>
<div id="myElement">示例元素</div>
// 批量操作(使用 DocumentFragment)
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {const li = document.createElement("li");li.textContent = `项目 ${i}`;fragment.appendChild(li);
}
document.getElementById("list").appendChild(fragment);// 避免重排重绘
const element = document.getElementById("myElement");
element.style.display = "none"; // 隐藏元素
// 进行大量 DOM 操作
element.style.display = "block"; // 显示元素

(2) 内存管理
// 移除事件监听器
function createComponent() {const element = document.createElement("div");const handler = () => console.log("点击");element.addEventListener("click", handler);// 清理函数return () => {element.removeEventListener("click", handler);element.remove();};
}

8. 实际应用示例

(1) 动态列表管理
   <div id="myList"></div>
class ListManager {constructor(containerId) {this.container = document.getElementById(containerId);this.items = [];this.setupEvents();}setupEvents() {this.container.addEventListener("click", (event) => {if (event.target.matches(".delete-btn")) {this.deleteItem(event.target.closest(".item").dataset.id);}});this.container.addEventListener("input", (event) => {if (event.target.matches(".item-input")) {this.updateItem(event.target.closest(".item").dataset.id,event.target.value);}});}addItem(text) {const id = Date.now().toString();const item = {id,text,element: this.createItemElement(id, text)};this.items.push(item);this.container.appendChild(item.element);return id;}createItemElement(id, text) {const div = document.createElement("div");div.className = "item";div.dataset.id = id;div.innerHTML = `<input type="text" class="item-input" value="${text}"><button class="delete-btn">删除</button>`;return div;}deleteItem(id) {const index = this.items.findIndex(item => item.id === id);if (index !== -1) {this.items[index].element.remove();this.items.splice(index, 1);}}updateItem(id, text) {const item = this.items.find(item => item.id === id);if (item) {item.text = text;}}
}// 使用示例
const listManager = new ListManager("myList");
listManager.addItem("第一个项目");
listManager.addItem("第二个项目");

(2) 模态框组件
class Modal {constructor() {this.modal = null;this.isOpen = false;this.createModal();}createModal() {this.modal = document.createElement("div");this.modal.className = "modal";this.modal.innerHTML = `<div class="modal-content"><span class="close">&times;</span><div class="modal-body"></div></div>`;document.body.appendChild(this.modal);this.setupEvents();}setupEvents() {this.modal.querySelector(".close").addEventListener("click", () => {this.close();});this.modal.addEventListener("click", (event) => {if (event.target === this.modal) {this.close();}});document.addEventListener("keydown", (event) => {if (event.key === "Escape" && this.isOpen) {this.close();}});}open(content) {this.modal.querySelector(".modal-body").innerHTML = content;this.modal.style.display = "block";document.body.style.overflow = "hidden";this.isOpen = true;}close() {this.modal.style.display = "none";document.body.style.overflow = "";this.isOpen = false;}
}// 使用示例
const modal = new Modal();
modal.open("<h2>标题</h2><p>这是模态框内容</p>");

(3) 表单验证
class FormValidator {constructor(formId) {this.form = document.getElementById(formId);this.fields = this.form.querySelectorAll("[data-validate]");this.errors = new Map();this.setupValidation();}setupValidation() {this.fields.forEach(field => {field.addEventListener("blur", () => this.validateField(field));field.addEventListener("input", () => this.clearError(field));});this.form.addEventListener("submit", (event) => {if (!this.validateForm()) {event.preventDefault();}});}validateField(field) {const value = field.value.trim();const rules = field.dataset.validate.split(" ");for (const rule of rules) {const error = this.checkRule(rule, value, field);if (error) {this.showError(field, error);return false;}}this.clearError(field);return true;}checkRule(rule, value, field) {switch (rule) {case "required":return value ? null : "此字段为必填项";case "email":return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? null : "请输入有效的邮箱地址";case "minlength":const min = parseInt(field.dataset.minlength);return value.length >= min ? null : `至少需要 ${min} 个字符`;case "match":const matchField = document.getElementById(field.dataset.match);return value === matchField.value ? null : "密码不匹配";default:return null;}}showError(field, message) {this.clearError(field);const errorElement = document.createElement("div");errorElement.className = "error-message";errorElement.textContent = message;errorElement.style.color = "red";errorElement.style.fontSize = "12px";field.parentNode.appendChild(errorElement);field.style.borderColor = "red";this.errors.set(field, errorElement);}clearError(field) {const errorElement = this.errors.get(field);if (errorElement) {errorElement.remove();field.style.borderColor = "";this.errors.delete(field);}}validateForm() {let isValid = true;this.fields.forEach(field => {if (!this.validateField(field)) {isValid = false;}});return isValid;}
}// 使用示例
const validator = new FormValidator("myForm");

(4) 无限滚动
class InfiniteScroll {constructor(containerId, loadMoreCallback) {this.container = document.getElementById(containerId);this.loadMoreCallback = loadMoreCallback;this.isLoading = false;this.hasMore = true;this.setupScrollListener();this.loadInitialData();}setupScrollListener() {window.addEventListener("scroll", () => {if (this.shouldLoadMore() && !this.isLoading && this.hasMore) {this.loadMore();}});}shouldLoadMore() {const { scrollTop, scrollHeight, clientHeight } = document.documentElement;return scrollTop + clientHeight >= scrollHeight - 100; // 距离底部100px时加载}async loadMore() {this.isLoading = true;this.showLoadingIndicator();try {const newItems = await this.loadMoreCallback();if (newItems.length === 0) {this.hasMore = false;this.showNoMoreData();} else {this.appendItems(newItems);}} catch (error) {this.showError("加载失败");} finally {this.isLoading = false;this.hideLoadingIndicator();}}appendItems(items) {const fragment = document.createDocumentFragment();items.forEach(item => {const element = document.createElement("div");element.className = "item";element.textContent = item;fragment.appendChild(element);});this.container.appendChild(fragment);}showLoadingIndicator() {let indicator = this.container.querySelector(".loading-indicator");if (!indicator) {indicator = document.createElement("div");indicator.className = "loading-indicator";indicator.textContent = "加载中...";this.container.appendChild(indicator);}}hideLoadingIndicator() {const indicator = this.container.querySelector(".loading-indicator");if (indicator) {indicator.remove();}}showNoMoreData() {const message = document.createElement("div");message.className = "no-more-data";message.textContent = "没有更多数据了";this.container.appendChild(message);}showError(message) {const errorElement = document.createElement("div");errorElement.className = "error-message";errorElement.textContent = message;this.container.appendChild(errorElement);}loadInitialData() {this.loadMore();}
}// 使用示例
const infiniteScroll = new InfiniteScroll("content", async () => {// 模拟异步数据加载return new Promise(resolve => {setTimeout(() => {resolve(["新项目 " + Date.now()]);}, 1000);});
});

(5) 拖拽功能
   <div class="draggable">可拖拽元素1</div><div class="draggable">可拖拽元素2</div>
class Draggable {constructor(element) {this.element = element;this.isDragging = false;this.offset = { x: 0, y: 0 };this.makeDraggable();}makeDraggable() {this.element.style.position = "absolute";this.element.style.cursor = "move";this.element.addEventListener("mousedown", this.onMouseDown.bind(this));document.addEventListener("mousemove", this.onMouseMove.bind(this));document.addEventListener("mouseup", this.onMouseUp.bind(this));}onMouseDown(event) {this.isDragging = true;const rect = this.element.getBoundingClientRect();this.offset.x = event.clientX - rect.left;this.offset.y = event.clientY - rect.top;this.element.style.zIndex = "1000";event.preventDefault();}onMouseMove(event) {if (!this.isDragging) return;const x = event.clientX - this.offset.x;const y = event.clientY - this.offset.y;this.element.style.left = x + "px";this.element.style.top = y + "px";}onMouseUp() {this.isDragging = false;this.element.style.zIndex = "";}
}// 使用示例
const draggableElements = document.querySelectorAll(".draggable");
draggableElements.forEach(element => new Draggable(element));

9. 现代 DOM API

(1) MutationObserver
// 监听 DOM 变化
const observer = new MutationObserver((mutations) => {mutations.forEach(mutation => {if (mutation.type === 'childList') {console.log('子节点发生变化');}});
});observer.observe(document.getElementById('target'), {childList: true,attributes: true,subtree: true
});

(2) IntersectionObserver
// 监听元素进入视口
const io = new IntersectionObserver((entries) => {entries.forEach(entry => {if (entry.isIntersecting) {entry.target.classList.add('visible');}});
});document.querySelectorAll('.lazy-load').forEach(el => io.observe(el));

10. 兼容性和最佳实践

(1) 特征检测
// 检查浏览器支持
if ('querySelector' in document) {// 使用现代选择器
}if ('classList' in document.createElement('div')) {// 使用 classList API
}
(2) 性能监控
// 测量 DOM 操作性能
function measureDOMOperation(callback) {const start = performance.now();callback();const end = performance.now();console.log(`操作耗时: ${end - start}ms`);
}

http://www.dtcms.com/a/574621.html

相关文章:

  • 5a景区网站建设网页制作培训学费
  • 电子商务网站设计步骤2019网页游戏排行榜
  • jsp网站入门html企业网站主页模板
  • k8s:pod-1
  • 蓝牙钥匙 第45次 密码学基础在蓝牙钥匙中的应用:构建数字车锁的安全基石
  • Java练习——常用API1
  • hyip网站开发推荐个做淘宝主图视频的网站
  • 企业网站建设所需要的资料wordpress有什么数据库引擎
  • 上海云盾除了WAF,CDN还提供哪些细粒度的访问控制功能?
  • 高级机器学习作业(二)度量学习 + 稀疏学习 + GMM-EM半监督学习
  • Retimer vs Redriver:高速信号传输的“修复师”与“整形师”
  • 基于电鱼 RK3588 AI 工控机的智慧工地视频智能分析方案——减少布线复杂度与网络延迟,实现高效边缘智能
  • layout常用操作,DFF触发器版图为例
  • 海报设计网站官网网站建设服务条款
  • 网站建设是什么语言wordpress站关注别人
  • 创建网站怎么创怎样用网站做app
  • 制作购物网站教程南京设计公司有哪些公司
  • cmd控制台出现 系统找不到指定的路径。
  • 婚恋网站建设教程网站源码还可以做授权么
  • 【App开发】Mumu模拟器安装使用与Android Studio连接指南
  • 宝安中心地铁站是几号线通辽网站制作
  • 广东网站备案多长时间自助建站代理
  • 从零开始搭建 flask 博客实验(3)
  • 使用 Python 解释 Telegram 被封禁的原因(附中文版与中文群组频道搜索机器人示例)
  • Rust 练习册 3:深入理解闭包(Closure)
  • 官方网站制作wordpress 镜像
  • C语言应用实例:解方程(二分查找)
  • t想学网站建设石家庄专业建站公司
  • 基础数据结构之数组的双指针技巧之对撞指针(两端向中间):三数之和(LeetCode 15 中等题)
  • 网站鼠标悬停动态效果代码网站一个月