第一个JavaScript程序

在HTML中使用JavaScript

JavaScript最常见的使用方式是在HTML页面中嵌入代码。有三种方式可以在HTML中使用JavaScript。

内联JavaScript

直接在HTML标签的事件属性中编写JavaScript代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>内联JavaScript示例</title>
</head>
<body>
    <button onclick="alert('你好,东巴文!')">点击我</button>
    <input type="text" onfocus="this.style.backgroundColor='yellow'" onblur="this.style.backgroundColor='white'">
</body>
</html>

东巴文提醒:内联方式适合简单的交互,但不推荐在大型项目中使用,因为代码难以维护。

内部JavaScript

使用<script>标签在HTML中嵌入JavaScript代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>内部JavaScript示例</title>
    <script>
        function sayHello() {
            alert("你好,欢迎来到东巴文!");
        }
        
        function changeColor() {
            document.body.style.backgroundColor = 
                document.body.style.backgroundColor === "lightblue" ? "white" : "lightblue";
        }
    </script>
</head>
<body>
    <h1>内部JavaScript示例</h1>
    <button onclick="sayHello()">问好</button>
    <button onclick="changeColor()">切换背景色</button>
</body>
</html>

东巴文点评:内部JavaScript适合单页面或代码量较小的情况,便于快速开发和测试。

外部JavaScript文件

将JavaScript代码放在独立的.js文件中,然后在HTML中引用:

script.js文件

function sayHello() {
    alert("你好,欢迎来到东巴文!");
}

function changeColor() {
    document.body.style.backgroundColor = 
        document.body.style.backgroundColor === "lightblue" ? "white" : "lightblue";
}

console.log("外部JavaScript文件已加载");

index.html文件

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>外部JavaScript示例</title>
    <script src="script.js"></script>
</head>
<body>
    <h1>外部JavaScript示例</h1>
    <button onclick="sayHello()">问好</button>
    <button onclick="changeColor()">切换背景色</button>
</body>
</html>

东巴文推荐:外部JavaScript文件是最佳实践,便于代码复用、维护和缓存。

外部JavaScript文件

为什么使用外部文件?

优点 说明 东巴文评价
代码分离 HTML、CSS、JavaScript各司其职 ✅ 结构清晰
代码复用 同一JS文件可被多个页面引用 ✅ 减少重复
易于维护 修改JS不需要改HTML文件 ✅ 降低耦合
浏览器缓存 外部文件会被浏览器缓存 ✅ 加快加载
团队协作 前端工程师可以独立工作 ✅ 提高效率

文件组织结构

推荐的项目目录结构:

my-project/
├── index.html
├── css/
│   └── style.css
├── js/
│   ├── main.js
│   └── utils.js
└── images/
    └── logo.png

引用路径

<!-- 相对路径 -->
<script src="js/main.js"></script>
<script src="./js/main.js"></script>

<!-- 绝对路径(从网站根目录开始) -->
<script src="/js/main.js"></script>

<!-- 完整URL -->
<script src="https://cdn.example.com/library.js"></script>

东巴文提示:推荐使用相对路径,便于项目迁移。

script标签属性

src属性

指定外部JavaScript文件的路径:

<script src="js/main.js"></script>

type属性

指定脚本的MIME类型:

<!-- 传统写法 -->
<script type="text/javascript">
    console.log("Hello");
</script>

<!-- ES6模块 -->
<script type="module">
    import { greet } from './utils.js';
    greet();
</script>

async属性

异步加载脚本,加载完成后立即执行:

<script async src="analytics.js"></script>

执行顺序:不保证按声明顺序执行

适用场景:独立的第三方脚本,如统计代码、广告代码

defer属性

异步加载脚本,HTML解析完成后按顺序执行:

<script defer src="main.js"></script>
<script defer src="utils.js"></script>

执行顺序:按声明顺序执行

适用场景:需要操作DOM的脚本

async vs defer

