跳到主要内容 JavaScript 前端开发基础入门与 DOM 操作详解 | 极客日志
JavaScript 大前端
JavaScript 前端开发基础入门与 DOM 操作详解 系统讲解了 JavaScript 前端开发的核心基础知识。内容包括变量声明方式(var、let、const)的区别与作用域管理,基本数据类型与复杂数据结构的特性。深入探讨了条件判断语句(if、switch)与循环控制(for、while、do...while)的逻辑应用。详细解析了函数的定义、匿名函数及 ES6 箭头函数的语法与 this 指向机制。最后重点介绍了 DOM 操作技术,涵盖元素获取、内容与样式修改以及节点的动态创建与删除方法,为构建交互式网页提供实践指导。
LinuxPan 发布于 2026/3/27 更新于 2026/4/16 2 浏览引言
在当今数字化时代,互联网已然成为人们生活不可或缺的一部分,而网页作为互联网的主要载体,其用户体验的优劣直接关乎着信息的有效传递与用户的留存。JavaScript,这门在前端开发领域占据核心地位的编程语言,犹如一位神奇的魔法师,为静态的网页注入灵动的生命力,使之蜕变成为交互性强、功能丰富的精彩世界。
不妨回想一下,当我们浏览那些热门网站时,诸多令人惊艳的交互效果扑面而来。鼠标轻轻悬停于导航栏,下拉菜单如丝般顺滑地展开,各类选项一目了然,仿佛在热情指引我们探索网站的深层内容;点击图片,它竟能优雅地放大,细节之处尽显无遗,让我们不错过任何精彩;填写表单时,一旦输入有误,即时的错误提示便会贴心出现,引导我们快速修正。这些看似平常却又极大提升体验的交互细节,背后皆是 JavaScript 在默默施展魔力。它能够精准捕捉用户的每一次点击、滚动、输入等操作,并以毫秒级的响应速度触发相应的功能,为用户带来流畅、自然且愉悦的浏览之旅。
接下来,让我们一同深入 JavaScript 的奇妙世界,揭开其在前端开发中的神秘面纱,探寻那些让网页焕发生机的神奇代码。
变量与数据类型
在 JavaScript 中,变量犹如一个个神奇的盒子,用于存储各类数据,而声明变量的方式有 var、let、const 三种,它们各自有着独特的性格与适用场景。
var,作为元老级的变量声明方式,自 JavaScript 诞生之初便已存在。它具有函数作用域,这意味着在一个函数内部声明的 var 变量,在整个函数体内都如同拥有了通行证,随处可见且可被访问。不过,var 变量存在变量提升的特性,就好像变量被偷偷地提到了函数顶部进行了预声明,即便你在函数底部才正式声明它,在顶部也能访问,只不过此时它的值是 undefined,犹如一个空盒子等待被填满。例如:
function varTest ( ) {
console .log (x);
var x = 10 ;
console .log (x);
}
varTest ();
并且,var 允许在同一作用域内重复声明同一个变量,后续的声明会悄无声息地覆盖前面的声明,如同在同一个盒子里不断更换物品。
let 则是 ES6 引入的新贵,它带来了块级作用域的概念,让变量的作用范围更加精准可控。在一个由花括号{}包裹的代码块中,如 if 语句、for 循环内部,使用 let 声明的变量就像是被限定在了这个小天地里,外界无法轻易窥探。而且,它不存在变量提升,坚决杜绝了在变量未声明就使用的乱象,若你试图在声明前访问,JavaScript 会毫不留情地抛出引用错误,就像未被允许进入的禁地,强行闯入就会触发警报。例如:
function letTest ( ) {
if (true ) {
let y = 20 ;
console .log (y);
}
console .log (y);
}
letTest ();
const,同样来自 ES6 家族,主要用于声明常量。它和 let 一样具有块级作用域,一旦被赋予初始值,就如同被刻上了不可更改的印记,后续任何试图重新赋值的操作都会引发 TypeError 错误。不过,若是 const 声明的是复杂数据类型,如对象或数组,虽然不能重新赋值整个变量,但可以修改其内部的属性或元素,因为 const 保证的是变量所指向的内存地址不变,而复杂数据类型内部结构的改变并不影响这个地址。例如:
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
const PI = 3.14159 ;
PI = 3.14 ;
const array = [1 , 2 , 3 ];
array.push (4 );
console .log (array);
const obj = { name : 'Alice' };
obj.name = 'Bob' ;
console .log (obj);
JavaScript 的数据类型丰富多样,仿若一个琳琅满目的魔法宝库,大致可分为基本数据类型与复杂数据类型。基本数据类型像是精巧的原子,各自独立,包括 Number(数字型)、String(字符串型)、Boolean(布尔型)、Undefined(未定义型)、Null(空值型)。Number 类型涵盖了整数与浮点数,无论是简单的数学运算 1 + 2,还是复杂的科学计算 Math.pow(2, 3),它都能轻松应对;String 类型则是文本的乐园,用单引号或双引号包裹,如'Hello, JavaScript',字符串的拼接、截取、查找等操作,让文本处理充满趣味;Boolean 类型仅有 true 和 false 两个值,在条件判断中扮演着关键角色,犹如交通信号灯,决定程序的走向。
复杂数据类型则像是由原子组成的分子,结构更为复杂。Object(对象)类型就是一个万能的收纳箱,可以容纳多个键值对,用来描述一个实体的各种属性,如{ name: 'John', age: 30, hobbies: ['reading', 'traveling'] },通过点语法或方括号语法就能访问和修改其中的属性;Array(数组)类型如同一条有序的数据链,每个元素都有对应的索引,方便存储和操作一系列相关的数据,像[10, 20, 30],数组的方法如 push、pop、map、filter 等,为数据处理提供了强大的工具。
条件与循环语句 在 JavaScript 的编程世界里,条件与循环语句宛如精密的导航仪与高效的引擎,精准指引并驱动着程序的运行流程,使其能够根据不同的情境做出智能决策,或是高效重复执行特定任务。
if...else 语句作为条件判断的主力军,语法简洁而强大。它以 if 开头,紧跟括号内的条件表达式,当表达式的值为 true 时,便会如同开启一扇通往特定代码块的门,执行其中的语句;若条件不满足,else 分支就会像备胎一样顶上,执行另一段备用代码块。例如,在一个简单的用户登录验证场景中:
let username = 'admin' ;
let password = '123456' ;
if (username === 'admin' && password === '123456' ) {
console .log ('登录成功,欢迎您!' );
} else {
console .log ('用户名或密码错误,请重新输入。' );
}
这里,通过对用户名和密码的精确比对,if...else 语句迅速给出相应反馈,保障系统安全。而且,它还支持 else if 的链式扩展,面对多种细分情况时,能像层层筛选的滤网一样,精准定位到符合的条件分支执行,使程序的逻辑更加细腻周全。
switch 语句则像是一个多路开关,当需要对一个表达式的多种可能值进行判断时,它便能大显身手。以一个根据不同成绩等级输出评价的案例来看:
let score = 85 ;
switch (true ) {
case score >= 90 :
console .log ('优秀' );
break ;
case score >= 80 :
console .log ('良好' );
break ;
case score >= 60 :
console .log ('及格' );
break ;
default :
console .log ('不及格' );
}
在这个例子中,switch 依据 score 的值精准落入对应的 case 分支,输出恰当评价。不过要特别留意,每个 case 分支执行完毕后,break 语句如同断路闸一般至关重要,若遗漏,程序就会像失控的列车,顺势冲向下一个 case 分支,引发错误的连续执行。
循环语句方面,for 循环是最为常用的迭代利器。它的语法结构好似一台精密的循环机器,由初始化表达式、条件表达式、更新表达式三部分协同工作。初始化表达式负责启动循环变量,条件表达式如同门禁,决定循环是否继续,更新表达式则在每次循环结束后对变量进行调整。以计算 1 到 100 的整数和为例:
let sum = 0 ;
for (let i = 1 ; i <= 100 ; i++) {
sum += i;
}
console .log (sum);
在这里,for 循环有条不紊地从 1 迭代到 100,将每个数累加到 sum 中。同时,它还能巧妙嵌套,构建出复杂的多维迭代逻辑,用于处理诸如多维数组、矩阵运算等复杂任务。
while 循环则像是一位坚守岗位的循环卫士,只要条件表达式为 true,就会执着地重复执行循环体中的代码。比如,要实现一个简单的猜数字游戏,在玩家猜对之前,循环持续进行:
let targetNumber = 42 ;
let guess;
while (guess !== targetNumber) {
guess = parseInt (prompt ('请猜一个数字:' ));
if (guess > targetNumber) {
console .log ('猜大了,请再试一次。' );
} else if (guess < targetNumber) {
console .log ('猜小了,请再试一次。' );
}
}
console .log ('恭喜你,猜对了!' );
在这个例子中,while 循环时刻监控玩家的猜测,根据不同情况给出提示,直至猜对为止。
do...while 循环像是 while 循环的加强版,它的独特之处在于,无论条件初始是否满足,循环体至少会执行一次,就像先迈出第一步,再看是否符合前行条件。例如:
let count = 0 ;
do {
console .log (count);
count++;
} while (count < 5 );
这段代码会先输出 0,然后逐步递增输出,直至 count 达到 5。它适用于那些需要先执行一次操作,再依据结果判断是否继续的场景,为程序逻辑增添了更多灵活性。
函数 函数,在 JavaScript 中犹如一个个精心封装的魔法盒子,将一系列操作指令收纳其中,可依据需求随时调用,重复施展其魔力,极大地提升了代码的复用性与可维护性。
普通函数的定义方式通常使用 function 关键字,像是在宣告一场独特仪式的开启。语法如下:
function addNumbers (a, b ) {
return a + b;
}
这里,addNumbers 便是函数名,括号内的 a、b 是形参,如同等待被填充的魔法原料槽,函数体中的 return 语句则像一个结果出口,将计算得到的两数之和送出。调用函数时,只需使用函数名并传入实际参数,如:
let result = addNumbers (5 , 3 );
console .log (result);
函数在接收参数时相当灵活,实参的数量不必严格与形参匹配。若实参少于形参,多余的形参值为 undefined;若实参多于形参,多余的实参则会被默默忽略。
匿名函数,顾名思义,是没有名字的函数,宛如一位神秘的幕后高手。它常作为回调函数登场,在事件处理、异步编程等场景中大放异彩。例如,为一个按钮添加点击事件监听器:
document .getElementById ('myButton' ).onclick = function ( ) {
console .log ('按钮被点击了!' );
};
这里的匿名函数如同隐匿在按钮背后的触发指令,当按钮被点击时,迅速执行相应操作。匿名函数还能通过立即执行函数表达式(IIFE)实现自执行,将创建与执行合二为一,避免变量污染全局命名空间,常用于初始化任务,如:
(function ( ) {
let privateVariable = 42 ;
console .log ('立即执行函数内部:' , privateVariable);
})();
箭头函数,作为 ES6 引入的简洁利器,以其精简的语法和独特的 this 绑定特性备受青睐。它的基本语法形如:
const multiply = (a, b ) => a * b;
短短一行,便定义了一个乘法函数,当函数体只有一条返回语句时,甚至可以省略花括号与 return 关键字。箭头函数最大的亮点在于 this 的指向,它不绑定自身的 this,而是如同忠诚的追随者,捕获所在上下文的 this 值。对比传统函数:
function Person ( ) {
this .age = 0 ;
setInterval (function growUp ( ) {
this .age ++;
}, 1000 );
}
function Person ( ) {
this .age = 0 ;
setInterval (() => {
this .age ++;
}, 1000 );
}
在上述例子中,箭头函数巧妙地避开了传统函数 this 指向易混淆的陷阱,确保在定时器回调中,this 始终指向预期的 Person 实例,使得代码逻辑更加清晰、稳定。
获取 DOM 元素 在 JavaScript 的前端开发领域,精准且高效地获取 DOM 元素是实现丰富交互效果的基石。DOM(Document Object Model),即文档对象模型,宛如一棵倒置的树状结构,将 HTML 文档中的各个元素进行了细致的对象化封装,使得 JavaScript 能够轻松与之对话,进而随心所欲地操控页面内容。
document.getElementById 方法,无疑是这一交互过程中的一把利器,它凭借元素独一无二的 id 属性,能够以极高的精准度直击目标元素。就如同在一个庞大的图书馆中,每本书都有唯一的索引号,通过这个索引号,便能迅速定位到所需书籍。例如,在网页中存在一个标题元素:
<h1 > 精彩的 JavaScript 世界</h1 >
在 JavaScript 代码中,若要获取并操作这个标题,只需调用:
const titleElement = document .getElementById ('page-title' );
console .log (titleElement.textContent );
这里,通过指定'id'为'page-title',document.getElementById 迅速锁定目标,返回对应的 DOM 元素对象,后续便可通过该对象的一系列属性与方法,如修改文本内容、样式等,为页面带来动态变化。
与之类似的 querySelector 方法,则像是一位更加全能的探险家,它能够接纳多种形式的 CSS 选择器作为参数,不仅可以通过 id 精准定位,还能依据类名、标签名以及复杂的组合选择器来挖掘所需元素。以获取页面中的按钮元素为例:
使用 querySelector,既可以通过类名获取:
const buttonByClass = document .querySelector ('.action-btn' );
buttonByClass.addEventListener ('click' , function ( ) {
console .log ('按钮被点击了!' );
});
const specificButton = document .querySelector ('button.action-btn' );
specificButton.style .backgroundColor = 'skyblue' ;
querySelectorAll 方法,则像是 querySelector 的加强版兵团,它会依据选择器规则,将所有匹配的元素一网打尽,以类数组形式呈现。假设页面中有多个具有相同类名的列表项:
<ul >
<li > 项目一</li >
<li > 项目二</li >
<li > 项目三</li >
</ul >
使用 querySelectorAll 可一次性获取所有列表项:
const listItems = document .querySelectorAll ('.list-item' );
listItems.forEach (function (item, index ) {
item.textContent = `项目${index + 1 } (更新)` ;
});
如此一来,便能批量对列表项进行文本更新,实现高效的页面内容调整。不同的获取方法各具千秋,熟练驾驭它们,便能在 DOM 操作的舞台上长袖善舞,为网页注入灵动活力。
修改 DOM 内容和样式 在成功捕获 DOM 元素之后,如何巧妙地修改其内容与样式,成为让网页活灵活现的关键所在。JavaScript 提供了一系列强大且便捷的方式,使得开发者能够像一位位精湛的艺术家,随心所欲地雕琢网页,实时呈现出千变万化的视觉效果。
修改元素的文本内容,可借助 innerHTML、textContent 以及 innerText 等属性来实现。innerHTML 属性宛如一位魔法画师,它不仅能够识别并渲染文本,还能完美解析 HTML 标签,实现文本与结构的同步更新。假设页面中有一个段落元素:
const paragraph = document .getElementById ('intro-paragraph' );
paragraph.innerHTML = '这是一段 <strong>全新且精彩</strong> 的文本。' ;
执行后,页面上的段落会立即呈现出带有加粗强调的新文本,结构与样式瞬间焕然一新。
textContent 属性则像是一位纯净文本使者,它专注于文本本身,只会提取并设置元素及其子元素中的纯文本内容,忽略任何 HTML 标签。例如:
const anotherParagraph = document .createElement ('p' );
anotherParagraph.textContent = '这里的 <em>标签</em> 会被当作文本输出。' ;
document .body .appendChild (anotherParagraph);
此时,页面上新增的段落中,标签会以文本形式原汁原味地展示,不会产生任何样式效果,确保了文本的纯粹性。
innerText 属性与 textContent 类似,但在处理换行、空白符等细节时存在细微差异,它更贴近用户视觉上看到的文本内容,会自动对多余空白进行合并等处理。
修改元素样式方面,style 属性是直接操控元素内联样式的金钥匙。每个 DOM 元素的 style 对象都对应着一系列 CSS 属性,不过需要留意的是,在 JavaScript 中,CSS 属性名需遵循驼峰命名法。以一个按钮为例:
const dynamicButton = document .getElementById ('dynamic-btn' );
dynamicButton.addEventListener ('click' , function ( ) {
this .style .backgroundColor = 'orange' ;
this .style .color = 'white' ;
});
如此,每次点击按钮,其外观便会在瞬间切换,为用户带来即时的视觉反馈。
除了直接操作 style 属性,还可通过修改元素的 className 或 classList 属性,灵活切换 CSS 类名,进而批量应用预定义的样式规则。在 CSS 中定义了一些类:
.highlight { background-color : yellow; box-shadow : 0 0 5px rgba (0 , 0 , 0 , 0.3 ); }
.big-font { font-size : 20px ; }
在 JavaScript 中,可为元素动态添加或移除这些类:
const targetElement = document .getElementById ('target' );
targetElement.classList .add ('highlight' , 'big-font' );
setTimeout (() => {
targetElement.classList .remove ('highlight' );
}, 3000 );
通过这种方式,元素的样式能依据程序逻辑或用户交互,在不同时刻呈现出多样的组合变化,极大提升了页面的动态表现力。
动态创建和删除 DOM 元素 在现代网页开发的舞台上,动态创建与删除 DOM 元素的能力,犹如神奇的魔法棒,赋予网页根据用户操作、数据变化实时变形的超能力,打造出高度交互、内容常新的浏览体验。
要凭空创造一个 DOM 元素,document.createElement 方法便是那开启创造之门的咒语。它接受一个标签名作为参数,瞬间就能在内存中生成一个对应的 DOM 节点对象,尽管此时这个节点还未在页面上现身。例如,若要在页面添加一个新的图片元素:
const newImage = document .createElement ('img' );
newImage.src = 'new-image.jpg' ;
newImage.alt = '一张全新的图片' ;
此刻,newImage 对象已就绪,但还游离于页面结构之外。为使其正式登台亮相,需借助 appendChild 或 insertBefore 等方法,将其插入到合适的 DOM 位置。appendChild 如同一位收纳大师,它会将新元素添加到指定父元素的最后一个子元素位置。假设页面有一个容器元素:
const container = document .getElementById ('image-container' );
container.appendChild (newImage);
瞬间,新图片便出现在容器底部,成为页面视觉的一部分。
insertBefore 方法则更加灵活多变,它允许在指定的参考子元素之前插入新元素,精准把控元素的排列顺序。比如,已有一组图片列表,要在第二张图片前插入新图:
<ul >
<li > <img src ="image1.jpg" alt ="图片 1" > </li >
<li > <img src ="image2.jpg" alt ="图片 2" > </li >
<li > <img src ="image3.jpg" alt ="图片 3" > </li >
</ul >
const list = document .getElementById ('image-list' );
const secondItem = list.children [1 ];
list.insertBefore (newImage, secondItem);
这样,新图片便优雅地插入到了期望位置,完美融入图片序列。
与创建相对的,删除 DOM 元素在某些场景下同样关键。removeChild 方法肩负起这一清理重任,它从父元素的怀抱中移除指定的子元素。继续以上述图片列表为例,若要删除某张图片:
const itemToRemove = list.children [0 ];
list.removeChild (itemToRemove);
执行后,首张图片便从页面消失,列表自动重新排列,无缝衔接。
在实际应用中,动态创建与删除 DOM 元素常协同发力。比如构建一个动态评论区,用户每提交一条评论,JavaScript 便使用 createElement 生成包含评论内容、作者等信息的 DOM 结构,并通过 appendChild 添加到评论区容器;若评论可删除,点击删除按钮时,触发 removeChild 移除相应评论元素,整个过程行云流水,让网页时刻与用户互动同步,展现出极强的生命力与适应性。