一、初识JavaScript
1.1 JavaScript是什么?
JavaScript(简称JS)是一门跨平台 、面向对象 的脚本语言,核心作用是控制网页行为,让静态页面动起来。
- 运行环境 :主要在客户端 (浏览器),也可通过
Node.js运行在服务器端 - 核心版 本:
ES6(ECMAScript 2015)是目前最常用的版本,新增了大量实用语法
三个核心特点:
✅ 客户端运行 :在用户浏览器中直接执行,无需服务器处理
✅ 脚本语言 :不需要编译,由浏览器直接解释执行
✅ 面向对象:支持面向对象编程,代码更易组织
1.2 JavaScript的组成
JS不是单一语法,而是由三部分组成,各司其职:
ECMAScript:JS的基础语法核心,规定了变量、函数、数据类型等基础规则,是所有JS环境的通用标准Web APIs:分为DOM和BOM,是JS操作网页和浏览器的接口- DOM(文档对象模型):操作网页元素(如修改文字、样式、添加标签)
- BOM(浏览器对象模型):操作浏览器(如跳转页面、弹出弹窗、获取地址栏)
1.3 JS的3种书写位置
方式1: 内部JavaScript(写在HTML里)
用<script>标签包裹代码,可放在HTML的或中,推荐放在闭合标签上方。
bash
<!DOCTYPE html>
<html>
<body>
<h1>我的网页</h1>
<!-- 推荐放在body结束前, 避免JS执行时html还没加载完 -->
<script>
alert("Hello JavaScript!");
</script>
</body>
</html>
注意 :
① <script>标签不能自闭合(不能写成<script/>);
② 放底部是因为浏览器按顺序加载HTML,若JS先加载且要操作下方HTML,会因HTML未加载而失效
方式2:外部JavaScript(实际项目常用)
将代码写在.js后缀的文件中,再通过<script>标签的src属性引入HTML,是开发中最推荐的方式(代码复用性高、HTML更简洁)。
bash
<!-- index.html -->
<body>
<script src="app.js"></script>
</body>
<!-- app.js -->
console.log("这是外部JS文件");
注意 :
① 引入外部JS的<script>标签中间不能写代码,写了也会被忽略;
② 多个外部JS按引入顺序执行。
方式3:内联JavaScript(写在标签内部,了解即可)
将代码直接写在HTML标签的事件属性中,仅作了解,后续Vue框架会用到类似写法。
bash
<body>
<!-- 点击按钮弹出提示框 -->
<button onclick="alert('逗你玩~~~')">点击我月薪过万</button>
</body>
1.4 JS注释:代码的"说明书"
注释是给开发者看的文字,浏览器会忽略,用于标注代码功能,方便后续维护。
| 注释类型 | 符号 | 作用 | 快捷键 |
|---|---|---|---|
| 单行注释 | // | 注释当前行内容 | Ctrl + / |
| 块注释 | /* */ | 注释多行内容(可跨行) | Shift + Alt + A |
bash
// 这是单行注释
console.log("hello"); // 注释也可以写在代码后面
/*
多行注释
可以写很多行
*/
/**
* 文档注释(常用)
* 说明函数功能
* @param {number} x - 参数说明
*/
1.5 JS结束符:分号用不用?
用英文分号;表示一条语句结束,实际开发中可加可不加 ,浏览器会自动推断语句结束位置。
约定 :风格统一最重要,要么每句都加,要么每句都不加(按团队要求来),避免混用。
bash
// 方式1:每行都加(严谨)
console.log("Hello");
let name = "小明";
// 方式2:不加分号(现代风格)
console.log("Hello")
let name = "小明"
1.6 JS输入输出:和用户交互
输入输出是人与计算机的交互:用户输入信息(如键盘输入),计算机处理后展示结果(如弹窗、控制台打印)。
输出语法(向用户展示内容)
| 语法 | 作用 | 示例 |
|---|---|---|
| document.write('内容') | 向网页body中输出内容,支持HTML标签 | document.write('<h2>我是输出的标题</h2>') |
| alert('内容') | 弹出警告对话框,阻断页面执行 | alert('欢迎来到JS世界') |
| console.log('内容') | 向浏览器控制台打印内容,供开发者调试 | console.log('调试信息') |
输入语法(获取用户信息)
bash
// 弹出输入框,提示用户输入姓名,返回值是用户输入的内容
var name = prompt('请输入您的姓名:');
// 将输入的姓名打印到控制台
console.log('用户姓名:', name);
代码执行顺序
- 默认按HTML文档流顺序执行(从上到下)
alert()和prompt()会跳过页面渲染优先执行(先弹窗,再加载页面内容)
1.7 字面量:描述具体的数据
字面量是直接表示具体值 的语法,相当于"数据的字面形式",用来描述事物的具体内容。
bash
// 数字字面量(表示具体数字)
var salary = 1000;
// 字符串字面量(表示具体文本,用单/双引号包裹)
var company = '黑马程序员';
// 后续会学的其他字面量
var arr = [1,2,3]; // 数组字面量
var obj = {name: '张三'}; // 对象字面量
二、JS基础语法:变量、数据类型与运算符
2.1 核心概念:内存、数据、变量
- 数据:存储在内存中的信息(本质是二进制0101),程序所有操作的目标都是数据(万物皆数据,函数也是数据)。
- 内存:内存条通电后产生的临时存储空间,断电后数据消失(与硬盘的持久存储不同)。声明变量/函数时,JS引擎会自动分配内存,不用手动管理。
- 变量:值可以变化的量,是内存的"标识"------通过变量名找到对应的内存,进而操作内存中的数据(一个变量对应一块小内存)。
三者关系:内存是"容器",数据是"容器里的东西",变量是"容器的标签"。
2.2 变量:存储数据的容器
变量的定义格式
bash
// 1. var - 老方法(不推荐)
// 只声明变量,不赋值(默认值为undefined)
var age;
// 声明并赋值(推荐)
var name = '张三';
// 同时声明多个变量
var height = 180, weight = 70;
// 2. let - 现代方法(推荐)
let age = 18;
age = 19; // 可以重新赋值
// let age = 20; // 错误!不能重复声明
// 3. const - 声明常量
const PI = 3.14;
// PI = 3.15; // 错误!常量不能修改
JS是弱类型语言:变量没有固定类型,可随时存储不同类型的值(如先存数字,再存字符串)。
var、let、const的区别(ES6特性)
ES6新增let和const,解决了var的一些问题,实际开发中优先用let/const。
| 关键字 | 作用域 | 是否可重复声明 | 是否可修改值 | 适用场景 |
|---|---|---|---|---|
| var | 全局/函数作用域(代码块内声明也能被外部访问) | 是 | 是 | 兼容旧环境,现在很少用 |
| let | 块级作用域(仅在所在代码块内有效) | 否 | 是 | 值会变化的变量 |
| const | 块级作用域 | 否 | 否(声明时必须赋值) | 值固定的常量(如PI、接口地址) |
变量命名规范
- 由字母、数字、下划线(_)、美元符号($)组成,不能以数字开头
- 区分大小写(name和Name是两个不同变量)
- 不能用JS关键字(如var、function、if等)
- 推荐用驼峰命名法:首字母小写,后续单词首字母大写(如userName、totalPrice)
命名规范示例
bash
// ✅ 正确命名
let userName = "小明"; // 驼峰命名法
let isLogin = true; // 布尔值用is开头
let MAX_COUNT = 100; // 常量全大写
// ❌ 错误命名
let 1name = ""; // 不能数字开头
let user-name = ""; // 不能用短横线
let function = ""; // 不能用关键字
2.3 数据类型:JS中的"数据分类"
JS将数据分为两大类:基本类型(值类型)和对象类型(引用类型),不同类型的存储和操作方式不同。
(1)基本数据类型(5种)
直接存储值,占用空间小,存放在内存栈中。
| 类型 | 描述 | 示例 |
|---|---|---|
| String | 任意字符串(单/双引号、反引号包裹) | 'hello'、"world"、姓名:${name} |
| Number | 任意数字(整数、小数、NaN),NaN表示"非数字" | 100、3.14、NaN(typeof NaN === 'number') |
| Boolean | 布尔值,仅两个值:true(真)、false(假) | true、false |
| Undefined | 变量声明未赋值时的默认值 | var age; // age的值是undefined |
| Null | 表示"空对象",主动赋值表示值为空 | var obj = null; // 表示obj后续会存对象 |
注意 :大数值精度问题
JS中数字 默认是双精度浮点数,能安全表示的整数范围是 -2⁵³+1 ~ 2⁵³-1(约±9e15),超过这个范围会丢失精度。
bash
// 大数值丢失精度示例
console.log(Number("898186844400803840")); // 输出898186844400803800(末尾40变成00)
解决方案:
- 用字符串存储大数值,避免转为Number类型
- 若必须处理数值型大数值,用第三方库(如
lossless-json、json-bigint)
基本数据类型赋值示例
bash
// 1. String - 字符串
let name = "JavaScript";
let greeting = 'Hello';
let message = `模板字符串${name}`; // ES6新特性
// 2. Number - 数字
let age = 25;
let price = 99.99;
let bigNum = 1e6; // 1000000(科学计数法)
// 3. Boolean - 布尔值
let isStudent = true;
let isWorking = false;
// 4. Undefined - 未定义
let x; // undefined
let y = undefined;
// 5. Null - 空值
let empty = null;
(2)对象数据类型(引用类型)
存储的是内存地址(指向堆中的数据),占用空间大,适合存储复杂数据。
| 类型 | 描述 | 示例 |
|---|---|---|
| Object | 通用对象,存储键值对数据 | {name: '张三', age: 20} |
| Function | 特殊对象,可执行代码 | function sum(a,b){return a+b} |
| Array | 特殊对象,按索引存储有序数据 | [1,2,3,4] |
引用数据类型示例
bash
// 1. Object - 对象
let person = {
name: "小明",
age: 18,
sayHello: function() {
console.log("你好!");
}
};
// 2. Array - 数组
let colors = ["red", "green", "blue"];
// 3. Function - 函数
function add(a, b) {
return a + b;
}
(3)数据类型判断方法
| 方法 | 适用场景 | 局限性 | 示例 |
|---|---|---|---|
typeof |
判断基本类型(undefined、Number、String、Boolean) | 无法区分Null和Object、Object和Array(typeof null === 'object'是历史bug) | typeof 'hello' → 'string' |
instanceof |
判断对象的具体类型 | 不能判断基本类型 | [1,2] instanceof Array → true |
===(全等于) |
判断undefined和null |
仅适用于这两种类型 | age === undefined → true |
补充:undefined与null的区别
- undefined:变量声明但未赋值(默认值)
- null:变量声明且赋值,但值为空(主动表示"无对象")
赋值场景 :
① 初始赋值为null,表示变量后续会存对象;
② 函数结束前将对象赋值为null,让其成为垃圾对象(被回收)。
类型判断示例
bash
// 常用判断方法
typeof "hello" // "string"
typeof 123 // "number"
typeof true // "boolean"
typeof undefined // "undefined"
typeof null // "object"(历史遗留问题)
// 准确判断
Array.isArray([]) // true(判断数组)
[] instanceof Array // true
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call([]) // "[object Array]"
2.4 运算符:JS中的"计算工具"
(1)关系运算符(比较运算)
用于比较两个值的关系,返回布尔值(true/false),核心区分==和===。
| 运算符 | 规则 | 示例 | 结果 |
|---|---|---|---|
| ==(等于) | 先做类型转换,再比较值 | "12" == 12 | true |
| ===(全等于) | 不做类型转换,同时比较值和类型 | "12" === 12 | false |
开发中优先用===,避免类型转换导致的意外结果。
(2)逻辑运算符(与、或、非)
用于逻辑判断,支持"短路运算"(满足条件后不再执行后续代码)。
| 运算符 | 名称 | 短路规则 | 示例 | 结果 |
|---|---|---|---|---|
| & | 逻辑与 | 遇假则停,返回第一个假值;全为真返回最后一个真值 | 3 && 0 && 5 |
0 |
| 或(表示双竖杠) | 逻辑或 | 遇真则停,返回第一个真值;全为假返回最后一个假值 | 0 或 3 或5 | 3 |
| ! | 逻辑非 | 取反布尔值(真变假,假变真) | !true | false |
运算符示例
bash
//算术运算符
let a = 10, b = 3;
a + b // 13(加)
a - b // 7(减)
a * b // 30(乘)
a / b // 3.333...(除)
a % b // 1(取余)
a ** b // 1000(指数,ES7)
//比较运算符
5 == "5" // true(值相等)
5 === "5" // false(值和类型都相等)
5 != "5" // false
5 !== "5" // true
10 > 5 // true
10 >= 10 // true
//逻辑运算符
// &&(与)- 全为真才为真
true && true // true
true && false // false
// ||(或)- 有一个为真就为真
true || false // true
false || false // false
// !(非)- 取反
!true // false
!false // true
// 短路运算(常用技巧)
let name = user && user.name; // user存在才取name
let count = value || 0; // value为假时用0
2.5 类型转换:不同类型数据的转换
JS中运算或判断时,常会自动转换数据类型 (隐式转换),也可手动转换 (显式转换)。
(1)转换为字符串
bash
var num = 123;
// 1. toString()方法(null和undefined不能用)
var str1 = num.toString();
// 2. String()强制转换(所有类型都能用)
var str2 = String(num);
// 3. toLocaleString()(数字转千分位字符串)
var str3 = num.toLocaleString(); // "123"(大数字如1234567 → "1,234,567")
// 4. 隐式转换(+拼接字符串)
var str4 = num + "";
(2)转换为数字型(重点)
bash
var str = "123";
// 1. parseInt():解析为整数(遇到非数字字符停止)
var num1 = parseInt(str); // 123
var num2 = parseInt("123a"); // 123
var num3 = parseInt("a123"); // NaN
// 2. parseFloat():解析为浮点数(支持小数点)
var num4 = parseFloat("123.45"); // 123.45
// 3. Number():强制转换(整体转换,非数字则为NaN)
var num5 = Number(str); // 123
var num6 = Number("123a"); // NaN
// 4. 隐式转换(-、*、/运算)
var num7 = str - 0; // 123
// 5. +号隐式转换
var num8 = +str; // 123
(3)转换为布尔值
以下值转换为布尔值为false(假值),其余均为true(真值):0、NaN、""(空串)、null、undefined。
bash
// 显式转换
console.log(Boolean(0)); // false
console.log(Boolean("hello")); // true
// 隐式转换(逻辑运算、条件判断时)
if ("hello") { console.log("真值"); }
三、JS函数:封装可复用的代码块
函数是一组可重复执行的代码块,封装逻辑后可多次调用,减少代码冗余。
3.1 函数的两种定义方式
方式1:函数声明(function关键字定义)
bash
// 定义函数
function 函数名(形参1, 形参2) {
// 函数体(要执行的代码)
return 返回值; // 可选,返回函数执行结果
}
// 调用函数(形参接收实参的值)
var 结果 = 函数名(实参1, 实参2);
// 示例:求和函数
function sum(a, b) {
return a + b;
}
var total = sum(2, 3);
console.log(total); // 5
特点:形参无需指定类型,返回值无需定义类型,直接用return返回即可。
方式2:函数表达式(赋值给变量)
bash
// 定义函数(匿名函数赋值给变量)
var 函数名 = function(形参列表) {
函数体;
};
// 调用函数
函数名(实参列表);
// 示例
var sayHello = function(name) {
console.log("Hello, " + name);
};
sayHello("张三"); // Hello, 张三
注意 :JS没有函数重载
Java中函数名相同、参数不同 视为重载,但JS中重复定义同名函数,后定义的会覆盖前定义的。
bash
function sum(a) {
return a + 1;
}
function sum(a, b) { // 覆盖前一个sum
return a + b;
}
console.log(sum(2)); // NaN(第二个sum需要两个参数,b未赋值为undefined)
函数的作用域
bash
let globalVar = "全局变量"; // 全局作用域
function testScope() {
let localVar = "局部变量"; // 函数作用域
if (true) {
let blockVar = "块级变量"; // 块级作用域(ES6)
console.log(blockVar); // 可以访问
}
// console.log(blockVar); // 错误!不能访问块级变量
}
console.log(globalVar); // 可以访问
// console.log(localVar); // 错误!不能访问局部变量
3.2 arguments:隐形参数(处理不定参)
当不确定函数接收多少个实参时,用arguments(函数内置对象)获取所有实参,是一个"伪数组"。
伪数组特点
- 有length属性,按索引存储数据
- 没有数组的方法(如push、pop)
- 仅能在函数内部使用
示例:求任意个数的和
bash
function sum() {
var total = 0;
// 遍历arguments,累加所有实参
for (var i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(sum(1,2)); // 3
console.log(sum(1,2,3,4)); // 10
arguments转真数组
bash
function fn() {
// 方法1:Array.prototype.slice.call
var arr1 = Array.prototype.slice.call(arguments);
// 方法2:[].slice.call(简写)
var arr2 = [].slice.call(arguments);
console.log(arr1 instanceof Array); // true
}
四、JS对象:存储复杂数据的容器
对象是多个数据的集合体(封装体),用于统一管理关联数据,JS中对象分3类:自定义对象、内置对象、浏览器对象。
内置对象是JS自带的对象(如Math、Date、Array),提供了常用功能,是开发核心;浏览器对象(BOM、DOM)用于操作浏览器和网页,后续详解。
4.1 内置对象 Math(数学计算)
Math不是构造函数,无需实例化,直接用Math.属性/方法调用,提供常用数学运算。
| 属性/方法 | 功能 | 示例 | 结果 |
|---|---|---|---|
| Math.PI | 圆周率 | Math.PI | 3.141592653589793 |
| Math.floor(x) | 向下取整(舍掉小数) | Math.floor(3.8) | 3 |
| Math.ceil(x) | 向上取整(进1) | Math.ceil(3.2) | 4 |
| Math.round(x) | 四舍五入(注意:-3.5返回-3) | Math.round(3.5) | 4 |
| Math.abs(x) | 绝对值 | Math.abs(-5) | 5 |
| Math.max(x,y,...) | 求最大值 | Math.max(1,3,2) | 3 |
| Math.min(x,y,...) | 求最小值 | Math.min(1,3,2) | 1 |
| Math.random() | 获取[0,1)之间的随机小数 | Math.random() | 0.123456...(随机) |
实用示例:获取指定范围的随机整数
bash
// 获取 [min, max] 范围内的随机整数(包含min和max)
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 示例:获取1-10之间的随机数
console.log(getRandom(1, 10));
4.2 内置对象:Date(日期对象)
Date是构造函数,需实例化(new Date())才能使用,用于处理日期和时间。
(1)实例化Date对象
bash
// 1. 无参数:获取当前时间
var now = new Date();
console.log(now); // 输出当前时间(如 Tue Jan 06 2026 13:57:10 GMT+0800 (中国标准时间)
// 2. 有参数:获取指定时间
var future1 = new Date('2026/12/31'); // 字符串格式
var future2 = new Date(2026, 11, 31); // 数字格式(月份0-11,11表示12月)
var future3 = new Date(2026, 11, 31, 23, 59, 59); // 年、月、日、时、分、秒
(2)获取日期时间的方法
| 方法 | 功能 | 示例(now为当前时间对象) |
|---|---|---|
| getFullYear() | 获取年份(4位) | now.getFullYear() → 2026 |
| getMonth() | 获取月份(0-11) | now.getMonth() + 1 → 1(1月) |
| getDate() | 获取日期(1-31) | now.getDate() → 6 |
| getDay() | 获取星期(0-6,0为周日) | now.getDay() → 3(周三) |
| getHours() | 获取小时(0-23) | now.getHours() → 10 |
| getMinutes() | 获取分钟(0-59) | now.getMinutes() → 30 |
| getSeconds() | 获取秒数(0-59) | now.getSeconds() → 45 |
(3)获取总毫秒数(时间戳)
时间戳是从1970年1月1日(世界标准时间)到指定时间的毫秒数,用于时间差计算。
bash
var date = new Date();
// 方法1:valueOf()/getTime()
console.log(date.valueOf()); // 输出时间戳 1767679294424
console.log(date.getTime());
// 方法2:简写(隐式转换)
var timestamp1 = +new Date();
// 方法3:HTML5新增(有兼容性,推荐现代浏览器用)
var timestamp2 = Date.now();
格式化日期
bash
now.toLocaleString() // "2024/1/1 12:00:00"
now.toLocaleDateString() // "2024/1/1"
now.toLocaleTimeString() // "12:00:00"
4.3 内置对象:Array(数组对象)
数组是有序的集合,可存储任意类型数据,长度可变(自动扩容),用于管理一组相关数据。
(1)创建数组的两种方式
bash
// 方式1:字面量方式(推荐,简洁)
var arr1 = [1, 'test', true, null]; // 可存储不同类型数据
// 方式2:new Array()(构造函数)
var arr2 = new Array(); // 空数组
var arr3 = new Array(1,2,3,4); // 传入多个参数:数组元素
var arr4 = new Array(5); // 传入一个参数:数组长度(5个空元素)
(2)数组属性:length(长度)
bash
var arr = [1,2,3];
console.log(arr.length); // 3
// 修改length可改变数组长度
arr.length = 5;
console.log(arr); // [1, 2, 3, 空属性 × 2](新增两个空元素)
(3)数组方法:检测是否为数组
bash
var arr = [1,2,3];
var obj = {};
// 方法1:instanceof
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
// 方法2:Array.isArray()(HTML5新增,更可靠)
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
(4)数组方法:遍历数组
bash
var arr = [1,2,3,4];
// 方法1:for循环(最灵活,可控制索引)
for (var i = 0; i < arr.length; i++) {
console.log(arr[i]); // 1,2,3,4
}
// 方法2:for...in循环(遍历索引,适合对象/数组)
for (var k in arr) {
console.log(arr[k]); // 1,2,3,4
}
// 方法3:forEach循环(数组专属,简洁)
arr.forEach(function(item) {
console.log(item); // 1,2,3,4
});
// ES6箭头函数简写
arr.forEach(item => console.log(item));
(5)数组方法:添加/删除元素
| 方法 | 功能 | 是否修改原数组 | 返回值 |
|---|---|---|---|
push(参数1...) |
在数组末尾添加元素 |
是 | 新数组长度 |
pop() |
删除数组最后一个元素 |
是 | 被删除的元素 |
unshift(参数1...) |
在数组开头添加一个或多个元素 | 是 | 新数组的长度 |
shift() |
删除数组第一个元素,无参数 | 是 | 被删除的元素(数组为空时返回undefined) |
bash
// 示例1:push() 末尾添加
var arr = [1,2,3];
var len1 = arr.push(4, 'hello');
console.log(arr); // [1,2,3,4,'hello']
console.log(len1); // 5(返回新长度)
// 示例2:pop() 末尾删除
var delItem1 = arr.pop();
console.log(arr); // [1,2,3,4]
console.log(delItem1); // 'hello'(返回被删除元素)
// 示例3:unshift() 开头添加
var len2 = arr.unshift(0, 'test');
console.log(arr); // [0,'test',1,2,3,4]
console.log(len2); // 6(返回新长度)
// 示例4:shift() 开头删除
var delItem2 = arr.shift();
console.log(arr); // ['test',1,2,3,4]
console.log(delItem2); // 0(返回被删除元素)
(6)数组方法:数组转换与拼接
这类方法用于数组与字符串的转换、多个数组的合并,部分方法不修改原数组,需接收返回值使用。
| 方法 | 功能 | 是否修改原数组 | 返回值 |
|---|---|---|---|
join(分隔符) |
将数组元素拼接为字符串,分隔符可选(默认逗号) | 否 | 拼接后的字符串 |
concat(数组1,数组2...) |
合并多个数组(或元素),生成新数组 | 否 | 合并后的新数组 |
bash
// 示例1:join() 数组转字符串
var arr1 = [1,2,3,4];
var str1 = arr1.join('-'); // 用连字符分隔
var str2 = arr1.join(); // 无参数,默认逗号
console.log(str1); // '1-2-3-4'
console.log(str2); // '1,2,3,4'
console.log(arr1); // [1,2,3,4](原数组不变)
// 示例2:concat() 合并数组
var arr2 = [5,6];
var arr3 = arr1.concat(arr2, 'a', true); // 可合并数组和单个元素
console.log(arr3); // [1,2,3,4,5,6,'a',true]
console.log(arr1); // [1,2,3,4](原数组不变)
(7)数组方法:截取与替换
slice用于截取数组片段,splice可实现截取、替换、添加元素(功能灵活,常用),注意两者对原数组的影响差异。
| 方法 | 功能 | 是否修改原数组 | 返回值 |
|---|---|---|---|
slice(开始索引, 结束索引) |
截取数组从开始索引到结束索引(含头不含尾),索引可负数(表示从末尾算) | 否 | 截取到的新数组 |
splice(开始索引, 删除个数, 新增元素...) |
从开始索引删除指定个数元素,可选在该位置添加新元素 | 是 | 被删除元素组成的数组(无删除则返回空数组) |
bash
// 示例1:slice() 截取数组
var arr = [1,2,3,4,5];
var newArr1 = arr.slice(1, 3); // 从索引1开始,到索引3结束(不含3)
var newArr2 = arr.slice(-2); // 负数索引,从末尾第2个元素开始截取到最后
console.log(newArr1); // [2,3]
console.log(newArr2); // [4,5]
console.log(arr); // [1,2,3,4,5](原数组不变)
// 示例2:splice() 删除元素
var delArr1 = arr.splice(2, 2); // 从索引2开始,删除2个元素
console.log(arr); // [1,2,5](原数组被修改)
console.log(delArr1); // [3,4](返回被删除元素)
// 示例3:splice() 替换元素(删除+添加)
var delArr2 = arr.splice(1, 1, 'a', 'b'); // 从索引1删1个元素,添加'a'和'b'
console.log(arr); // [1,'a','b',3,4,5]
console.log(delArr2); // [2](返回被删除元素)
// 示例4:splice() 仅添加元素(删除个数设为0)
var delArr3 = arr.splice(3, 0, 6, 7); // 从索引3开始,删0个,添加6和7
console.log(arr); // [1,2,3,'a','b',6,7,4,5]
console.log(delArr3); // [](无删除,返回空数组)
(8)数组方法:排序与反转
用于数组元素的排序和顺序反转,均会直接修改原数组。
| 方法 | 功能 | 是否修改原数组 | 返回值 |
|---|---|---|---|
reverse() |
反转数组元素的顺序 | 是 | 反转后的原数组 |
sort() |
默认按字符串Unicode编码排序,可传入比较函数自定义排序规则 | 是 | 排序后的原数组 |
bash
// 示例1:reverse() 反转数组
var arr1 = [1,2,3,4];
arr1.reverse();
console.log(arr1); // [4,3,2,1](原数组修改)
// 示例2:sort() 默认排序(字符串规则,存在问题)
var arr2 = [10, 2, 23];
arr2.sort();
console.log(arr2); // [10,2,23](按首字符Unicode排序,不符合数字排序预期)
// 示例3:sort() 传入比较函数(数字升序/降序)
// 升序:a - b < 0 → a排在b前面
arr2.sort(function(a, b) {
return a - b;
});
console.log(arr2); // [2,10,23]
// 降序:b - a < 0 → b排在a前面
arr2.sort(function(a, b) {
return b - a;
});
console.log(arr2); // [23,10,2]
// ES6箭头函数简写(升序)
arr2.sort((a, b) => a - b);
(9)数组方法:查找元素
用于查找数组中指定元素的索引或判断是否存在,不同方法适配不同场景。
| 方法 | 功能 | 是否修改原数组 | 返回值 |
|---|---|---|---|
indexOf(元素, 起始索引) |
从左到右查找元素,起始索引可选(默认0) | 找到返回对应索引,未找到返回-1 | 严格匹配(===),区分数据类型 |
lastIndexOf(元素) |
从右到左查找元素 | 找到返回对应索引,未找到返回-1 | 严格匹配(===),区分数据类型 |
bash
var arr = [1,2,3,2,4];
// 示例1:indexOf() 从左查找
var idx1 = arr.indexOf(2); // 默认从索引0开始
var idx2 = arr.indexOf(2, 2); // 从索引2开始查找
console.log(idx1); // 1
console.log(idx2); // 3
// 示例2:lastIndexOf() 从右查找
var idx3 = arr.lastIndexOf(2);
console.log(idx3); // 3(最右侧匹配元素的索引)
// 示例3:未找到元素返回-1
var idx4 = arr.indexOf(5);
console.log(idx4); // -1
// 示例4:严格匹配(区分类型)
var arr2 = [1, '1', 2];
console.log(arr2.indexOf(1)); // 0(匹配数字1)
console.log(arr2.indexOf('1')); // 1(匹配字符串'1')
补充 :ES6新增includes()方法,用于判断数组是否包含指定元素,返回布尔值(arr.includes(2) → true),同样严格匹配,使用更直观。
4.4 数据格式:JSON(轻量级数据交换格式)
JSON(JavaScript Object Notation)不是内置对象,而是通用数据格式,常用于前后端数据传输,语法和JS对象类似,但有严格规范。
(1)JSON语法规则
- 键名必须用
双引号包裹(JS对象可省略引号) - 值只能是
字符串、数字、布尔、null、数组、JSON对象(不能是函数、undefined) - 不能有多余
逗号(末尾不能加逗号)
bash
// 合法JSON格式
{
"name": "张三",
"age": 20,
"isStudent": true,
"hobbies": ["篮球", "编程"]
}
// 非法JSON格式(键名无引号、值含函数)
{
name: "张三",
sayHello: function() {}
}
(2)JSON与JS对象的转换
通过JSON全局对象的两个方法实现转换,是前后端交互的核心操作。
| 方法 | 功能 | 示例 |
|---|---|---|
JSON.parse(jsonStr) |
JSON字符串 → JS对象 | JSON.parse('{"name":"张三"}') |
JSON.stringify(obj) |
JS对象 → JSON字符串 | JSON.stringify({name:"张三"}) |
bash
// 1. JSON字符串转JS对象
var jsonStr = '{"name":"张三","age":20}';
var obj = JSON.parse(jsonStr);
console.log(obj.name); // 张三(可正常访问属性)
// 深拷贝技巧
let copy = JSON.parse(JSON.stringify(person));
// 2. JS对象转JSON字符串
var user = { name: "李四", age: 22 };
var jsonStr2 = JSON.stringify(user);
console.log(jsonStr2); // "{"name":"李四","age":22}"(字符串格式)
五、BOM对象:操作浏览器的接口
**BOM(Browser Object Model,浏览器对象模型)**是JS操作浏览器的接口,无官方标准,核心对象是window(全局对象,所有BOM属性/方法都挂载在window上,可省略window前缀)。
5.1 核心BOM对象
(1)window对象(全局对象)
window是JS全局作用域的顶层对象,所有全局变量、函数、内置对象都属于window。
bash
// 全局变量本质是window的属性
var msg = "Hello";
console.log(window.msg); // Hello
// 全局函数本质是window的方法
function sayHi() {
console.log("Hi");
}
window.sayHi(); // Hi
常用弹窗方法
| 方法 | 功能 | 特点 |
|---|---|---|
alert(内容) |
弹出警告框 | 无返回值,阻断页面执行 |
confirm(提示语) |
弹出确认框(确定/取消) | 返回布尔值(确定true/取消false) |
prompt(提示语,默认值) |
弹出输入框 | 返回用户输入内容(取消返回null) |
(2)location对象(地址栏信息)
用于获取或修改浏览器地址栏信息,实现页面跳转等功能。
| 属性/方法 | 功能 |
|---|---|
location.href |
获取当前页面完整URL,修改可实现跳转 |
location.reload() |
刷新当前页面(参数true强制刷新,忽略缓存) |
| location.assign(url) | 跳转到指定URL,可后退返回原页面 |
bash
// 1. 获取当前URL
console.log(location.href); // https://www.example.com
// 2. 跳转页面(两种方式)
location.href = "https://www.baidu.com"; // 直接修改href跳转
location.assign("https://www.baidu.com"); // 调用assign方法跳转
// 3. 刷新页面
location.reload(); // 普通刷新
location.reload(true); // 强制刷新
(3)history对象(浏览历史)
用于操作浏览器的浏览历史记录,仅能操作当前窗口的历史。
| 方法 | 功能 |
|---|---|
history.back() |
后退到上一页(等同于浏览器后退按钮) |
history.forward() |
前进到下一页(等同于浏览器前进按钮) |
history.go(n) |
跳转到指定历史记录(n为正数前进n页,负数后退n页,0刷新) |
(4)navigator对象(浏览器信息)
用于获取浏览器的基本信息,常用于浏览器兼容性判断。
bash
// 获取浏览器用户代理信息(包含浏览器版本、内核等)
console.log(navigator.userAgent); //'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36'
// 判断是否为移动设备(简单判断)
var isMobile = /Mobile|Android/.test(navigator.userAgent);
console.log(isMobile ? "移动设备" : "桌面设备");
六、DOM对象:操作网页元素的接口
DOM(Document Object Model,文档对象模型)是JS操作网页元素的接口,将HTML文档视为一个树形结构(DOM树),每个HTML标签都是一个DOM节点(元素节点、文本节点、属性节点)。
6.1 DOM树核心概念
- 文档节点(document):整个HTML文档的根节点,所有DOM操作都从document开始
- 元素节点(Element) :HTML标签(如
<div>、<p>、<button>) - 文本节点(Text):标签内的文本内容
- 属性节点(Attribute) :标签的属性(如
class、id、src)
6.2 核心操作:获取DOM元素
先获取到DOM元素,才能对其进行修改、删除等操作,常用获取方法如下:
| 方法 | 功能 | 返回值 |
|---|---|---|
getElementById(id值) |
通过id属性获取元素(id唯一) | 单个元素节点(未找到返回null) |
getElementsByClassName(类名) |
通过class属性获取元素 | HTMLCollection集合(类数组) |
getElementsByTagName(标签名) |
通过标签名获取元素 | HTMLCollection集合(类数组) |
querySelector(选择器) |
通过CSS选择器获取元素(ES6新增) | 第一个匹配的元素节点 |
querySelectorAll(选择器) |
通过CSS选择器获取所有匹配元素 | NodeList集合(类数组) |
bash
// 1. 通过id获取(最常用,高效)
var box = document.getElementById("box");
// 2. 通过class获取(返回集合,需遍历)
var items = document.getElementsByClassName("item");
console.log(items[0]); // 取第一个元素
// 3. 通过CSS选择器获取(灵活,推荐ES6使用)
var btn = document.querySelector("#btn"); // id选择器
var lis = document.querySelectorAll("ul li"); // 后代选择器
6.3 核心操作:修改DOM元素
(1)修改元素内容
| 属性/方法 | 功能 | 特点 |
|---|---|---|
innerHTML |
设置/获取元素内的HTML内容 | 支持HTML标签解析 |
innerText |
设置/获取元素内的文本内容 | 忽略HTML标签,只保留文本 |
bash
var box = document.getElementById("box");
// 1. 修改内容(支持HTML标签)
box.innerHTML = "<h3>修改后的标题</h3>";
// 2. 修改纯文本
box.innerText = "修改后的纯文本";
// 3. 获取内容
console.log(box.innerHTML);
(2)修改元素样式
通过style属性修改元素行内样式,属性名采用驼峰命名法(如backgroundColor替代background-color)。
bash
var box = document.getElementById("box");
// 1. 修改单个样式
box.style.width = "200px";
box.style.backgroundColor = "red";
box.style.fontSize = "18px";
// 2. 通过class修改样式(推荐,分离样式和脚本)
box.className = "active"; // 替换原有class
box.classList.add("new-class"); // 新增class
box.classList.remove("active"); // 移除class
(3)修改元素属性
直接通过元素节点的属性名修改,或使用setAttribute()/getAttribute()方法。
bash
var img = document.querySelector("img");
// 1. 直接修改属性
img.src = "new-img.jpg";
img.alt = "新图片";
// 2. 用方法修改属性
img.setAttribute("title", "图片标题"); // 设置属性
console.log(img.getAttribute("src")); // 获取属性值
img.removeAttribute("alt"); // 移除属性
6.4 核心操作:添加/删除DOM元素
bash
// 1. 创建新元素
var newDiv = document.createElement("div");
newDiv.innerText = "新创建的div";
newDiv.style.color = "blue";
// 2. 添加元素到页面(插入到body末尾)
document.body.appendChild(newDiv);
// 3. 插入到指定元素前面
var box = document.getElementById("box");
document.body.insertBefore(newDiv, box); // 把newDiv插入到box前面
// 4. 删除元素(需通过父元素删除)
document.body.removeChild(newDiv);
6.5 核心操作:DOM事件(元素交互)
事件是用户与网页的交互行为(如点击、鼠标移动、键盘输入),通过绑定事件处理器,可让元素响应交互。
(1)常用事件类型
- onclick:点击事件
- onmouseover:鼠标移入事件
- onmouseout:鼠标移出事件
- onkeyup:键盘松开事件
- onload:页面加载完成事件
(2)事件绑定方式
bash
var btn = document.getElementById("btn");
// 方式1:行内事件(不推荐,耦合度高)
// <button onclick="handleClick()">按钮</button>
function handleClick() {
alert("按钮被点击了");
}
// 方式2:DOM0级事件(直接赋值)
btn.onclick = function() {
console.log("DOM0级点击事件");
};
// 方式3:DOM2级事件(addEventListener,推荐,可绑定多个事件)
btn.addEventListener("click", function() {
console.log("DOM2级点击事件1");
});
btn.addEventListener("click", function() {
console.log("DOM2级点击事件2");
});
// 移除DOM2级事件(需用命名函数)
function handleBtnClick() {
console.log("可移除的事件");
}
btn.addEventListener("click", handleBtnClick);
btn.removeEventListener("click", handleBtnClick);
注意:事件处理函数中的this,指向绑定事件的DOM元素,可通过this操作当前元素。
第七章:实用技巧与最佳实践
7.1 调试技巧
bash
// 1. 使用debugger语句
function calculate() {
debugger; // 执行到这里会暂停
let result = 10 * 5;
return result;
}
// 2. 条件断点
console.log("调试信息");
// 在开发者工具中右键行号添加条件断点
// 3. 性能分析
console.time("操作耗时");
// 执行一些代码
console.timeEnd("操作耗时"); // 显示执行时间
7.2 代码组织
bash
// 立即执行函数(IIFE)
(function() {
// 私有变量,不会污染全局
let privateVar = "私有";
console.log(privateVar);
})();
// 模块模式
let myModule = (function() {
let privateVar = "私有";
function privateMethod() {
console.log(privateVar);
}
return {
publicMethod: function() {
privateMethod();
}
};
})();
myModule.publicMethod();
7.3 错误处理
bash
// 1. try...catch
try {
let result = riskyOperation();
} catch (error) {
console.error("出错啦:", error);
// 优雅降级
showFallbackUI();
} finally {
console.log("无论如何都会执行");
}
// 2. 自定义错误
function validateAge(age) {
if (age < 0) {
throw new Error("年龄不能为负数");
}
if (age > 150) {
throw new Error("年龄不现实");
}
}
// 3. Promise错误处理
fetch("https://api.example.com/data")
.then(response => response.json())
.catch(error => console.error("请求失败", error));
常用资源推荐
- 官方文档:MDN Web Docs
- 在线练习:freeCodeCamp
- 代码挑战:Codewars
- 视频教程:JavaScript.info