无属性:    HTML解析 → [暂停] → JS下载 → JS执行 → [继续]HTML解析
async:    HTML解析 → [并行JS下载] → [暂停]JS执行 → [继续]HTML解析
defer:    HTML解析 → [并行JS下载] → [完成后]JS执行
属性 加载方式 执行时机 执行顺序 东巴文推荐
阻塞 立即 按声明 ❌ 放在body末尾
async 异步 加载后立即 不保证 第三方脚本
defer 异步 HTML解析后 按声明 ✅ 推荐使用

最佳实践

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>script标签最佳实践</title>
    
    <!-- defer推荐放在head中 -->
    <script defer src="js/main.js"></script>
    
    <!-- async用于独立脚本 -->
    <script async src="https://www.googletagmanager.com/gtag/js"></script>
</head>
<body>
    <h1>页面内容</h1>
    
    <!-- 传统方式:放在body末尾 -->
    <script src="js/legacy.js"></script>
</body>
</html>

JavaScript执行顺序

基本执行顺序

JavaScript代码按照在HTML中出现的顺序执行:

<script>
    console.log("第一个脚本");
</script>
<script>
    console.log("第二个脚本");
</script>
<script>
    console.log("第三个脚本");
</script>
<!-- 输出顺序:第一个脚本 → 第二个脚本 → 第三个脚本 -->

DOM加载时机

<script>
    // 此时DOM还未加载完成
    console.log(document.getElementById("myDiv"));  // null
</script>

<script defer>
    // defer脚本在DOM加载完成后执行
    console.log(document.getElementById("myDiv"));  // <div id="myDiv">
</script>

<div id="myDiv">内容</div>

<script>
    // 放在元素后面,可以访问到元素
    console.log(document.getElementById("myDiv"));  // <div id="myDiv">
</script>

DOMContentLoaded事件

在DOM加载完成后执行代码:

document.addEventListener("DOMContentLoaded", function() {
    console.log("DOM已加载完成");
    // 在这里操作DOM是安全的
    const element = document.getElementById("myDiv");
    element.style.color = "red";
});

load事件

在页面所有资源(图片、样式等)加载完成后执行:

window.addEventListener("load", function() {
    console.log("页面所有资源已加载完成");
    // 图片等资源已经加载完成,可以获取尺寸
    const img = document.getElementById("myImage");
    console.log(img.width, img.height);
});

执行时机对比

事件/时机 触发条件 东巴文说明
脚本位置 解析到脚本时 阻塞HTML解析
defer DOM解析完成后 按顺序执行
async 脚本加载完成后 不保证顺序
DOMContentLoaded DOM构建完成 不等待图片
load 所有资源加载完成 包括图片

使用console输出

console对象提供了多种输出方法,是调试JavaScript的重要工具。

基本输出

console.log("普通日志");
console.info("信息日志");
console.warn("警告日志");
console.error("错误日志");

格式化输出

// 字符串格式化
console.log("你好,%s!", "东巴文");

// 整数格式化
console.log("数字:%d", 42);

// 浮点数格式化
console.log("浮点数:%f", 3.14159);

// 对象格式化
const user = { name: "东巴文", age: 1 };
console.log("用户:%o", user);

表格输出

const users = [
    { name: "张三", age: 25, city: "北京" },
    { name: "李四", age: 30, city: "上海" },
    { name: "王五", age: 28, city: "广州" }
];
console.table(users);

分组输出

console.group("用户信息");
console.log("姓名:东巴文");
console.log("年龄:1");
console.group("详细信息");
console.log("职业:程序员");
console.log("爱好:编程");
console.groupEnd();
console.groupEnd();

计时

console.time("数组操作");
const arr = [];
for (let i = 0; i < 100000; i++) {
    arr.push(i);
}
console.timeEnd("数组操作");  // 数组操作: 5.234ms

断言

const value = 10;
console.assert(value === 5, "value不等于5");  // 输出错误信息
console.assert(value === 10, "value不等于10");  // 不输出

清空控制台

console.clear();

代码注释

注释是代码中不被执行的部分,用于解释代码的作用。

