JavaScript 诞生于 1995 年,最初只做表单验证,现在是支撑整个 Web 生态的通用语言。
一、JavaScript 发展历史
1.1 诞生背景(1995 年)
在 JavaScript 之前,表单验证只能由服务器端完成;Brendan Eich 做出 LiveScript,Navigator 2.0 发布前为蹭 Java 热度改名 JavaScript。
1.2 标准化历程
| 年份 | 事件 |
|---|---|
| 1995 | 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
面向对象的、弱数据类型的、解释性的、动态的脚本语言;语法宽松、解释执行。
1.4 JavaScript 的三大主要作用
数据校验(诞生目的)、网页特效(主场景)、数据交互(Ajax)。
二、开发环境与第一个程序
2.1 开发环境
编辑器:VS Code / Sublime Text / Hbuilder / WebStorm;运行: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> 标签内,放 <body> 最后。
<script>
alert('hello JavaScript');
</script>
外联 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)。
3.3 常量
const PI = 3.14159;
const VERSION = "1.0";
// 以下会报错:常量不允许修改
VERSION = "2.0"; // TypeError
3.4 数据类型
分基本数据类型与引用数据类型:
基本数据类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| Number | 整数和浮点数 | 10, 3.14, NaN |
| String | 被引号包围的字符 | "hello", 'world' |
| Boolean | 逻辑值 | true, false |
| null | 空值 | null |
| undefined | 未定义 | undefined |
引用数据类型:
| 类型 | 说明 |
|---|---|
| Array | 数组 |
| Object | 对象 |
| Function | 函数对象 |
3.5 弱数据类型特性
弱类型:变量类型由值决定。
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会发生”穿透”。
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)
函数声明可在定义前调用(hoisting):
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 把 HTML 标签映射为对象树,顶层 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 事件三要素
三要素:事件源、事件对象、事件处理函数。
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 → 目标元素),冒泡由内向外(目标元素 → 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>
九、总结
变量类型由值决定、优先 let/const;流程控制三类;函数是一等公民;DOM + 事件驱动。