JavaScript程序入门:从变量、函数到第一个交互页面

教程3天前发布 jdkjadmin
0 00
JavaScript程序入门:从变量、函数到第一个交互页面

JavaScript程序入门:从变量、函数到第一个交互页面

JavaScript 是一种常用于网页开发的编程语言。它可以读取用户操作、更新页面内容、校验表单,也可以在服务器、命令行工具和桌面应用等环境中运行。对于刚开始学编程的人来说,最直观的起点通常是浏览器:写几行代码,就能让网页对点击和输入作出反应。

本文从变量、数据类型、条件判断和函数讲起,最后完成一个可以直接运行的交互页面。示例使用原生 JavaScript,不依赖框架或第三方库。阅读时可以把代码复制到文件中实际运行,再尝试修改提示文字、判断条件和函数参数。

一、JavaScript 适合做什么

在浏览器中,JavaScript 常用于处理页面交互,例如点击按钮后切换内容、根据输入更新结果、校验表单格式,以及从服务器获取数据后渲染页面。HTML 负责页面结构,CSS 负责外观,JavaScript 则负责行为;实际项目里三者通常配合使用。

JavaScript 并不只存在于浏览器。Node.js 等运行环境可以在服务器或本机运行 JavaScript,常见用途包括开发接口服务、编写自动化脚本和构建工具。浏览器 JavaScript 与 Node.js 的运行环境并不相同:浏览器提供 DOM 等网页相关接口,Node.js 则提供文件系统等服务端能力。语言语法有许多共通之处,但不能假定某个环境里的接口在另一个环境也存在。

本文关注浏览器端入门。页面中的代码可以改善使用体验,却不能替代服务端的权限检查和安全校验。凡是涉及账户权限、费用、库存、隐私或其他重要数据,都不能只依赖浏览器提交的结果。

二、准备运行环境

开始只需要一个现代浏览器和文本编辑器。新建一个文本文件,将扩展名保存为 .html,再用浏览器打开即可。下面这段代码会在开发者工具的控制台输出一行文本:

<!doctype html>
<html lang="zh-CN">
<meta charset="utf-8">
<title>JavaScript 起步</title>
<script>
  console.log("你好,JavaScript");
</script>
<h1>打开开发者工具查看控制台</h1>
</html>

浏览器开发者工具通常可以通过菜单打开,也可以使用常见快捷键。控制台适合查看调试信息和错误提示,但不应把它当成页面的正式输出区域。页面内容应通过 HTML 和 DOM 来显示。

也可以将 JavaScript 放进单独的 .js 文件,再由 HTML 引入。为了让浏览器先解析页面结构、随后再执行脚本,可以使用 defer:

<script src="app.js" defer></script>

这里的 src 指向外部脚本文件。使用 defer 的外部脚本会在 HTML 解析完成后执行,并按文档顺序执行。入门示例也可以直接把脚本放在页面结构后面;稍后的完整示例会采用这种写法。

三、变量:保存程序需要的数据

变量可以理解为一个有名字的存储位置。JavaScript 使用 let 和 const 声明变量:

let userName = "小林";
userName = "阿宁";

const greeting = "你好";
console.log(userName, greeting);

let 声明的变量可以重新赋值,适用于之后需要变化的数据;const 声明后不能重新赋值,适用于变量绑定不打算改变的情况。上例中 userName 改成了另一个字符串,而 greeting 不能再被赋予另一个值。

需要注意,const 限制的是变量绑定,不能据此认为对象内容也被冻结了:

const settings = { theme: "light" };
settings.theme = "dark"; // 可以修改对象的属性

// settings = {}; // 不可以:不能重新给 const 变量赋值

初学时一般优先使用 const;确定需要重新赋值时再使用 let。过去常见的 var 具有不同的作用域和声明行为,新代码通常不需要用它入门。理解旧项目时可能会遇到 var,但不要把三者当作完全等价的写法。