单行注释

使用//开始,到行尾结束:

// 这是一个单行注释
console.log("Hello");  // 这也是单行注释

// 计算两个数的和
function add(a, b) {
    return a + b;  // 返回结果
}

多行注释

使用/* */包围:

/*
 * 这是一个多行注释
 * 可以跨越多行
 * 用于详细说明
 */
function calculateArea(width, height) {
    return width * height;
}

/* 也可以写成一行 */
const PI = 3.14159;

文档注释(JSDoc)

使用/** */格式,用于生成文档:

/**
 * 计算两个数的和
 * @param {number} a - 第一个数
 * @param {number} b - 第二个数
 * @returns {number} 两个数的和
 * @example
 * add(1, 2)  // 返回 3
 */
function add(a, b) {
    return a + b;
}

/**
 * 用户对象
 * @typedef {Object} User
 * @property {string} name - 用户名
 * @property {number} age - 年龄
 */

/**
 * 创建用户
 * @param {string} name - 用户名
 * @param {number} age - 年龄
 * @returns {User} 用户对象
 */
function createUser(name, age) {
    return { name, age };
}

注释的最佳实践

好的注释

// 计算斐波那契数列的第n项(使用动态规划优化)
function fibonacci(n) {
    if (n <= 1) return n;
    
    let prev = 0, curr = 1;
    for (let i = 2; i <= n; i++) {
        [prev, curr] = [curr, prev + curr];
    }
    return curr;
}

不好的注释

// i加1
i++;

// 返回a加b
function add(a, b) {
    return a + b;
}

东巴文原则:注释应该解释"为什么"而不是"是什么"。代码本身应该足够清晰,让人能看懂"是什么"。

第一个完整示例

让我们把学到的知识综合起来,创建一个完整的示例:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>第一个JavaScript程序 - 东巴文</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 50px auto;
            padding: 20px;
        }
        .result {
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 5px;
            min-height: 50px;
        }
        button {
            padding: 10px 20px;
            margin: 5px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <h1>第一个JavaScript程序</h1>
    <p>欢迎来到东巴文学习JavaScript!</p>
    
    <div>
        <button onclick="sayHello()">问好</button>
        <button onclick="showTime()">显示时间</button>
        <button onclick="changeColor()">切换颜色</button>
        <button onclick="calculate()">计算</button>
    </div>
    
    <div id="result" class="result">结果将显示在这里...</div>
    
    <script>
        console.log("JavaScript程序已加载");
        
        function sayHello() {
            const result = document.getElementById("result");
            result.innerHTML = "<strong>你好,欢迎来到东巴文!</strong>";
            result.style.color = "green";
        }
        
        function showTime() {
            const now = new Date();
            const result = document.getElementById("result");
            result.innerHTML = "当前时间:" + now.toLocaleString();
            result.style.color = "blue";
        }
        
        function changeColor() {
            const colors = ["red", "green", "blue", "orange", "purple"];
            const randomColor = colors[Math.floor(Math.random() * colors.length)];
            document.body.style.backgroundColor = randomColor;
            document.getElementById("result").innerHTML = "背景颜色已切换为:" + randomColor;
        }
        
        function calculate() {
            const a = 10;
            const b = 20;
            const sum = a + b;
            document.getElementById("result").innerHTML = 
                `${a} + ${b} = ${sum}`;
        }
    </script>
</body>
</html>

东巴文点评:这个示例展示了JavaScript的基本用法:DOM操作、事件处理、变量、函数等。我们将在后续章节详细学习这些概念。

下一步

恭喜你完成了第一个JavaScript程序!接下来让我们深入学习:

  1. 基本语法 - 学习语法规则
  2. 数据类型概述 - 了解数据类型
  3. 原始类型 - 深入学习原始类型

东巴文(db-w.cn) - 让编程学习更简单

🎉 东巴文寄语:第一个程序是每个程序员的里程碑。从这行代码开始,你已经踏上了JavaScript学习之旅。在 db-w.cn,我们将陪你一起成长!