32、web前端开发之JavaScript(一)
目录
- JavaScript简介
- JavaScript基础语法
- 变量与数据类型
- 运算符
- 控制流程
- 函数
- 数组
- 对象
- DOM操作
- 事件处理
- 异步编程与Promise
- 模块化
- 高级概念
- 实际应用案例
- 总结
一、JavaScript简介
1、 JavaScript的起源与发展
JavaScript 由 Brendan Eich 在 1995 年于 Netscape 公司开发,最初名为 Mocha,后改名为 JavaScript。虽然名称中包含“Java”,但它与 Java 无关,两者属于不同的语言。
- 1995年:JavaScript 1.0 版本发布。
- 1997年:ECMA(European Computer Manufacturers Association)发布 ECMAScript 标准(ES1)。
- 2015年:发布 ES6(ECMAScript 2015),是曾经规模最大的一次更新,引入了许多现代 JavaScript 功能。
- 2020年及以后:JavaScript 持续演进,每年发布新特性。
2、 JavaScript的主要特点
- 轻量级:运行在客户端(浏览器)或服务器端(Node.js)。
- 动态类型:变量无需预先声明类型。
- 基于原型:支持面向对象编程(OOP)和函数式编程(FP)。
- 内置功能:支持事件驱动、DOM操作和异步处理。
3、 JavaScript的应用领域
- 客户端开发:用于增强网页交互(如动态UI、表单验证)。
- 服务器端开发:通过 Node.js 构建后端服务、RESTful API。
- 移动开发:React Native 等框架支持跨平台移动应用开发。
- 桌面和终端应用:使用 Electron 构建跨平台桌面应用。
- 游戏开发:HTML5 游戏和浏览器扩展。
4、JavaScript与其他技术的关系
- HTML:用于结构化内容。
- CSS:用于样式化和布局。
- TypeScript:JavaScript 的超集,支持静态类型。
- 框架与库:如 React、Angular、Vue.js 提供高效的开发模式。
二、JavaScript基础语法
1、 基本语法结构
- 语句:JavaScript 程序由语句构成,每条语句用分号
;
结束。 - 换行和空格:JavaScript 对换行和空格不敏感,视为一个分隔符。
- 注释:
- 单行注释:
// 这是一行注释
- 多行注释:
/* 这是多行注释 */
- 单行注释:
示例:
// 单行注释
console.log('Hello, World!'); // 输出 "Hello, World!"
/*
多行
注释
*/
2、变量声明
在 JavaScript 中,变量使用 var
、let
或 const
声明。
- var:函数作用域,允许重复声明和未初始化。
- let:块级作用域,不允许重复声明。
- const:块级作用域,常量,必须初始化。
示例:
var name = 'Alice'; // 函数作用域
let age = 30; // 块级作用域
const PI = 3.14159; // 常量
3、数据类型
JavaScript 的数据类型分为基本类型和引用类型。
基本类型:
- Number:数字(整数和浮点数)。
- String:字符串(单引号或双引号)。
- Boolean:布尔值(
true
或false
)。 - Null:空值(
null
)。 - Undefined:未定义的值(
undefined
)。 - Symbol:唯一且不可变的值(ES6 引入)。
- BigInt:大整数(ES6 引入)。
引用类型:
- Object:对象(键值对集合)。
- Array:数组(索引的有序列表)。
- Function:函数(可执行的代码块)。
- Date:日期和时间对象。
- RegExp:正则表达式对象。
- Map、Set:ES6 引入的集合类型。
示例:
const num = 123; // Number
const str = 'hello'; // String
const flag = true; // Boolean
const nil = null; // Null
let undef; // Undefined
const sym = Symbol(); // Symbol
const arr = [1, 2, 3]; // Array
const obj = { name: 'Bob', age: 30 }; // Object
4、运算符
JavaScript 支持多种运算符,包括算术运算符、比较运算符、逻辑运算符等。
算术运算符:
+
:加法-
:减法*
:乘法/
:除法%
:取模**
:幂(ES6 引入)
比较运算符:
===
:严格等于!==
:严格不等>
:大于<
:小于>=
:大于或等于<=
:小于或等于
逻辑运算符:
&&
:逻辑与||
:逻辑或!
:逻辑非
赋值运算符:
=
:简单赋值+=
:加法赋值-=
:减法赋值*=
:乘法赋值/=
:除法赋值%=
:取模赋值**=
:幂赋值(ES6 引入)
字符串运算符:
+
:连接字符串+=
:连接字符串并赋值
示例:
console.log(5 + 3); // 8
console.log('5' + 3); // '53'
console.log(5 === '5'); // false(严格比较)
console.log(5 == '5'); // true(松散比较)
5、控制结构
控制结构用于控制程序的执行流程,包括条件语句和循环语句。
1. 条件语句
- if 语句:根据条件执行不同的代码块。
- if…else 语句:当条件为真时执行一个代码块,否则执行另一个代码块。
- switch 语句:用于多个条件分支。
示例:
// if 语句
let x = 5;
if (x > 10) {
console.log('x 大于 10');
}
// if...else 语句
let y = 5;
if (y > 10) {
console.log('y 大于 10');
} else {
console.log('y 不大于 10');
}
// switch 语句
let day = 2;
switch (day) {
case 1:
console.log('星期一');
break;
case 2:
console.log('星期二');
break;
default:
console.log('其他天');
}
2. 循环语句
- for 循环:用于已知循环次数的场景。
- while 循环:用于未知循环次数的场景。
- do…while 循环:至少执行一次循环。
- for…in 循环:遍历对象的属性。
- for…of 循环:遍历数组或可迭代对象(ES6 引入)。
示例:
// for 循环
for (let i = 0; i < 5; i++) {
console.log(i);
}
// while 循环
let j = 0;
while (j < 5) {
console.log(j);
j++;
}
// do...while 循环
let k = 0;
do {
console.log(k);
k++;
} while (k < 5);
// for...in 循环
const obj = { a: 1, b: 2, c: 3 };
for (let key in obj) {
console.log(`${key}: ${obj[key]}`);
}
// for...of 循环
const arr = [1, 2, 3];
for (let value of arr) {
console.log(value);
}
6、函数
函数是可重复使用的代码块,封装了一组语句。
1. 函数的定义
- 函数声明:
function greet(name) {
console.log(`Hello, ${name}!`);
}
greet('Alice'); // 输出 "Hello, Alice!"
- 匿名函数:
const add = function(a, b) {
return a + b;
};
console.log(add(2, 3)); // 输出 5
- 箭头函数(ES6 引入):
const multiply = (a, b) => a * b;
console.log(multiply(2, 3)); // 输出 6
2. 函数的参数和返回值
- 参数:函数执行时传入的值。
- 返回值:函数执行后的结果,使用
return
关键字返回。
示例:
function sum(a, b) {
return a + b;
}
console.log(sum(2, 3)); // 输出 5
3. 函数的作用域和提升
- 函数作用域:函数内声明的变量仅在函数内有效。
- 变量提升:
var
变量会被提升到函数顶部,而let
和const
不会。
示例:
function scopeTest() {
console.log(x); // undefined,因为 x 被提升
var x = 10;
}
scopeTest();
function letTest() {
console.log(y); // ReferenceError: y 未定义
let y = 20;
}
letTest();
7、错误处理与调试
JavaScript 提供了 try...catch
语句用于错误处理。
示例:
try {
// 可能会导致错误的代码
console.log(x);
} catch (error) {
console.error('捕获到错误:', error);
}
常用调试方法:
- 使用
console.log()
输出变量值。 - 使用浏览器的开发者工具(DevTools)设置断点进行调试。
三、JavaScript变量与数据类型详解
1、变量的声明与赋值
在JavaScript中,变量是用来存储和操作数据的容器。声明变量使用 let
、const
和 var
关键字。
- let:声明块级作用域的变量,可以重新赋值,但不能在同一作用域重新声明。
- const:声明常量,值不能更改,同样具有块级作用域。
- var:声明函数作用域或全局变量,允许重新声明和赋值,现多少用。
示例:
let name = 'Alice'; // 声明并赋值
const PI = 3.14159; // 常量
var age = 30; // 函数/全局变量
2、数据类型
JavaScript数据类型分为基本类型(primitive)和引用类型(reference)。
1. 基本类型
包括:
- Number:数字,支持整数和浮点数,例如
123
、3.14
。 - String:字符串,使用单引号或双引号包围,例如
'hello'
、"world"
。 - Boolean:布尔值,
true
或false
。 - Null:空值,表示为
null
。 - Undefined:未定义的值,使用
undefined
。 - Symbol:唯一且不可变的值,使用
Symbol('key')
,ES6引入。 - BigInt:大整数,用
n
或BigInt()
表示,用于超出常规数值范围的情况。
示例:
let num = 123; // Number
const str = 'hello'; // String
let flag = true; // Boolean
let nil = null; // Null
let undef; // Undefined
const sym = Symbol(); // Symbol
let bigNum = 9007199254740991n; // BigInt
2. 引用类型
包括:
- Object:对象,键值对集合。
- Array:数组,索引的有序列表。
- Function:函数,可执行的代码块。
- Date:日期和时间对象。
- RegExp:正则表达式对象。
- Map、Set等:ES6引入的集合类型。
示例:
const obj = {name: 'Bob', age: 30}; // 对象
const arr = [1, 2, 3]; // 数组
const sum = (a, b) => a + b; // 函数
const date = new Date(); // 日期对象
3、变量命名规则
变量命名需要遵循以下规则:
- 名称只能包含字母、数字、下划线
_
和美元符号$
。 - 不能以数字开头。
- 区分大小写。
- 不能使用JavaScript的保留字和符号。
示例:
let userName; // 正确
const _age = 25; // 正确
let 123num; // 错误,数字开头
let function; // 错误,使用保留字
4、变量的作用域
作用域决定了变量的访问范围:
- 全局变量:在脚本的任何地方都可访问。
- 函数变量:仅在函数内部可用。
- 块级变量:在
{}
包围的块中有效,如if
、while
、function
内。
示例:
let globalVar = 'global'; // 全局变量
if (true) {
let blockVar = 'block'; // 块级变量
console.log(blockVar); // 可访问
}
// console.log(blockVar); // ReferenceError: blockVar未定义
function func() {
let localVar = 'local'; // 函数变量
console.log(localVar);
}
func(); // Outputs: local
console.log(localVar); // ReferenceError: localVar未定义
5、数据类型检查
使用 typeof
运算符来检查基本类型,结果包括:
"number"
"string"
"boolean"
"undefined"
"symbol"
"object"
"function"
特殊情况:
typeof null
返回"object"
,需要特别注意。- 检查数组类型,使用
Array.isArray()
。
示例:
typeof 123; // "number"
typeof 'hello'; // "string"
typeof null; // "object"(注意)
typeof undefined; // "undefined"
Array.isArray([1,2,3]); // true
6、类型转换
JavaScript中的类型转换分为显式和隐式两种。
1. 显式转换
使用构造函数或包装对象进行转换。
- 转换为Number:
Number()
,parseInt()
,parseFloat()
- 转换为String:
String()
,toString()
- 转换为Boolean:
Boolean()
示例:
let str = '123';
let num = Number(str); // 123
let bool = Boolean(''); // false
2. 隐式转换
在特定操作中自动进行转换,如算术运算或比较。
示例:
const a = '5';
const b = 5;
console.log(a + b); // '55'(字符串拼接)
console.log(a == b); // true(隐式转换为数值)
console.log(a === b);// false(严格比较)
7、Null与Undefined
- null 表示一个空值,通常用于变量初始化。
- undefined 表示未定义的值,变量声明后未赋值的情况。
比较:
null == undefined; // true(松散比较)
null === undefined; // false(严格比较)
typeof null; // 'object'(需要注意)
8、变量提升
- var 变量会被提升到函数的顶部。
- let 和 const 变量不提升,存在“暂时性死区”(TDZ)。
示例:
console.log(a); // undefined(var变量提升)
var a = 10;
console.log(b); // ReferenceError: b未定义
let b = 20; // let在TDZ内不可访问
四、JavaScript 运算符详解
1、运算符概述
运算符是JavaScript中用于执行运算的符号,它们可以是算术运算、比较、逻辑判断、赋值等。运算符的作用是将操作数(变量、值、表达式等)进行运算,并返回结果。
2、算术运算符
算术运算符用于执行数学运算,包括加法、减法、乘法、除法等。
1. 常见算术运算符
+
:加法-
:减法*
:乘法/
:除法
示例:6 / 2
返回3
。%
:取模(返回除法运算的余数)
示例:7 % 3
返回1
。**
:幂(ES6 引入)
示例:2 ** 3
返回8
(即 2323)。
2. 示例
console.log(5 + 3); // 输出:8
console.log(10 - 4); // 输出:6
console.log(2 * 3); // 输出:6
console.log(6 / 2); // 输出:3
console.log(7 % 3); // 输出:1
console.log(2 ** 3); // 输出:8
3、比较运算符
比较运算符用于比较两个值,并返回一个布尔值(true
或 false
)。
1. 严格比较运算符
严格比较运算符会同时比较值和类型。
===
:严格等于
示例:5 === '5'
返回false
,因为类型不同。!==
:严格不等于
示例:5 !== '5'
返回true
。
2. 松散比较运算符
松散比较运算符会先将类型转换后再比较。
==
:等于
示例:5 == '5'
返回true
,因为'5'
会被转换为5
。!=
:不等于
示例:5 != '5'
返回false
。
3. 大于和小于运算符
>
:大于
示例:5 > 3
返回true
。<
:小于
示例:5 < 3
返回false
。>=
:大于或等于
示例:5 >= 5
返回true
。<=
:小于或等于
示例:5 <= 5
返回true
。
4. 示例
console.log(5 === '5'); // 输出:false(严格比较)
console.log(5 == '5'); // 输出:true(松散比较)
console.log(5 > 3); // 输出:true
console.log(5 < 3); // 输出:false
console.log(5 >= 5); // 输出:true
console.log(5 <= 5); // 输出:true
4、逻辑运算符
逻辑运算符用于将多个条件结合在一起,并返回一个布尔值。
1. 逻辑与 (&&
)
逻辑与运算符返回 true
,只有当所有操作数都为 true
时。
- 示例:
true && true
返回true
。 - 示例:
true && false
返回false
。
2. 逻辑或 (||
)
逻辑或运算符返回 true
,只要至少有一个操作数为 true
。
- 示例:
true || false
返回true
。 - 示例:
false || false
返回false
。
3. 逻辑非 (!
)
逻辑非运算符对一个布尔值取反。
- 示例:
!true
返回false
。 - 示例:
!false
返回true
。
4. 短路求值
逻辑与和逻辑或运算符具有短路求值的特性:
- 逻辑与 (
&&
)会在第一个表达式为false
时,直接返回false
,不再执行第二个表达式。 - 逻辑或 (
||
)会在第一个表达式为true
时,直接返回true
,不再执行第二个表达式。
5. 示例
console.log(true && true); // 输出:true
console.log(true && false); // 输出:false
console.log(true || false); // 输出:true
console.log(false || false); // 输出:false
console.log(!true); // 输出:false
console.log(!false); // 输出:true
// 短路求值示例
console.log(false && (5 / 0)); // 输出:false,不会执行除以零的操作
console.log(true || (5 / 0)); // 输出:true,不会执行除以零的操作
5、赋值运算符
赋值运算符用于将运算的结果赋值给变量。
1. 标准赋值运算符
=
:简单赋值
示例:let a = 5;
2. 算术赋值运算符
+=
:加法赋值
示例:a += 5;
等价于a = a + 5;
。-=
:减法赋值
示例:a -= 5;
等价于a = a - 5;
。*=
:乘法赋值
示例:a *= 5;
等价于a = a * 5;
。/=
:除法赋值
示例:a /= 5;
等价于a = a / 5;
。%=
:取模赋值
示例:a %= 5;
等价于a = a % 5;
。**=
:幂赋值(ES6 引入)
示例:a **= 5;
等价于a = a ** 5;
。
3. 示例
let a = 10;
a += 5; // 等价于 a = a + 5
console.log(a); // 输出:15
a -= 3; // 等价于 a = a - 3
console.log(a); // 输出:12
a *= 2; // 等价于 a = a * 2
console.log(a); // 输出:24
a /= 4; // 等价于 a = a / 4
console.log(a); // 输出:6
a %= 3; // 等价于 a = a % 3
console.log(a); // 输出:0
a **= 2; // 等价于 a = a ** 2
console.log(a); // 输出:0(因为 0 的任何次幂都是 0)
6、字符串运算符
JavaScript 中的加法运算符 (+
) 可以用于连接字符串。
1. 字符串连接
+
:字符串连接
示例:'Hello, ' + 'World!'
返回'Hello, World!'
。+=
:字符串连接赋值
示例:let str = 'Hello'; str += ' World!';
返回'Hello World!'
。
2. 示例
console.log('Hello, ' + 'World!'); // 输出:Hello, World!
console.log('5' + 3); // 输出:'53'
let str = 'Hello';
str += ' World!';
console.log(str); // 输出:Hello World!
7、运算符的优先级
运算符的优先级决定了表达式中运算的执行顺序。优先级高的运算符先执行。以下是运算符的优先级从高到低的排序:
- 圆括号
()
- 逻辑非
!
- 算术运算符:
**
(最高) - 算术运算符:
*
、/
、%
- 算术运算符:
+
、-
- 比较运算符:
>
,<
,>=
、<=
- 比较运算符:
===
、!==
、==
、!=
- 逻辑与
&&
- 逻辑或
||
- 赋值运算符:
=
,+=
、-=
、*=
、/=
、%=
、**=
- 逗号
,
8、常见错误与注意事项
-
类型转换问题:
JavaScript 的松散比较会导致类型转换,可能引发意外结果。例如:console.log('5' == 5); // 输出:true console.log('5' === 5); // 输出:false
建议使用严格比较运算符 (
===
和!==
) 来避免类型转换的问题。 -
逻辑与和逻辑或的结果:
逻辑与 (&&
) 和逻辑或 (||
) 的返回值并非总是true
或false
,它们会返回两个操作数中的一个:console.log(5 && 10); // 输出:10 console.log(0 && 10); // 输出:0 console.log(5 || 10); // 输出:5 console.log(0 || 10); // 输出:10
-
赋值运算符的误用:
注意赋值运算符 (=
) 和比较运算符 (==
或===
) 的区别,避免在条件判断中误用赋值运算符:if (x = 5) { // 这会将 x 赋值为 5,并执行代码块 console.log('x 被赋值为 5'); }