JavaScript 基础
JavaScript 诞生于 1995 年,最初目的是验证表单输入。经过三十年的发展,已从简单的表单校验语言演变成为一门强大的通用编程语言,支撑着整个现代 Web 开发生态。
一、JavaScript 发展历史
1.1 诞生背景(1995 年)
在 JavaScript 问世之前,表单验证必须通过服务器端完成。当时还是电话拨号上网的年代,每次表单提交都要经历漫长的等待。Netscape(网景)公司的 Brendan Eich 着手开发了一种名为 LiveScript 的客户端脚本语言。在 Netscape Navigator 2.0 发布前夕,为借助当时 Java 的热度,将其更名为 JavaScript。
1.2 标准化历程
| 年份 | 事件 |
|---|---|
| 1995 | Brendan Eich 在 Netscape 创建 LiveScript → JavaScript |
| 1996 | 微软推出 JScript(IE 3.0),三方并存 |
| 1997 | ECMA-262 标准发布,定名 ECMAScript |
| 1999 | ECMAScript 3 发布(最广泛使用的版本) |
| 2009 | ES5 发布(严格模式、JSON 支持等) |
| 2015 | ES6/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 变量命名规范
- 只能由大小写字母、数字、下划线
_、$组成 - 不能以数字开头
- 不能使用关键字或保留字
- 使用有意义的名称,遵循小驼峰法(如
userName、classRoom)
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 += 10 | a = a + 10 | a 的值加 10 |
a -= 10 | a = a - 10 | a 的值减 10 |
a *= 10 | a = a * 10 | a 的值乘 10 |
a /= 10 | a = a / 10 | a 的值除 10 |
a **= 10 | a = a ** 10 | a 的 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>
九、总结
- JavaScript 诞生于 1995 年,用于表单验证,现已发展为通用编程语言
- 弱数据类型语言,变量类型由值决定(使用
let和const代替var) - 三大流程控制:顺序、选择(if/switch)、循环(for/while)
- 函数是第一公民——可赋值、可作为参数、可作为返回值
- 箭头函数提供简洁的函数表达式写法
- DOM 操作通过选择器获取元素,通过属性和方法修改内容
- 事件驱动是 JavaScript 的核心机制,DOM2 事件模型最常用