XYCOVO CONSOLE KURISU · WEB 渗透 / AI 辅助攻防 ONLINE
#038 · 2024-01-25✓ PASS

JavaScript 基础

JavaScript 零基础入门教程:从发展历史、变量与数据类型、运算符与流程控制到函数与 DOM 操作,搭配丰富的代码示例。
javascript前端web开发编程AUTHOR: KURISU

JavaScript 诞生于 1995 年,最初目的是验证表单输入。经过三十年的发展,已从简单的表单校验语言演变成为一门强大的通用编程语言,支撑着整个现代 Web 开发生态。


一、JavaScript 发展历史

1.1 诞生背景(1995 年)

在 JavaScript 问世之前,表单验证必须通过服务器端完成。当时还是电话拨号上网的年代,每次表单提交都要经历漫长的等待。Netscape(网景)公司的 Brendan Eich 着手开发了一种名为 LiveScript 的客户端脚本语言。在 Netscape Navigator 2.0 发布前夕,为借助当时 Java 的热度,将其更名为 JavaScript

1.2 标准化历程

年份事件
1995Brendan Eich 在 Netscape 创建 LiveScript → JavaScript
1996微软推出 JScript(IE 3.0),三方并存
1997ECMA-262 标准发布,定名 ECMAScript
1999ECMAScript 3 发布(最广泛使用的版本)
2009ES5 发布(严格模式、JSON 支持等)
2015ES6/ES2015 发布(let/const、箭头函数、class 等)

1.3 什么是 JavaScript

JavaScript 是一门面向对象的、弱数据类型的、解释性的、动态的脚本语言。它具有以下特点:

  • 脚本语言,语法相对宽松
  • 解释执行(不需要编译成二进制)
  • 可以对网页元素动态编程
  • 弱数据类型语言
  • 面向对象编程语言

1.4 JavaScript 的三大主要作用

  • 数据校验(JS 为此诞生)
  • 网页特效(目前最主要的使用场景)
  • 数据交互(Ajax 技术)

二、开发环境与第一个程序

2.1 开发环境

推荐使用 VS Code、Sublime Text 等编辑器,或 Hbuilder、WebStorm 等 IDE。运行环境使用 Chrome 浏览器。

2.2 Hello World

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        alert("hello world");
        document.write("nihao");
    </script>
</body>
</html>

2.3 JavaScript 的三种书写方式

行内 JS:使用 HTML 标签的 onxxx 事件属性。

<button onclick="alert('你点我干嘛?')">点一下试试</button>

页面内嵌 JS:写在 <script> 标签中。

<script>
    alert('hello JavaScript');
</script>

基于性能优化原则,建议将 <script> 写在 <body> 标签的最后。

外联 JS 文件:W3C 三层分离原则——结构层(HTML)、表示层(CSS)、行为层(JS)。

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

2.4 三种对话框

// 警告框——展示信息,只有一个确定按钮
alert('hello JavaScript!');

// 确认框——返回 true(确认)或 false(取消)
var isDelete = confirm("您确定要删除吗?");
if (isDelete) {
    alert("数据已删除");
}

// 输入框——接收用户输入,返回字符串
var age = prompt("请输入您的年龄:", "20");
alert("您今年是" + age + "岁了");

三、变量与数据类型

3.1 变量定义

// 传统方式(var)
var age = 10;
var gender;          // 先声明
gender = "";       // 后赋值

// ES6 推荐方式
let name = "刘建宏";      // let 定义变量(推荐)
const VERSION = "1.0";   // const 定义常量(不可修改)

直接 变量名 = 值(不带 var/let/const)定义的是全局变量,作用域过大,禁止使用。

