JavaScript
ECMAScript
ECMAScript(简称 ES)是 JavaScript 的核心标准,由 ECMA 国际组织 维护和制定(官方组织是 TC39)。
JavaScript 是基于 ECMAScript 规范的编程语言,所有现代 JavaScript 解释器(如 V8 引擎)都遵循 ECMAScript 规范。
ES 的版本代表 JavaScript 语法的演进,例如:
ES5(2009):第一个被广泛支持的版本(
JSON、strict mode)。ES6(2015):引入了大量新特性(箭头函数、
let/const、模块化、Promise)。ES7+(2016~2024):逐步增加了新特性(
async/await、可选链?.、空值合并??)。
Promise 和异步编程
JavaScript 是单线程的,为了避免 阻塞 UI,它引入了 异步编程 来处理 网络请求、文件读取、定时器、事件监听 等任务。
在 JavaScript 中,主要的异步编程方式有:
回调函数(Callback) → 早期方式,容易形成回调地狱
Promise(ES6,2015) → 更清晰的异步流程控制
async/await(ES8,2017) → 语法更简洁,读起来像同步代码
模块化
ES6 引入了模块化的概念,可以使用 import 和 export 关键字导入和导出模块。
ESM 的特点
ESM 是 JavaScript 的模块化规范,它是 ECMAScript 的一部分
ESM 使用
import和export关键字来导入和导出模块ESM 是静态的,模块的依赖关系在编译时就确定了
ESM 是单例的,同一个模块只会加载一次
ESM 的使用
导出模块
javascript// math.js export function add(a, b) { return a + b; }导入模块
javascript// index.js import { add } from "./math.js"; console.log(add(1, 2));运行 ESM 模块
Node.js 默认不支持 ESM 语法,需要在
package.json文件中添加"type": "module"字段,或者使用.mjs文件扩展名。json{ "type": "module" }示例:
node index.js或node --experimental-modules index.mjs
ESM 和 CommonJS 的区别
标准来源
ESM 是 ECMAScript 的一部分,官方标准,新增语法
CommonJS 是 Node.js 的模块化规范,社区标准,仅新增了
require和module.exports两个全局对象
导入模块
ESM 使用
import关键字导入模块CommonJS 使用
require函数导入模块
导出模块
ESM 使用
export关键字导出模块CommonJS 使用
module.exports导出模块
加载模块
ESM 是静态的,模块的依赖关系在编译时就确定了
CommonJS 是动态的,模块的依赖关系在运行时确定
模块的单例
ESM 是单例的,同一个模块只会加载一次
CommonJS 是非单例的,同一个模块会加载多次
模块的循环依赖
ESM 不允许模块的循环依赖
CommonJS 允许模块的循环依赖
ESM 和 CommonJS 的兼容
ESM 导入 CommonJS 模块
ESM 可以导入 CommonJS 模块,但是导入的模块会被当作默认导出。
javascript// index.js import math from "./math.js"; console.log(math.add(1, 2));javascript// math.js module.exports = { add(a, b) { return a + b; }, };CommonJS 导入 ESM 模块
CommonJS 无法导入 ESM 模块,需要使用
import函数。javascript// index.js const { add } = await import("./math.js"); console.log(add(1, 2));javascript// math.js export function add(a, b) { return a + b; }
常用对象的原型方法速查表
字符串对象
string.split(separator, limit): 将字符串拆分为数组。
数组对象
array.join(separator): 将数组转换为字符串。array.pop(): 删除并返回数组的最后一个元素。array.push(item1, item2, ..., itemX): 向数组的末尾添加一个或多个元素,并返回新的长度。array.shift(): 删除并返回数组的第一个元素。array.reverse(): 反转数组中元素的顺序,直接修改原数组。array.forEach(function(currentValue, index, arr), thisValue): 用于调用数组的每个元素,并将元素传递给回调函数。array.map(function(currentValue, index, arr), thisValue): 用于调用数组的每个元素,并将元素传递给回调函数,返回新的数组。
基础概念
原型方法是什么?和原型链有什么关系?
原型方法是附加在 JavaScript 对象的 prototype 上的函数,所有继承该 prototype 的对象实例都可以访问并使用这些方法。
原型链是 JavaScript 实现对象继承的一种机制,通过一系列的 prototype 连接形成链条。每个对象都有一个内部的 [[Prototype]] 属性(通常通过 __proto__ 访问),指向其构造函数的原型对象(prototype)。
原型方法依赖于原型链, 通过原型链的方式实现了对象的继承,如果对象本身没有这个方法,会沿着原型链向上查找,直到找到为止。
原型链是原型方法的实现基础,原型链保证了对象实例可以继承 prototype 上的属性和方法。
JavaScript 基础
表达式和参考符
typeof
用于判断变量的类型
typeof "John"; // Returns string内置对象-数组
Array.prototype.map()
map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
const array1 = [1, 4, 9, 16];
// Pass a function to map
const map1 = array1.map((x) => x * 2);
console.log(map1);
// Expected output: Array [2, 8, 18, 32]Array.prototype.forEach()
forEach() 方法对数组的每个元素执行一次提供的函数。
document.querySelectorAll(".check-content").forEach((element) => {
element.style.display = "";
});Window
参考:MDN 文档
滚动相关 (Scroll)
window.scrollX: 获取窗口的水平滚动位置。window.scrollY: 获取窗口的垂直滚动位置。window.scrollTo(): 滚动到指定的坐标。jswindow.scrollTo(0, 100);window.scrollBy(): 滚动指定的距离, 相对于当前的滚动位置。jswindow.scrollBy(0, 100);
平滑滚动
如果想要在页面滚动时更加平滑,可以使用 scroll-behavior 属性:
html {
scroll-behavior: smooth;
}元素 (Element)
参考:MDN 文档
事件相关 (Event)
我们可以为元素添加事件监听器,当事件发生时执行指定的函数。
element.addEventListener("click", () => {
console.log("Element clicked");
});不同的元素事件有不同的类型,下面是一些常见的事件类型:
click: 鼠标点击事件mousedown: 鼠标按下事件和
click事件的区别是,mousedown事件是鼠标按下时触发,所以不受按钮禁用(disabled)状态的影响,而click事件是鼠标按下和抬起都在同一个元素上时触发。mouseover: 鼠标移入事件mouseout: 鼠标移出事件
滚动相关 (Scroll)
element.scrollTop:获取或设置一个元素的内容垂直滚动的像素数。滚动到指定位置:
element.scrollTop = 100;element.scrollHeight:获取元素的内容高度,包括溢出的内容。element.scrollLeft:获取或设置一个元素的内容水平滚动的像素数。element.scrollIntoView():使元素滚动到可见区域。
内置对象 (Built-in Objects)
静态对象 (Static objects)
Object.defineProperty()
定义对象的一个属性,或修改现有属性的特性。
Object.defineProperty(obj, prop, descriptor);可以用它来修改对象的属性,比如修改navigator对象的webdriver属性:
Object.defineProperty(navigator, "webdriver", {
get: () => false,
});webDriver是一个布尔值,指示浏览器是否正在运行webDriver测试。通过修改这个属性,可以防止网站检测到你是通过 WebDriver 运行的,有一定的反爬虫效果。
还可以修改其他属性,比如修改navigator对象的userAgent属性:
Object.defineProperty(navigator, "userAgent", {
get: () =>
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
});Dom 操作 (Document Object Model)
参考:MDN 文档
Shadow DOM
参考:MDN 文档
Shadow DOM 是一种 JavaScript API,用来将 DOM 树的一部分封装起来,使其成为独立的“子树”。这个子树与外部的 DOM 隔离,外部的样式和 JavaScript 无法直接访问或影响它,反之亦然。这种封装提供了一种方式来创建自定义元素,使得其内部结构和行为不受外部环境的干扰。
在使用 Vue.js、React 等现代框架时,常需要进行动态内容的渲染。通过 Shadow DOM,可以将动态渲染的内容封装起来,避免与页面其他部分的冲突。
另外,在样式隔离、Web 组件封装、定制化 UI 等方面,Shadow DOM 也有着广泛的应用。
视频号的管理后台 --> 达人广场界面的内容,都是通过 Shadow Dom 来实现的
Shadow DOM 的基础操作
element.shadowRoot: 获取元素的 Shadow DOM 根节点。jslet customElement = document.querySelector("custom-element"); let shadowRoot = customElement.shadowRoot;element.attachShadow(): 创建一个 Shadow DOM 根节点。里面有一个参数,可以是一个对象,用来设置 Shadow DOM 的模式:
{ mode: "open" }表示可以通过element.shadowRoot访问 Shadow DOM。{ mode: "closed" }表示不可以通过element.shadowRoot访问 Shadow DOM。
Web APIs
完整的列表可以参考:MDN 文档
Window
Window 接口代表一个包含 DOM 文档的窗口。document 属性指向窗口中载入的 Document 对象。
setInterval()
setInterval() 方法会按照指定的周期(以毫秒计)来调用函数或计算表达式。
setInterval(() => {
console.log("Hello");
}, 1000);clearInterval 方法用于停止 setInterval() 方法执行的函数代码。
let interval = setInterval(() => {
console.log("Hello");
}, 1000);
clearInterval(interval);setInterval() 实现轮询
可以用这个实现轮询的方法,比如我需要等待某个元素加载完成后再进行操作:
function waitForElement(selector, callback, interval = 100, timeout = 5000) {
const start = Date.now();
const timer = setInterval(() => {
const element = document.querySelector(selector);
if (element) {
clearInterval(timer);
callback(element);
} else if (Date.now() - start >= timeout) {
clearInterval(timer);
console.warn(`Element ${selector} not found within ${timeout} ms`);
}
}, interval);
}
waitForElement("#id_main_name", (NameSelectElement) => {
const Namelayui =
NameSelectElement.parentNode.querySelector(".layui-anim-upbit");
const TypeSelectElement = document.getElementById("id_main_type");
function ClickName(e) {
var s = $(e);
var selValue = e.target.getAttribute("lay-value");
TypeSelectElement.setAttribute("value", "");
for (let i = 0; i < NameSelectElement.length; i++) {
if (NameSelectElement.options[i].textContent == selValue) {
var sva = NameSelectElement.options[i].getAttribute("typevalue");
if (sva) {
TypeSelectElement.setAttribute("value", sva);
}
}
}
}
if (Namelayui) {
Namelayui.addEventListener("click", ClickName, true);
} else {
console.warn("Element with class 'layui-anim-upbit' not found.");
}
});通过这样设计,可以在元素加载完成后再进行操作,避免因为元素未加载完成而导致的错误。
setTimeout()
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。
setTimeout(() => {
console.log("Hello");
}, 1000);Location
Location 对象表示当前窗口的 URL。可以通过 window.location 或者 document.location 访问。
以下是 URL 的组成部分:
我们可以通过 location 对象的属性来获取这些信息:
location.href: 获取或设置整个 URL。location.origin: 获取当前页面的协议、主机名和端口号。
例如:
console.log(location.origin); // "https://example.org:8080"Web Storage
通过 Web Storage,网页可以在本地存储数据(类似于 Cookie,但是更安全,更快)。
Node
Node 对象表示文档中的节点。
节点属性
对于任何获取的元素,你可以通过点操作符.来访问它的属性。
比如想要获取 img 元素的 src 属性,可以这样:
document.querySelector("img").src;常用的节点属性有:
childNodes: 返回节点的子节点集合,作为 NodeList 对象。firstChild: 返回节点的第一个子节点。nodeName: 返回节点的名称。textContent: 设置或返回节点的文本内容。innerText: 设置或返回节点及其后代的文本内容。innerHTML: 设置或返回节点的 HTML 内容。
evaluate()
evaluate(xpathExpression, contextNode, namespaceResolver, resultType, result)
evaluate() 方法计算 XPath 表达式,并返回结果。
document.evaluate(
"//div",
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;getElementById()
返回对拥有指定 ID 的第一个对象的引用。
document.getElementById("myId");querySelector()
返回文档中匹配指定 CSS 选择器的一个元素。
document.querySelector(".auxo-table-body");可以组合起来使用,比如我想要获取某个元素下的某个子元素:
document.querySelector("div.flex.flex-col div.flex.flex-row span");querySelectorAll()
返回文档中匹配指定 CSS 选择器的所有元素。
document.querySelectorAll("tbody tr");Navigator
Navigator 对象包含有关浏览器的信息。
在控制台中输入 Navigator 可以查看浏览器的相关信息。
The localStorage Object
对象存储可以一直使用,直到用户清除浏览器缓存。
// 设置
localStorage.setItem("lastname", "Smith");
// 获取
document.getElementById("result").innerHTML = localStorage.getItem("lastname");