资讯动态

JavaScript零基础入门:从变量、函数到DOM与异步编程

发布时间:2026/10/23 15:04:04 来源:尧图企业网站定制
简介一份面向JavaScript初学者的系统化语言教程也适合有一定编程基础、希望补齐核心概念的学习者。文档按知识模块组织从变量声明、数据类型、运算符与控制结构讲起逐步深入到函数、对象、DOM操作和异步编程基本覆盖ES6中let/const、Symbol、Promise等常见特性函数部分强调一等公民特性异步部分梳理回调、Promise与async/await并通过大量示例代码展示每项语法的实际用法帮助读者在阅读中同步理解运行机制与编程思路。资源为单个docx文档约19KB便于在电脑、平板或手机端直接查阅与检索目前已有88人浏览学习。除了系统梳理知识体系文档还给出时钟、待办事项、简易计算器等实践项目建议并推荐MDN、Eloquent JavaScript、freeCodeCamp等延伸资料适合作为入门自学、培训辅助或快速复习的随身手册。1. JavaScript 到底是个什么东西给网页装上大脑的“遥控器”想象你面前放着一张印好的报纸图片、文字全都在那儿但无论你怎么摸它都不会动一下。网页最初的形态就是这样HTML 负责画出结构和内容CSS 负责上色和排版但页面本身是死的。JavaScript简称 JS的出现相当于给这张报纸装上了一个遥控器——点按钮能弹提示、填错表单能当场校验、图片可以轮播、页面局部内容能自己刷新。它解决的核心问题只有一个让网页从“死”变“活”。而 JS 的本事远不止浏览器这一亩三分地。借助 Node.js 这类运行时环境它也能跑在服务器上处理后端请求还能用来写桌面应用、做小游戏。对初学者来说先弄懂 JS 的语法、函数、对象、DOM 操作和异步编程这五件事就基本能看懂日常开发里的大部分前端代码了。JS 是一门“多范式”语言既能像命令式语言那样一步步下指令也能用函数式、声明式的思路写代码这样灵活的设计让它常被戏称为“什么都能干但也到处是坑”的语言。搞懂它等于拿到了理解整个现代 Web 开发的钥匙。2. 从变量到规则先给代码搭一个能跑起来的骨架这一章回答一个很实际的问题一段 JS 代码到底是用什么“砖块”和“规则”砌起来的。前面说 JS 是给网页装大脑那大脑里的神经回路就是本节要讲的变量、数据类型、运算符和控制结构。这四样东西熟悉了你就拥有阅读任何一段基础 JS 代码的能力。2.1 先分清数据类型原始类型和引用类型的差别JS 里的数据分两大类这个分类会直接影响你写代码时“改一个值会不会影响另一个变量”。第一类是原始类型Primitive Type包括字符串String、数字Number、布尔值Boolean、空值Null、未定义Undefined以及 ES6 引入的 Symbol。第二类是引用类型Reference Type重点是对象Object、数组Array和函数Function。打个比方原始类型像你在纸上写下一串数字别人抄走一份你手里那份怎么改都不会影响对方引用类型像一本共享笔记本大家看的是同一本谁拿笔改一行所有人翻开都会看到变化。这就是为什么把一个数组赋值给另一个变量后改其中一个另一个也跟着变的根本原因——它们指向的是同一个存储位置。let a 10; let b a; // b 拿到的是 a 的“复印件” b 20; console.log(a); // 10a 不受影响 let arr1 [1, 2, 3]; let arr2 arr1; // arr2 和 arr1 指向同一个数组 arr2.push(4); console.log(arr1); // [1, 2, 3, 4]arr1 也跟着变了这段代码前半部分是原始类型赋值后半部分是引用类型赋值。差别在于前者是“值传递”后者是“引用共享”。理解这一点之后你再看到有人用slice()或展开运算符[...arr]去“复制”数组就知道那其实是在刻意切断引用关系让两份数据互不干扰。还有一个新手容易踩坑的地方用typeof检查类型时typeof null返回的是object。这算是 JS 从早期版本遗留下来的一个知名怪癖——从语义上null表示“空值”属于原始类型但在typeof眼里它长得像一个空对象。你不需要背下这个的原因只需要记住判断null不要依赖typeof直接拿值和null比较就行。2.2 var、let、const 三兄弟变量提升和块级作用域到底怎么选JS 声明变量有三种方式它们之间的区别是初学者最容易混淆的地方也是面试题里的常客。三兄弟分别叫var、let和const。var是语言诞生之初就在的“老前辈”let和const是 ES6 时代加入的“新规矩派”。var最著名的特征是存在“变量提升”hoisting。通俗地说代码还没执行到声明那一行变量就已经被悄悄“预注册”了提前访问它不会报错只是值是undefined。let和const则老实得多它们有块级作用域被一对{}包住就只在那个块里生效而且在真正声明之前访问它会直接抛出一个错误这个阶段有个专门的名字叫“暂时性死区”TDZ。console.log(age); // undefined不报错因为 var 有变量提升 var age 18; console.log(name); // 报错Cannot access name before initialization let name 张三;那个报错就是 TDZ 在起作用let声明之前的区域属于禁区摸一下就给颜色看。这种设计其实是好事它逼着你先声明再使用能避免很多“以为是别的原因结果是变量提前访问”的诡异 bug。选型建议很简单默认用const需要重新赋值的场景才用let。const意味着“这个变量名不能再指向别的值”但它不意味着“值本身不可变”——比如const obj {}之后你依然可以给 obj 增加新属性只是不能再写obj somethingElse。至于var它现在更常出现在老代码和某些面试题里新项目里基本不主动用它了。2.3 运算符与控制结构把流程控制写成代码有了变量就得有操作运算符就是变量之间的“动作”。算术运算符负责 - * / %加减乘除取余赋值运算符负责以及它的加强版、-等比较运算符负责判断大小和相等逻辑运算符、||、!负责组合多个条件。三元运算符是其中的小巧门条件 ? 值1 : 值2一行就能写出 if/else 的效果。控制结构决定代码往哪个方向走。条件分支用if...else循环用for、while、do...while跳转用break、continue、return。它们和运算符组合起来就能表达“如果分数大于 60 就输出及格否则输出不及格”这类真实世界的逻辑。let score 75; if (score 60) { console.log(及格); } else { console.log(不及格); } for (let i 0; i 3; i) { console.log(第 i 次循环); }上面for循环里的三个部分要分开看let i 0是起点i 3是继续循环的条件i是每轮循环之后做的事。把这三个参数摆在明面上是for循环最直观的地方而while循环只关心“条件还成立吗”更适合循环次数不确定的场景。控制结构本身不复杂真正需要练的是“把脑子里解决问题的步骤翻译成条件和循环”——这个翻译能力比背语法重要得多。3. 函数与对象JS 里的两大“形态构造器”变量和控制结构只能让代码“跑起来”真正让代码有组织、可复用的是函数和对象。函数封装行为对象封装数据它们组合起来几乎能表达你在网页开发里遇到的一切东西按钮的点击逻辑是函数用户的资料是对象页面的每个组件都是一棵“数据 行为”的树。3.1 函数为什么是“一等公民”在 JS 里函数不只是“一段可以调用的代码块”它更算是一种特殊的值。这句话看起来抽象实际上意味着一件非常有用的事函数可以像数字、字符串一样被传递——把它塞进另一个函数当参数或者作为返回值从函数里吐出来。这种特性在编程语言里被叫作“函数是一等公民”first-class function。打个比方普通语言里的函数像固定工位上的人只能在自己的位置干活JS 里的函数像自由职业者今天可以被 A 项目调用明天能作为“简历”交给 B 项目后天还能被工厂包装成另一个函数再发出去。这个灵活性是后面讲回调函数、异步编程的基石。function greet(name) { return Hello, name; } function shout(fn, word) { return fn(word).toUpperCase(); } let result shout(greet, World); console.log(result); // 输出HELLO, WORLD上面代码的关键在shout函数它的第一个参数fn接收的不是普通值而是另一个函数greet。调用时shout先在内部执行fn(word)也就是调用greet(World)再把结果转成大写。这就是把函数当作值传递的直观例子。很多初学者第一次看到“把函数传进函数”会觉得别扭其实你就把它想象成“把一台设备交给工程师去接入链路”——设备还是那个设备只是换了环境运行。3.2 对象把相关的东西打包成一个整体对象是 JS 的另一种核心形态。它的作用是存储键值对每个键对应一个值值可以是数字、字符串、数组甚至另一个函数。你可以用一个对象把“一个人的所有信息”装在一起而不是散乱地用一堆变量各管各的。let person { name: John, age: 30, greet: function () { console.log(Hello, this.name); } }; person.greet(); // 输出Hello, John person.age 31; // 修改对象属性这里的person就是一个对象name和age是属性greet是挂在对象上的方法。注意greet函数内部用了this.name这个this指的是“当前调用这个方法的对象”所以当person.greet()被调用时this就是person自然能取到name。对象最大的价值是组织信息页面上的每个组件、接口返回的每份数据几乎都能用一个对象来描述。3.3 函数和数组都是对象但各有各的脾气JS 里有个容易让人困惑的设计数组和函数本质上也是对象。这意味着数组可以挂自定义属性函数甚至也能有自己的属性。但它们各自有专属的“超能力”数组有length属性还有一整套方法如push()、pop()、map()、filter()这让它虽然底层是对象却专门用于处理有序数据。函数可以被调用这个“可调用”的能力是普通对象所没有的但它可以像对象一样存放额外信息。理解这个设定的意义在于你不会再纠结“数组到底是对象还是数组”这种哲学问题。实际写代码时判断一个数据该用什么形态只需要看你的使用场景——要维护顺序和批量数据就用数组要描述一个事物的多维属性就用对象要封装一段可复用的行为就用函数。三者在底层是亲戚但在使用习惯上各有分工这恰恰是 JS 灵活性的来源。4. DOM 操作JS 凭什么叫“能管住网页”的语言前两章讲的语法、函数、对象都是 JS 自己的内在功夫。但 JS 最出圈的用途是动态地改变网页内容。它凭的不是魔法而是通过一个叫 DOMDocument Object Model的桥梁。4.1 DOM 是什么把网页变成一棵树DOM 是 HTML 和 XML 文档的编程接口。它做的事是把页面上的标签结构翻译成一棵“树”让编程语言能够访问和修改。你可以把 DOM 想象成一张网页的“施工图纸”图纸上标着哪里有标题、哪里有按钮、哪段文字需要被隐藏而 JS 就是照着这张图纸干活的施工队。这棵树的根部是文档document往下是html、body再往下是各种标签每一层都对应树上的一个节点。有了这个结构JS 就能精确地说出“我要找页面上 id 为myElement的那个按钮”。如果没有 DOM页面就只是一段纯文本字符串改起来会非常笨拙——而有了 DOM每个元素都是可以单独操作的对象。4.2 用 JS 改页面获取、修改、响应三步走任何 DOM 操作都可以拆成三个动作找到元素、修改它的内容或样式、有时还要监听用户在它上面的操作。// 第一步获取元素 let element document.getElementById(myElement); // 第二步修改内容 element.innerHTML New content; // 第三步添加事件监听 element.addEventListener(click, function () { alert(Element was clicked!); });这短短几行代码背后是整个动态网页的本质逻辑。document.getElementById(myElement)是在 DOM 树上做定位查找找到后element.innerHTML直接替换了元素内部的 HTML 内容而addEventListener则给元素挂上了一个“点击时执行什么”的监听器。注意第三步这个函数并没有立刻被调用而是被注册为“将来发生点击时才执行”——这是异步思想的雏形也是下一章的主线。4.3 为什么 DOM 操作经常“翻车”DOM 操作看似简单但实际做项目时新手最容易在三个地方翻车元素没找到、内容被覆盖、顺序不对。“元素没找到”最常见的原因是 JS 代码出现在目标标签之前页面自上而下解析时还没读到那个标签getElementById自然返回null。所以老手写代码时会把脚本放在页面末尾或者等DOMContentLoaded事件触发后再操作。“内容被覆盖”则是因为innerHTML是直接把整块内容替换掉如果你想在原有内容后面追加一段不小心用了innerHTML 就会把之前的全部冲掉。这个用insertAdjacentHTML()或者先拼接再赋值都能解决但前提是你知道问题出在哪。还有一个最容易忽略的易混点getElementById返回值是null还是元素很多人拿到null后还继续调用.innerHTML于是报错“Cannot read properties of null”。这里需要形成一个肌肉记忆任何 DOM 查询的结果都要先判空再做后续操作。这不是复杂的技术却是一条实实在在的防坑经验。5. 易混概念回调、Promise、async/await 和同步代码的边界异步编程是 JS 新手“劝退率”最高的一关。很多人不是学不会语法而是分不清什么叫“同步”、什么叫“异步”、回调函数和 Promise 到底解决什么问题。这一章就用最直白的方式把这几个概念拆开。5.1 单线程的现实JS 只有一双手先记住一个铁律JS 是单线程的。意思是它在同一个时刻只能处理一个任务没有分身术。这就像一家只有一位收银员的超市顾客必须一个一个结账前面的人动作慢后面的人只能等着。这个设计一开始是为了简化浏览器里的操作——如果多个线程同时改同一个页面画面怎么渲染、数据怎么统一都会变得极其复杂。但单线程有一个致命短板碰到耗时任务比如请求接口、读一个大文件时整条线程会被卡住页面就“假死”了。异步编程就是为了解决这个问题而生的既然只有一双手那就把耗时的活儿“外包”出去干完再通知主线程处理结果。5.2 回调函数 vs Promise两种“干完再叫我”的姿势回调函数是最朴素的异步方案。它的做法是把“做完之后要执行什么”作为函数传进去任务完成后自动调用它。放在上一章的例子里addEventListener里的那层匿名函数就是一个回调。// 回调风格1 秒后执行回调 setTimeout(function () { console.log(时间到); }, 1000); // Promise 风格同样是 1 秒后出结果但可以用 .then 接后续步骤 let promise new Promise(function (resolve, reject) { setTimeout(function () { resolve(Success!); }, 1000); }); promise.then(function (result) { console.log(result); // 输出Success! });两段代码做的事情本质上是一样的等 1 秒后再执行某段逻辑。区别在于代码的组织方式。回调的写法是“嵌套推进”的一个异步套一个异步时层级一深就变成传说中的“回调地狱”。Promise 则把异步这件事包装成了一个对象它有三个状态——进行中pending、成功fulfilled、失败rejected。成功后用.then接下一步失败用.catch接错误处理。对比项回调函数Promise代码形状嵌套层级多时难读链式.then扁平化错误处理每个回调里手动检查统一用.catch兜底能否用 async/await不行可以写法更顺适合场景简单的一次性监听多步依赖的异步流程记住一个关键区别回调本身只是一种“传函数进去”的写法甚至同步代码里也能出现回调而 Promise 是专门为异步结果而生的容器它自带状态管理和错误传递机制。5.3 async/await把异步写成同步的样子Promise 解决了回调地狱但.then一串起来还是有点绕。于是 JS 又提供了async/await这是一种建立在 Promise 之上的语法糖目的是让异步代码看起来像普通的同步代码但背后依然是异步执行。async function run() { let result await new Promise(function (resolve) { setTimeout(function () { resolve(加载完成); }, 1000); }); console.log(result); // 1 秒后输出加载完成 } run();这段代码最大的视觉变化是没有.then了取而代之的是一个await关键字它表示“这一行要等 Promise 出结果期间不阻塞主线程等结果回来再继续往下走”。async用来标记这是一个异步函数只有标记了它里面才能用await。对初学者来说理解async/await最直接的角度就是它是 Promise 的语法糖用法上把异步流程写成了“先等待结果再执行下一步”的直线逻辑好读也好维护。5.4 常见误区这几个易混点必须厘清第一回调函数不等于异步。回调只是一种函数传递机制完全可以在同步代码里使用比如数组的forEach里传的那个函数。只有那些“晚点再执行”的回调才是异步的判断标准是看它是否被放进了定时器、网络请求等机制里。第二async/await不是另起炉灶的异步方案。它逃不出 Promise 的手掌心底层依然是 Promise 状态机在驱动。所以如果有人说他“不用 Promise只用 async/await”那不是真的async/await 本身就是靠 Promise 实现的。第三await只能用在async函数内部。把这个规则理解成“只有特殊牌照的车才能走专用道”就好——在普通函数里写await立刻报错。第四朴素回调与 Promise 的错误处理思路不同。回调风格里每个错误点都可能要单独处理Promise 提供链式的.catch而 async/await 则推荐用try...catch包住。这三者的复杂度是一个递进的回调最原始Promise 更规范async/await 更易读。6. 什么时候用 JavaScript什么时候别硬上一个入门的边界判断学了这么多你可能会问那到底什么场景应该用 JS什么场景不应该我给出一个很实际的判断框架。该用 JavaScript 的场景核心只有一个词动态交互。页面上需要根据用户操作实时反馈时表单校验、弹窗、内容切换、需要从服务器拉数据并更新局部内容时评论区加载、订单状态刷新、需要做一些浏览器端的信息处理时本地存储、Canvas 绘制这些场景都用得上 JS。它不是“锦上添花”而是这些功能的必要载体。写着写着你会发现JS 本质上把持住了 Web 的两个极端它既能像刻刀一样精细地改一个按钮的样式也能像起重机一样调度复杂的前端应用逻辑。这也是它的魅力所在。不该用 JS 的场景同样清晰。第一页面内容需要被搜索引擎稳定收录时关键信息不要完全依赖 JS 渲染——否则爬虫抓到的可能是一张“白纸版”的页面。第二如果一段任务纯粹是固定内容的展示完全没有交互就不需要引入一堆 JS 脚本纯 HTML 和 CSS 反而更快更省。第三涉及大量 CPU 密集的计算比如图像处理的复杂算法JS 的单线程特性会让它力不从心这类任务更适合交给浏览器原生能力或后端处理。我自己的血泪经验是刚入门时我看到什么都想用 JS 实现一遍结果页面加载了一堆用不上的脚本首屏越来越慢。后来我养成了一个习惯每次动笔前先在脑子里过一遍——“这个功能必须要用户交互吗必须实时变化吗如果没有 JS用纯 HTML/CSS 能不能达到 80% 的效果”如果答案是不需要我就把 JS 放下。这一步筛选帮我省掉了大量无意义的代码。JS 的学习曲线很特别入门不难两三天就能看懂基础语法但函数、对象、DOM、异步这四个概念层层递进每翻过一座山都会看到一片更广的疆域。找到一个自己真正想做的例子——比如一个待办事项列表亲手把它从静态页面做成可增删的交互应用你会突然觉得之前学的语法都活了起来。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