3.2 变量命名规范

  • 只能由大小写字母、数字、下划线 _$ 组成
  • 不能以数字开头
  • 不能使用关键字或保留字
  • 使用有意义的名称,遵循小驼峰法(如 userNameclassRoom

3.3 常量

const PI = 3.14159;
const VERSION = "1.0";

// 以下会报错:常量不允许修改
VERSION = "2.0";  // TypeError

3.4 数据类型

JavaScript 提供两大类数据类型:

基本数据类型

类型说明示例
Number整数和浮点数10, 3.14, NaN
String被引号包围的字符"hello", 'world'
Boolean逻辑值true, false
null空值(表示不存在)null
undefined未定义undefined

引用数据类型

类型说明
Array数组
Object对象(万物皆对象)
Function函数对象

3.5 弱数据类型特性

JavaScript 是弱数据类型语言,变量的类型由值的类型决定:

var a = 10;           // number
console.log(typeof a);

a = 5.6;              // number
a = "帅哥刘";          // string

3.6 类型转换

// 强制类型转换
var age = prompt("请输入您的年龄:", "20");
age = parseInt(age);       // 字符串转整数
price = parseFloat("19.99"); // 字符串转浮点数

// parseInt/parseFloat 会尽可能尝试转换,直到不成功为止
parseInt("20px");   // 20(去掉单位)
parseFloat("3.14cm"); // 3.14

四、运算符与表达式

4.1 算术运算符

var num1 = 50;
var num2 = 5;

console.log(num1 + num2);   // 55  加法
console.log(num1 - num2);   // 45  减法
console.log(num1 * num2);   // 250 乘法
console.log(num1 / num2);   // 10  除法
console.log(num1 % num2);   // 0   求余(求模)
console.log(num1 ** num2);  // 幂次方

注意:如果有字符串参与,+ 号会进行字符串拼接。

4.2 比较运算符

var age = 20;

if (age == 20)   { /* 等于(值相等) */ }
if (age != 20)   { /* 不等于 */ }
if (age > 18)    { /* 大于 */ }
if (age < 60)    { /* 小于 */ }
if (age >= 18)   { /* 大于等于 */ }
if (age <= 60)   { /* 小于等于 */ }
if (age === 20)  { /* 全等于(值和类型都相等) */ }
if (age !== "20"){ /* 不全等于 */ }

4.3 逻辑运算符

// 与(&&):所有条件都成立才为 true
if (age > 18 && age < 60) {
    alert("成年了");
}

// 或(||):任一条件成立即为 true
if (age > 60 || age < 18) {
    alert("身体不合格");
}

// 非(!):取反
if (!(age > 6)) {
    alert("年龄太小");
}

双写的 &&|| 具有短路效应,效率更高。

4.4 赋值运算符

表达式等价于结果
a += 10a = a + 10a 的值加 10
a -= 10a = a - 10a 的值减 10
a *= 10a = a * 10a 的值乘 10
a /= 10a = a / 10a 的值除 10
a **= 10a = a ** 10a 的 10 次幂

4.5 自加自减运算符

var a = 20;
var b = a++;    // a=21, b=20  (先赋值再自增)
var d = ++b;    // b=21, d=21  (先自增再赋值)
var e = d--;    // d=20, e=21  (先赋值再自减)
var f = --e;    // e=20, f=20  (先自减再赋值)

4.6 三目运算符

// 变量 = 表达式 ? 值1 : 值2;
var a = 100;
var b = 30;
var c = a > b ? 100 : 1000;  // c = 100

三目运算符是 if...else 的简写形式。


五、流程控制

5.1 选择结构

单分支

if (age > 18) {
    alert("恭喜您,已经成年了");
}

双分支

if (age >= 18) {
    alert("恭喜您,已经成年了");
} else {
    alert("对不起,没有成年");
}

多分支

if (age < 10) {
    alert("赶紧回家喝奶去");
} else if (age < 18) {
    alert("骚年加油吧");
} else if (age < 30) {
    alert("兄弟,奋斗吧");
} else if (age < 60) {
    alert("大叔,厉害了");
} else {
    alert("不要放弃,坚持吃药");
}

switch 语句

var week = prompt("请输入星期几:");
switch(week) {
    case "1":
        alert("今天星期一");
        break;
    case "2":
        alert("今天星期二");
        break;
    default:
        alert("输入错误");
        break;
}

break 语句用于终止 switch,不写则会发生”穿透”。

5.2 循环结构

for 循环

for (var i = 0; i < 100; i++) {
    console.log(i);
}

while 循环

var i = 0;
while (i < 100) {
    console.log(i);
    i++;
}

do…while 循环

var i = 0;
do {
    console.log(i);
    i++;
} while (i < 100);

do…while 至少执行一次循环体。

break 与 continue

// break:终止循环
for (var i = 0; i < 100; i++) {
    if (i == 50) break;
    console.log(i);
}

// continue:跳过本次迭代
for (var i = 0; i < 100; i++) {
    if (i == 50) continue;
    console.log(i);
}

for…in 与 for…of

// for...in — 迭代数组(返回下标)或对象(返回属性名)
var arr = [1, 3, 5, 6, 7];
for (var i in arr) {
    console.log(arr[i]);
}

// for...of — ES6 新增,迭代可迭代对象的值
for (var val of arr) {
    console.log(val);
}

六、函数

6.1 函数定义与调用

// 定义函数
function functionName([参数列表]) {
    // 函数体
    [return 返回值;]
}

// 调用函数
functionName(参数);

示例

// 无参数无返回值
function showInfo() {
    alert("大家好,我叫刘帅哥");
}
showInfo();

// 有参数
function say(msg) {
    alert("您说了一句===>" + msg);
}
say("刘建宏是个大帅锅");

// 有返回值
function sum(a, b) {
    return a + b;
}
var result = sum(5, 8);  // result = 13

6.2 函数提升(Hoisting)

JavaScript 中函数可以在定义之前调用,这是因为浏览器在解析 JS 文件时会先找到函数声明并在执行剩余语句之前设置好函数。

myFunc(5);  // 可以调用

function myFunc(x) {
    return x + 5;
}

6.3 函数分类

按参数有无:有参函数 / 无参函数 按返回值有无:有返回值函数 / 无返回值函数 按定义者:系统函数(如 parseInt)/ 自定义函数

6.4 箭头函数(ES6 Lambda 表达式)

// 无参数
var fn = () => alert("hello");

// 单参数(单行,隐式返回)
let double = x => x * 2;

// 多参数
let add = (x, y) => x + y;

// 多行代码需要 {}
let calc = (x, y) => {
    let z = 5;
    return (x + y) * z;
};

6.5 匿名函数

// 匿名函数赋给变量
var b = function() {
    alert("匿名函数");
};
b();

// 匿名函数作为参数
setTimeout(function() {
    alert("延迟执行");
}, 1000);

6.6 默认值参数

function getCircleArea(r, PI = 3.14) {
    return PI * r * r;
}

alert(getCircleArea(5));     // 78.5(使用默认 PI)
alert(getCircleArea(5, 3));  // 75

默认值参数必须在普通参数后面定义。

6.7 arguments 对象

function test() {
    console.log(arguments.length);   // 参数个数
    console.log(arguments[0]);       // 第一个参数
    console.log(arguments[1]);       // 第二个参数
}

test("hello", 123, true);

arguments 可用于模拟函数重载。

6.8 递归

// 求 1 到 n 的和
function sum(n) {
    if (n <= 1) return 1;       // 必须有结束条件
    return n + sum(n - 1);
}

alert(sum(100));  // 5050

6.9 闭包

闭包是一个能访问其他函数作用域中变量的函数。

function outer() {
    var a = '变量1';
    var inner = function() {
        console.log(a);  // 访问 outer 函数中的变量
    };
    return inner;
}

var fn = outer();
fn();  // "变量1"

闭包的作用:

  • 在函数外部访问函数内部的局部变量
  • 让局部变量始终保存在内存中,避免全局变量污染
// 经典闭包应用:立即执行函数
(function() {
    // 代码写在这里,避免全局变量污染
})();

七、DOM 操作基础

7.1 DOM 概述

DOM(Document Object Model)将 HTML 页面上的每个标签映射为一个对象,形成一棵 DOM 树。最顶层是 document 对象。

7.2 获取 DOM 对象

// 通过 id 获取(最重要)
var el = document.getElementById("myId");

// 通过 class 获取(返回类数组)
var els = document.getElementsByClassName("myClass");

// 通过标签名获取
var divs = document.getElementsByTagName("div");

// 通过 name 获取(主要用于表单元素)
var inputs = document.getElementsByName("username");

// CSS 选择器(ES6+,推荐)
var el = document.querySelector("#myId");         // 第一个匹配的元素
var els = document.querySelectorAll(".myClass");  // 所有匹配的元素

7.3 操作内容

var box = document.getElementById("box");

// innerHTML — 解析 HTML 标签(慎用,防止 XSS)
box.innerHTML = "<h1>这是标题</h1>";

// innerText — 不解析标签,仅操作文本
box.innerText = "<h1>这是纯文本</h1>";

// textContent — W3C 标准方式
box.textContent = "<h1>纯文本</h1>";

注意:innerHTML 容易引发 XSS(跨站脚本攻击),插入的值必须是安全数据。

7.4 操作属性

var msg = document.getElementById("msg");

// 方式一:直接通过属性名
msg.title = "这是标题";

// 方式二:通过数组方式
msg["title"] = "新标题";

// 方式三:使用 API
msg.getAttribute("title");                // 获取属性
msg.setAttribute("title", "新标题");       // 设置属性

7.5 操作样式

var show = document.getElementById("show");

// 获取行内样式
console.log(show.style.width);

// 获取计算后的样式(W3C 标准)
var style = getComputedStyle(show);
console.log(style.height);

// 获取纯数字样式值(无单位)
console.log(show.offsetWidth);
console.log(show.offsetHeight);

// 修改样式
show.style.width = "300px";
show.style.backgroundColor = "red";

八、事件处理

8.1 事件三要素

  • 事件源:触发事件的 HTML 元素
  • 事件对象:事件的相关信息
  • 事件处理函数:对事件的响应逻辑

8.2 三种事件绑定方式

DOM0 事件模型(推荐)

var btn = document.getElementById("btn");

btn.onclick = function(e) {
    console.log(e);    // e 是事件对象
    console.log(this); // this 指向事件源
    alert("按钮被点击了");
};

DOM2 事件模型(最常用)

var btn = document.getElementById("btn");

btn.addEventListener("click", function(e) {
    alert("按钮被点击");
    console.log(this);  // this 指向事件源
}, false);  // false=冒泡阶段, true=捕获阶段

8.3 事件捕获与冒泡

  • 捕获阶段:事件从 window → document → … → 目标元素(由外向内)
  • 冒泡阶段:事件从目标元素 → … → document → window(由内向外)
// 捕获事件(第 3 个参数为 true)
btn.addEventListener("click", function(e) {
    alert("捕获阶段触发");
}, true);

// 冒泡事件(第 3 个参数为 false,默认)
btn.addEventListener("click", function(e) {
    alert("冒泡阶段触发");
}, false);

8.4 常见事件类型

鼠标事件

事件说明
onclick单击鼠标
ondblclick双击鼠标
onmousedown按下鼠标按钮
onmouseup松开鼠标按钮
onmousemove鼠标移动
onmouseover鼠标移到元素之上
onmouseout鼠标移出元素

键盘事件

事件说明
onkeydown按下按键
onkeyup松开按键
onkeypress按下并松开按键

表单事件

事件说明
onfocus获得焦点
onblur失去焦点
onchange内容改变
onsubmit表单提交

窗口事件

事件说明
onload页面加载完成(最常用)
onresize窗口大小调整
onscroll滚动条滚动

8.5 实战示例

全选与反选

<input type="checkbox" onclick="checkAll(this)" />全选
<ul>
    <li><input type="checkbox" class="item" />选项1</li>
    <li><input type="checkbox" class="item" />选项2</li>
    <li><input type="checkbox" class="item" />选项3</li>
</ul>

<script>
function checkAll(node) {
    var items = document.getElementsByClassName("item");
    for (var i = 0; i < items.length; i++) {
        items[i].checked = node.checked;
    }
}
</script>

倒计时

<span id="msg">10</span>
<script>
var timer = setInterval(function() {
    var msg = document.getElementById("msg");
    msg.innerHTML = msg.innerHTML - 1;
}, 1000);

setTimeout(function() {
    clearInterval(timer);
    document.getElementById("msg").innerHTML = "点火!";
}, 10000);
</script>

九、总结

  1. JavaScript 诞生于 1995 年,用于表单验证,现已发展为通用编程语言
  2. 弱数据类型语言,变量类型由值决定(使用 letconst 代替 var
  3. 三大流程控制:顺序、选择(if/switch)、循环(for/while)
  4. 函数是第一公民——可赋值、可作为参数、可作为返回值
  5. 箭头函数提供简洁的函数表达式写法
  6. DOM 操作通过选择器获取元素,通过属性和方法修改内容
  7. 事件驱动是 JavaScript 的核心机制,DOM2 事件模型最常用

← #037 数据库基础…#039 HTML 常用标签… →