变量名应能表达用途,例如 itemCount 比 x 更容易理解。JavaScript 区分大小写,userName 和 username 是两个不同的名字。变量名不能以数字开头,也不能使用语言保留字作为普通标识符。多个单词常采用小驼峰命名法:firstName、totalPrice。

四、常见数据类型与运算

入门时经常遇到的类型包括字符串、数字、布尔值、null、undefined、对象和数组:

const title = "本周阅读";       // 字符串
const pageCount = 12;           // 数字
const isFinished = false;       // 布尔值
const selectedItem = null;      // 有意表示“当前没有值”
let notAssigned;                // 值为 undefined
const colors = ["蓝色", "绿色"]; // 数组
const user = { name: "小林" };   // 对象

JavaScript 的普通数字类型是 Number,既可表示整数,也可表示小数。不能把“看起来像数字”的字符串直接当成数字使用。用户通过输入框提交的内容通常是字符串,即使输入框写着 type="number",从 DOM 读取的 value 仍是字符串,需要明确转换和检查。

const rawValue = "18";
const value = Number(rawValue);

console.log(value + 2); // 20

转换并不保证成功。比如 Number("abc") 会得到 NaN,它表示“不是一个有效数字结果”。可以用 Number.isFinite() 检查是否为有限数字:

const value = Number("abc");

if (Number.isFinite(value)) {
  console.log("可以参与数字计算");
} else {
  console.log("请输入有效数字");
}

加号对字符串有特殊行为:只要一侧参与字符串拼接,结果就可能是字符串,而不是算术加法。

console.log(2 + 3);      // 5
console.log("2" + 3);    // "23"
console.log(Number("2") + 3); // 5

使用 === 做严格相等比较,通常比 == 更容易推断结果。严格相等不会先把不同类型的值强制转换成相同类型:

console.log(5 === 5);   // true
console.log(5 === "5"); // false

布尔值常用于条件判断。if 会根据条件执行不同分支:

const score = 76;

if (score >= 60) {
  console.log("通过");
} else {
  console.log("继续练习");
}

也可以使用 else if 表达多个条件。判断条件时要明确边界:例如分数是否允许等于 60、空字符串算不算有效输入,都应由需求决定,而不是靠猜测。

五、函数:把一段行为组织起来

函数是可以按名称调用的一段代码。它可以接收参数,也可以通过 return 返回结果:

function add(firstNumber, secondNumber) {
  return firstNumber + secondNumber;
}

const result = add(4, 7);
console.log(result); // 11

firstNumber 和 secondNumber 是参数,调用时传入的 4 和 7 是实参。参数名只是函数内部的变量名,不会自动验证传入值的类型或范围。如果需要输入必须为数字、必须大于零或不能超过某个上限,就应在函数或调用它的流程中明确检查。

function addFiniteNumbers(firstNumber, secondNumber) {
  if (
    !Number.isFinite(firstNumber) ||
    !Number.isFinite(secondNumber)
  ) {
    throw new TypeError("参数必须是有限数字");
  }

  return firstNumber + secondNumber;
}

console.log(addFiniteNumbers(4, 7)); // 11

这段函数检查了类型和值是否能作为有限数字参与计算,但没有限定业务范围。例如它仍允许负数。如果业务要求两个数字都不能小于零,就要另加范围判断。错误提示和限制规则应与实际需求一致,不存在适用于所有函数的统一参数上限。

函数也可以定义为函数表达式或箭头函数:

const multiply = function (firstNumber, secondNumber) {
  return firstNumber * secondNumber;
};

const square = number => number * number;

console.log(multiply(3, 4)); // 12
console.log(square(5));      // 25

单参数箭头函数可以省略参数括号,只有一个表达式时也可以省略花括号和 return。刚开始练习时,优先选择可读性清晰的写法,不必为了代码短而把多步逻辑压缩到一行。

