JavaScript
JavaScript 概述
JavaScript,简称 JS,是一种主要运行在浏览器中的脚本语言。它可以读取和修改页面内容、响应用户操作、发送网络请求,并实现动态交互效果。
现代 JavaScript 也可以运行在服务器或其他运行环境中,但本章主要讨论浏览器中的 JavaScript。
JavaScript 与 Java 的区别
JavaScript 和 Java 名称相似,但它们是两种不同的编程语言。
| 对比项 | Java | JavaScript |
|---|---|---|
| 类型系统 | 静态类型,变量类型通常在编译时确定 | 动态类型,变量可以保存不同类型的值 |
| 常见运行方式 | 编译为字节码后由 JVM 执行 | 由 JavaScript 引擎解析、编译并执行 |
| 主要应用 | 后端、桌面、Android 等 | Web 页面交互、前端开发、服务端开发等 |
| 面向对象方式 | 基于类 | 以原型机制为基础,也支持 class 语法 |
Java 最初由 Sun 公司开发,后来由 Oracle 维护;JavaScript 最初由网景公司开发。
JavaScript 的组成
浏览器中的 JavaScript 开发通常涉及以下部分:
-
ECMAScript:规定 JavaScript 的核心语法、类型、运算符、对象和语句等。
-
DOM:Document Object Model,文档对象模型,用于操作 HTML 文档。
-
BOM:Browser Object Model,浏览器对象模型,用于操作浏览器窗口、地址、历史记录和定时器等。
-
事件:浏览器会在点击、输入、加载等操作发生时触发事件,JavaScript 可以注册处理函数。
JavaScript 的使用方式
内部脚本
少量 JavaScript 可以写在 HTML 页面的 <script> 标签中:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>内部脚本</title>
<script>
console.log("页面脚本开始执行");
</script>
</head>
<body>
页面内容
</body>
</html>外部脚本
代码较多时,应保存为独立的 .js 文件,再通过 src 属性引入:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>外部脚本</title>
<script src="js文件地址"></script>
</head>
<body>
页面内容
</body>
</html>带有 src 属性的 <script> 标签仍然需要结束标签。
变量与数据类型
JavaScript 有数据类型,但变量本身不需要声明固定类型。变量保存的值发生变化时,其类型也可能改变,这称为动态类型。
常见数据类型
本阶段常见类型如下:
-
string:字符串。 -
number:数字,包括整数和小数。 -
boolean:布尔值,即true和false。 -
undefined:变量已声明但尚未赋值。 -
null:表示主动设置的空值。
此外,JavaScript 还提供对象类型,以及 bigint、symbol 等类型。
定义变量
旧版代码常使用 var:
var name = "张三";
var age = 20;
var sex = "男";
alert("姓名:" + name + ",年龄:" + age + ",性别:" + sex);
console.log("name 的类型:" + typeof name);
console.log("age 的类型:" + typeof age);
console.log("sex 的类型:" + typeof sex);
现代 JavaScript 通常优先使用 let 和 const:
const name = "张三";
let age = 20;
age = 21;
-
const:变量绑定不能重新赋值。 -
let:变量可以重新赋值,并具有块级作用域。
流程控制
分支语句
JavaScript 常用的分支语句包括 if、if...else 和 switch。
const score = 85;
if (score >= 60) {
console.log("及格");
} else {
console.log("不及格");
}
循环语句
常用循环包括 for、while 和 do...while。
for (let i = 0; i < 5; i++) {
console.log(i);
}
运算符与类型转换
相等比较
JavaScript 提供 == 和 ===:
const value1 = "10";
const value2 = 10;
console.log(value1 == value2); // true
console.log(value1 === value2); // false
-
==:比较前可能进行隐式类型转换。 -
===:不进行隐式类型转换,要求类型和值都相等。
实际开发通常优先使用 === 和 !==,减少隐式转换带来的歧义。
数值运算
Java 中使用两个整数相除时会执行整数除法,而 JavaScript 的普通数值统一使用 number 类型:
const value = 123;
console.log((value / 1000) * 1000); // 123
JavaScript 的 number 使用浮点数表示,因此虽然本例得到 123,但某些小数运算仍可能出现浮点精度误差。例如 0.1 + 0.2 的结果并不严格等于 0.3。
字符串运算
+ 在存在字符串操作数时通常执行字符串拼接:
console.log("123" + "23"); // "12323"
- 不支持字符串拼接。JavaScript 会尝试把字符串转换为数字:
const value1 = "123";
const value2 = "23";
console.log(value1 - value2); // 100
无法转换为有效数字时,结果通常为 NaN。
布尔转换
在条件判断中,JavaScript 会把值转换为布尔值。0、空字符串、null、undefined 和 NaN 等值会被视为假值,其他大多数值会被视为真值。
const value1 = true;
const value2 = false;
console.log(value1 == 1); // true,发生了类型转换
console.log(value1 === 1); // false,类型不同
console.log(value2 == 0); // true,发生了类型转换
使用 DOM 输出内容
可以借助 document 对象操作页面。下面的示例动态生成九九乘法表:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>九九乘法表</title>
</head>
<body>
<div id="tableBox"></div>
<script>
let html = "<table border='1'>";
for (let i = 1; i <= 9; i++) {
html += "<tr>";
for (let j = 1; j <= i; j++) {
html += "<td>" + j + "×" + i + "=" + i * j + "</td>";
}
html += "</tr>";
}
html += "</table>";
document.getElementById("tableBox").innerHTML = html;
</script>
</body>
</html>document.write() 也可以向文档写入内容,但页面加载完成后再调用可能覆盖整个页面,因此通常优先修改指定 DOM 元素。
JavaScript 数组
JavaScript 数组长度可变,并且同一数组中可以保存不同类型的值。
使用数组字面量
const array = [10, 20, 30];
for (let i = 0; i < array.length; i++) {
console.log("数组索引:" + i + ",数组元素:" + array[i]);
}
创建指定长度的数组
const array = new Array(3);
array[0] = 100;
array[1] = 200;
array[2] = 300;
new Array(3) 创建的是长度为 3 的空槽数组,并不是包含数字 3 的数组。
使用构造函数初始化元素
const array = new Array(1000, 2000, 3000);
for (let i = 0; i < array.length; i++) {
console.log("数组索引:" + i + ",数组元素:" + array[i]);
}
常用数组属性和方法
-
length:数组长度。 -
concat():连接数组,并返回新数组。 -
join():按指定分隔符连接元素,并返回字符串。 -
push():在数组末尾添加元素。 -
pop():删除并返回数组末尾的元素。 -
reverse():反转当前数组中的元素顺序。
const array1 = [10, 20, 30];
const array2 = new Array(100, 200, 300);
array1.push(1);
array1.push(2);
array1.push(3);
array2.pop();
const array3 = array1.concat(array2);
console.log("数组长度:" + array3.length);
array3.reverse();
const text = array3.join("_");
console.log("数组转字符串:" + text);JavaScript 函数
函数声明
function add(value1, value2) {
return value1 + value2;
}
函数表达式
const multiply = function (value1, value2) {
return value1 * value2;
};
箭头函数
const divide = (value1, value2) => value1 / value2;
调用示例:
let result = add(10, 20);
result = multiply(10, 20);
result = divide(10, 20);
console.log("结果:" + result);
函数参数和返回值不需要在语法中声明固定类型,但运行时的值仍然具有类型。
动态创建函数
JavaScript 可以使用 Function 构造函数动态创建函数:
const parameters = "name, age";
const body = "console.log('name:' + name + ',age:' + age);";
const createdFunction = new Function(parameters, body);
createdFunction("张三", 20);
这种方式需要在运行时解析字符串,通常不如普通函数清晰,并可能带来安全风险,因此实际开发中应谨慎使用。
脚本位置与页面加载
如果脚本在目标元素之前执行,相关 DOM 元素可能尚未创建。常见解决方式包括:
-
将
<script>放在<body>结束标签之前。 -
在外部脚本上使用
defer属性。 -
监听
DOMContentLoaded或load事件。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>页面加载</title>
<script>
window.onload = function () {
const input = document.getElementById("v1");
console.log("编辑框对象:", input);
console.log("编辑框中的数据:" + input.value);
};
</script>
</head>
<body>
数据:<input id="v1" type="text" value="这是一个数据" />
</body>
</html>原代码直接输出元素对象时,得到的是对象描述;读取输入框内容需要访问其 value 属性。
JavaScript 与函数重载
JavaScript 不支持 Java 式的函数重载。同一作用域中重复声明同名函数时,后面的定义通常会覆盖前面的定义。
可以根据参数数量或参数类型在一个函数内部执行不同逻辑,这只是手动分派,并不是真正的函数重载:
function showInfo() {
if (arguments.length === 0) {
console.log("无参数调用");
} else if (arguments.length === 1) {
console.log("一个参数:" + arguments[0]);
} else if (arguments.length === 2) {
console.log("两个参数:" + arguments[0] + "," + arguments[1]);
}
}
showInfo(100, 200);BOM 浏览器对象模型
BOM 用于操作浏览器窗口及其相关功能,例如地址栏、定时器、弹窗和窗口跳转。浏览器中的 window 是全局对象,许多方法可以省略 window. 前缀。
定时器
-
setInterval():每隔指定时间重复执行函数。 -
clearInterval():停止由setInterval()创建的定时器。 -
setTimeout():等待指定时间后执行一次函数。 -
clearTimeout():取消尚未执行的延时任务。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>定时器</title>
<script>
let intervalId;
let timeoutId;
function updateTime() {
const date = new Date();
const span = document.getElementById("spanId");
span.innerText = date.toLocaleString();
}
function startInterval() {
if (intervalId === undefined) {
intervalId = setInterval(updateTime, 1000);
}
}
function stopInterval() {
clearInterval(intervalId);
intervalId = undefined;
}
function startTimeout() {
timeoutId = setTimeout(function () {
alert("定时任务开始执行");
}, 3000);
}
function stopTimeout() {
clearTimeout(timeoutId);
}
</script>
</head>
<body>
<div style="width: 600px; height: 300px; text-align: center;">
<span id="spanId"></span>
<hr />
<button onclick="startInterval()">开始更新时间</button>
<button onclick="stopInterval()">停止更新时间</button>
<hr />
<button onclick="startTimeout()">启动延时任务</button>
<button onclick="stopTimeout()">取消延时任务</button>
</div>
</body>
</html>向定时器传入函数比传入字符串更清晰,也能避免额外的字符串解析。
信息弹窗
-
alert():显示提示信息。 -
confirm():显示确认框,返回布尔值。 -
prompt():显示输入框,返回输入的字符串或null。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>弹窗示例</title>
<script>
function deleteData() {
if (confirm("是否确认执行删除操作?")) {
console.log("执行删除功能");
}
}
function calculate() {
const number1 = prompt("请输入第一个数");
const number2 = prompt("请输入第二个数");
if (number1 !== null && number2 !== null) {
console.log("结果:" + (Number(number1) + Number(number2)));
}
}
</script>
</head>
<body>
<button onclick="deleteData()">删除</button>
<button onclick="calculate()">运算</button>
</body>
</html>打开新窗口
父页面:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>父窗口</title>
<script>
function createWindow() {
window.open("demo9.html", "", "width=600,height=700");
}
</script>
</head>
<body>
姓名:<input type="text" id="inp_name" /><br />
年龄:<input type="text" id="inp_age" /><br />
<button onclick="createWindow()">选择数据</button>
</body>
</html>子页面可以通过 window.opener 访问打开它的父窗口:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>子窗口</title>
<script>
function selectData() {
const selected = document.querySelector('input[name="select"]:checked');
if (!selected || !window.opener) {
return;
}
const row = selected.closest("tr");
const cells = row.children;
const name = cells[1].innerText;
const age = cells[2].innerText;
window.opener.document.getElementById("inp_name").value = name;
window.opener.document.getElementById("inp_age").value = age;
}
</script>
</head>
<body>
<table border="1" width="500">
<tr>
<th>选择</th>
<th>姓名</th>
<th>年龄</th>
</tr>
<tr>
<td><input type="radio" name="select" checked /></td>
<td>刘备</td>
<td>20</td>
</tr>
<tr>
<td><input type="radio" name="select" /></td>
<td>关羽</td>
<td>19</td>
</tr>
<tr>
<td><input type="radio" name="select" /></td>
<td>张飞</td>
<td>18</td>
</tr>
</table>
<button onclick="selectData()">获取选择的数据</button>
</body>
</html>浏览器可能拦截并非由用户操作直接触发的新窗口,跨源页面也不能任意访问彼此的 DOM。
页面地址
window.location 表示当前页面地址,可以通过修改 location.href 进行跳转:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>页面跳转</title>
<script>
function visitAddress() {
const address = document.getElementById("inputId").value;
location.href = address;
}
</script>
</head>
<body>
访问地址:<input type="text" id="inputId" />
<button onclick="visitAddress()">访问</button>
</body>
</html>
喜欢的话,留下你的评论吧~