使用 return 后,函数会结束并返回结果。如果函数没有执行到有效的 return,返回值是 undefined。不要把“在函数里调用 console.log()”误认为“函数返回了这个值”:记录信息和返回结果是两件不同的事。

六、浏览器里的 DOM 与事件

DOM 是浏览器把 HTML 页面表示成可操作对象的接口。JavaScript 可以通过选择器找到页面元素,再更改文本或属性:

const heading = document.querySelector("h1");
heading.textContent = "标题已经更新";

document.querySelector() 会返回匹配到的第一个元素;找不到时会返回 null。如果脚本执行时页面结构尚未创建,选择器也可能找不到目标元素。因此要保证脚本在相关 HTML 之后运行,或使用 defer、DOMContentLoaded 等方式安排执行时机。

事件表示用户或浏览器发生了某个动作,例如点击、输入或提交表单。使用 addEventListener() 注册事件处理函数,比把行为直接写成 HTML 属性更方便组织代码:

const button = document.querySelector("#hello-button");

button.addEventListener("click", function () {
  console.log("按钮被点击");
});

表单提交事件是实现交互页面的常用入口。浏览器默认会提交表单并可能刷新页面;如果要用 JavaScript 在当前页面处理,可以在事件处理函数中调用 event.preventDefault()。这只会阻止此次浏览器默认提交行为,不会自动完成数据保存或安全校验。

七、制作第一个交互页面

下面的示例允许用户输入称呼,提交后在页面上显示问候语,也可以点击按钮增加计数。请将整段代码保存为 index.html,再用浏览器打开。页面包含完整的 HTML、样式和 JavaScript,不依赖外部资源。

<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>我的第一个交互页面</title>
  <style>
    body {
      max-width: 640px;
      margin: 40px auto;
      padding: 0 16px;
      font-family: sans-serif;
      line-height: 1.6;
    }

    label, input, button {
      font: inherit;
    }

    input {
      padding: 6px;
    }

    button {
      margin: 6px 4px 6px 0;
      padding: 6px 10px;
      cursor: pointer;
    }

    .message {
      min-height: 1.6em;
    }
  </style>
</head>
<body>
  <main>
    <h1>我的第一个交互页面</h1>

    <form id="greeting-form">
      <label for="name-input">你的称呼:</label>
      <input
        id="name-input"
        name="name"
        type="text"
        maxlength="40"
        autocomplete="name"
      >
      <button type="submit">显示问候</button>
    </form>

    <p id="greeting" class="message" aria-live="polite"></p>

    <section aria-labelledby="counter-title">
      <h2 id="counter-title">点击计数器</h2>
      <p>当前计数:<output id="count">0</output></p>
      <button id="increase-button" type="button">增加一次</button>
      <button id="reset-button" type="button">归零</button>
    </section>
  </main>

  <script>
    const form = document.querySelector("#greeting-form");
    const nameInput = document.querySelector("#name-input");
    const greeting = document.querySelector("#greeting");
    const countOutput = document.querySelector("#count");
    const increaseButton = document.querySelector("#increase-button");
    const resetButton = document.querySelector("#reset-button");

    let count = 0;

    function makeGreeting(name) {
      return `你好,${name}!欢迎来到这个页面。`;
    }

    function renderCount() {
      countOutput.textContent = String(count);
    }

    form.addEventListener("submit", function (event) {
      event.preventDefault();

      const name = nameInput.value.trim();

      if (name === "") {
        greeting.textContent = "请先输入一个称呼。";
        nameInput.focus();
        return;
      }

      greeting.textContent = makeGreeting(name);
    });

    increaseButton.addEventListener("click", function () {
      count = count + 1;
      renderCount();
    });

    resetButton.addEventListener("click", function () {
      count = 0;
      renderCount();
    });
  </script>
</body>
</html>

八、逐步理解页面代码

1. 用 id 找到页面元素

脚本开头通过 document.querySelector() 找到表单、输入框、提示区域和两个按钮。选择器前的 # 表示按 id 查找,例如 #name-input 对应 HTML 中的 id="name-input"。

这些元素都写在脚本之前,所以脚本运行时它们已经存在。若把脚本移到文档的 <head> 中直接运行,选择器可能先于页面元素执行,得到 null。这时需要使用外部脚本的 defer,或等页面解析完成后再注册事件。

2. 函数把逻辑拆分成可复用的部分

makeGreeting(name) 接收一个称呼,并返回问候文本。反引号包围的字符串叫模板字符串,${name} 会插入变量值。renderCount() 则负责把当前计数写进页面。把“生成问候语”和“更新计数显示”分别放进函数,可以让事件处理代码更容易阅读。

3. 表单事件负责读取和处理输入

提交表单时,处理函数先阻止默认提交,再读取 nameInput.value。输入值是字符串,trim() 会去除字符串开头和结尾的空白。若结果为空,页面显示提示并把焦点移回输入框;否则调用函数生成问候语。

HTML 中的 maxlength="40" 是浏览器端的输入长度限制,适合改善交互体验,但不能当成安全边界。用户可以绕过页面控件,直接构造请求;如果数据会提交到服务器,服务端仍须按业务要求重新验证长度和内容。还要注意,不同语言和字符的编码方式会影响“长度”的含义,不能把一个简单的长度数字当作所有系统都一致的字符计数规则。

4. 计数器使用 let 保存变化的数据

count 会随着点击改变,因此声明为 let。每次点击增加按钮,程序执行 count = count + 1,再调用 renderCount() 更新页面。归零按钮则将变量重新赋值为 0。

这个计数器只保存在当前页面运行期间的内存中。刷新页面后,变量会重新初始化为 0。若要在刷新后保留数据,需要考虑浏览器存储或服务器存储;不同存储方式有各自的数据容量、隐私和安全边界,不能只为了“记住数据”就把敏感信息放进浏览器存储。

九、输出内容时的安全边界

示例使用 textContent 将问候语写入页面。这会把输入作为普通文本显示,不会把其中的内容当成 HTML 标签解析。对于用户输入、接口返回值等不可信文本,默认应选择 textContent,而不是直接拼接到 innerHTML 中。

例如,如果把用户输入写成下面这样,浏览器会尝试把字符串当作 HTML 解析:

// 不要把不可信输入直接插入 innerHTML
greeting.innerHTML = nameInput.value;

当输入中包含 HTML 片段或脚本相关内容时,未经恰当处理的 HTML 插入可能造成跨站脚本攻击(XSS)。实际能否触发、造成什么影响,取决于具体上下文、浏览器行为和页面环境,但直接把不可信字符串当 HTML 处理本身就是危险做法。若产品确实需要展示经过整理的富文本,应采用经过审查的 HTML 清理方案,并根据使用场景进行安全设计,不能仅靠字符串替换几个字符来保证安全。

textContent 可以避免把文本解析为 HTML,但它不能替代所有安全措施。例如,把字符串放进 URL、CSS、脚本代码或 HTML 属性时,各种上下文的规则不同。不要将用户输入拼接进可执行代码,也不要把客户端校验或隐藏按钮当作访问控制。涉及权限和数据完整性的判断必须在可信的服务端完成。

十、常见错误与排查方法

1. 变量名或大小写写错

JavaScript 区分大小写。声明的是 countOutput,后面却写成 countoutput,浏览器会认为它们是不同的标识符。出现“未定义”一类错误时,先检查名称拼写、大小写和变量是否在当前作用域内。

2. 选择器没有匹配到元素

如果 document.querySelector() 返回 null,后续读取它的属性或注册事件就会报错。检查 HTML 中的 id 是否与选择器一致,以及脚本是否在元素创建后运行。开发过程中也可以在控制台临时输出变量,确认选择器结果。

3. 把字符串当数字计算

表单控件的 value 是字符串。若要进行数值运算,应先解析并验证,而不是假定浏览器已替你完成转换。对于用户输入,可以检查空值、Number.isFinite() 和业务允许的范围。转换成功只说明它能得到有限数字,不代表它符合某项业务规则。

4. 忘记处理空输入或边界值

示例中对空称呼做了处理,但还没有制定更复杂的业务规则,例如允许哪些字符、最大长度如何计算、是否允许只有标点符号等。规则应由产品需求决定。若这些数据将送往服务端,前端验证只是即时反馈,服务端还需要按相同的业务约束验证。

5. 按钮意外提交表单

放在表单里的按钮如果没有指定类型,可能会按提交按钮处理。示例给计数器按钮设置了 type="button",避免点击时意外提交表单;用于提交的按钮则明确使用 type="submit"。这是避免表单交互出现意外刷新的简单做法。

6. 认为错误会自动显示在页面上

语法错误或运行时错误通常会出现在浏览器开发者工具的控制台中,不会自动变成用户看得到的提示。遇到页面无反应时,先检查控制台,再检查事件是否绑定、目标元素是否存在,以及处理函数是否执行。调试时可以暂时使用 console.log(),确认关键变量的值;发布前再清理不必要的调试输出。

十一、关于输入限制和校验

JavaScript 本身并没有一个适用于所有变量或函数参数的固定“字符长度上限”或“数值范围”。限制取决于业务规则、运行环境、数据类型、存储和接口设计。示例中的 maxlength="40" 只是一个演示用的 HTML 输入限制,不代表所有场景都应该使用 40,也不代表绕过它就不可能提交更长内容。

如果需要限定数字范围,可以明确写出下限和上限。例如只接受 1 到 100 的整数:

function isValidScore(value) {
  return Number.isInteger(value) && value >= 1 && value <= 100;
}

console.log(isValidScore(80));   // true
console.log(isValidScore(100.5)); // false
console.log(isValidScore(0));     // false

这个函数定义了一个具体规则:值必须是整数,且包含在 1 到 100 之间。边界是否包含在内由 >= 和 <= 决定。换成成绩、年龄、金额或数量时,应该根据真实业务调整类型、边界和错误处理,而不是照搬示例数字。

在用户界面上尽早指出输入问题,有助于减少误操作;在服务端再次验证,则是保护数据与业务规则的重要步骤。两者目的不同,不能互相替代。服务端还应根据身份和权限检查请求,而不能相信浏览器声称的用户身份或操作资格。

十二、练习与下一步

完成页面后,可以按顺序做几项小练习:修改问候文本;新增一个按钮,在点击时把计数减少一次;为计数器设定清楚的下限;将页面提示改成不同的错误信息;把脚本移入单独的 app.js 文件并使用 defer 引入。每次只修改一个功能,观察结果并检查控制台,比较容易定位问题。

接下来可以学习数组和循环,用于处理一组数据;学习对象,组织相关属性;学习异步操作和 fetch(),了解浏览器如何请求服务器;再逐步接触模块、测试与常用开发工具。学习时要区分语言能力、浏览器接口和项目框架:先理解数据如何变化、事件如何触发、输入如何校验,再学框架会更容易判断它替你解决了什么问题。

总结

JavaScript 入门的核心并不是记住许多语法,而是能把几个基本概念连起来:用变量保存状态,用函数组织行为,用条件判断处理不同情况,通过 DOM 读取和更新页面,再用事件响应用户操作。本文的问候页面和计数器展示了这条最小路径。

编写交互时要明确输入是什么类型、边界规则是什么、页面元素何时可用;显示不可信文本时优先使用 textContent;涉及权限、重要数据或安全判断时,不要只依赖浏览器代码。掌握这些基础习惯后,再逐步扩展功能,就能在理解每一步的前提下完成更复杂的网页程序。

© 版权声明

相关文章