1. 介绍
JavaScript 是 前端开发人员必须学习的 3 门语言中的一门:
- HTML 定义了网页的内容
- CSS 描述了网页的布局
- JavaScript 控制了网页的行为
接下来开始详解JavaScript。
2.引入方法
js有两种导入方式,一种是内部脚本:直接在html页面中的<script>xxx</script>标签中写入Javascript代码,另一种是外部脚本:创建 .js 文件然后使用<script src = "xxx.js"></script>引入这个文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<script>
document.writeln("hello world ");
</script>
<script src="test.js"></script>
<body>
</body>
</html>
3. JavaScript基础语法
3.1 书写语法
-
区分大小写:与 Java 一样,变量名、函数名以及其他一切东西都是区分大小写的
-
每行结尾的分号可有可无
如果一行上写多个语句时,必须加分号用来区分多个语句。
-
注释
-
单行注释:// 注释内容
-
多行注释:/* 注释内容 */
注意:JavaScript 没有文档注释
-
-
大括号表示代码块
下面语句大家肯定能看懂,和 java 一样 大括号表示代码块。
if (count == 3) { alert(count); }
3.2 输出语句
js 可以通过以下方式进行内容的输出,只不过不同的语句输出到的位置不同
-
使用 window.alert() 写入警告框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> window.alert("Hello Javascript ! ! !");//写入警告框 </script> </body> </html>
上面代码通过浏览器打开,我们可以看到如下图弹框效果
-
-
使用 document.write() 写入 HTML 输出
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> document.write("hello js 2~");//写入html页面 </script> </body> </html>
上面代码通过浏览器打开,我们可以在页面上看到
document.write(内容)
输出的内容 -
-
使用 console.log() 写入浏览器控制台
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> console.log("hello js 3");//写入浏览器的控制台 </script> </body> </html>
上面代码通过浏览器打开,我们可以在不能页面上看到
console.log(内容)
输出的内容,它是输出在控制台了,而怎么在控制台查看输出的内容呢?在浏览器界面按F12
就可以看到下图的控制台
3.3 变量
JavaScript 中用 var 关键字(variable 的缩写)来声明变量。格式 var 变量名 = 数据值;
。而在JavaScript 是一门弱类型语言,变量==可以存放不同类型的值==;如下在定义变量时赋值为数字数据,还可以将变量的值改为字符串类型的数
var test = 20;
test = "张三";
js 中的变量名命名也有如下规则,和java语言基本都相同
-
组成字符可以是任何字母、数字、下划线(_)或美元符号($)
-
数字不能开头
-
建议使用驼峰命名
JavaScript 中 var
关键字有点特殊,有以下地方和其他语言不一样
-
作用域:全局变量
{ var age = 20; } alert(age); // 在代码块中定义的age 变量,在代码块外边还可以使用
-
变量可以重复定义
{ var age = 20; var age = 30;//JavaScript 会用 30 将之前 age 变量的 20 替换掉 } alert(age); //打印的结果是 30
针对如上的问题,ECMAScript 6 新增了 let
关键字来定义变量。它的用法类似于 var
,但是所声明的变量,只在 let
关键字所在的代码块内有效,且不允许重复声明。
例如:
{
let age = 20;
}
alert(age);
运行上面代码,浏览器并没有弹框输出结果,说明这段代码是有问题的。通过 F12
打开开发者模式可以看到如下错误信息:
而如果在代码块中定义两个同名的变量,IDEA 开发工具就直接报错了
ECMAScript 6 新增了 const关键字,用来声明一个只读的常量。一旦声明,常量的值就不能改变。通过下面的代码看一下常用的特点就可以了:
如图,常量重新赋值就会报错。
3.4 数据类型
JavaScript 中提供了两类数据类型:原始类型 和 引用类型。
使用 typeof 运算符可以获取数据类型
alert(typeof age);
以弹框的形式将 age 变量的数据类型输出
原始数据类型:
-
number:数字(整数、小数、NaN(Not a Number))
var age = 20; var price = 99.8; alert(typeof age); // 结果是 : number alert(typeof price);// 结果是 : number
==注意:== NaN是一个特殊的number类型的值,后面用到再说
-
string:字符、字符串,单双引皆可
var ch = 'a'; var name = '张三'; var addr = "北京"; alert(typeof ch); //结果是 string alert(typeof name); //结果是 string alert(typeof addr); //结果是 string
==注意:==在 js 中 双引号和单引号都表示字符串类型的数据
-
boolean:布尔。true,false
var flag = true; var flag2 = false; alert(typeof flag); //结果是 boolean alert(typeof flag2); //结果是 boolean
-
null:对象为空
var obj = null; alert(typeof obj);//结果是 object
为什么打印上面的 obj 变量的数据类型,结果是object;这个官方给出了解释,下面是从官方文档截的图:
-
-
undefined:当声明的变量未初始化时,该变量的默认值是 undefined
var a ; alert(typeof a); //结果是 undefined
3.5 运算符
JavaScript 提供了如下的运算符。大部分和 Java语言 都是一样的,不同的是 JS 关系运算符中的 ==
和 ===
,一会我们只演示这两个的区别,其他运算符将不做演示
-
一元运算符:++,--
-
算术运算符:+,-,*,/,%
-
赋值运算符:=,+=,-=…
-
关系运算符:>,<,>=,<=,!=,\==,===…
-
逻辑运算符:&&,||,!
-
三元运算符:条件表达式 ? true_value : false_value
3.5.1 == 和 === 的区别
概述:
-
==:
-
判断类型是否一样,如果不一样,则进行类型转换
-
再去比较其值
-
-
===:js 中的全等于
-
判断类型是否一样,如果不一样,直接返回false
-
再去比较其值
-
代码:
let age1 = 20;
let age2 = "20";
alert(age1 == age2);// true
alert(age1 === age2);// false
3.5.2 类型转换
上述讲解 ==
运算符时,发现会进行类型转换,所以接下来我们来详细的讲解一下 JavaScript 中的类型转换。
-
其他类型转为number
-
string 转换为 number 类型:按照字符串的字面值,转为数字。如果字面值不是数字,则转为NaN
将 string 转换为 number 有两种方式:
-
使用
+
正号运算符:let str = +"20"; alert(str + 1) //21
-
使用
parseInt()
函数(方法):let str = "20"; alert(parseInt(str) + 1);
==建议使用
parseInt()
函数进行转换。== -
-
boolean 转换为 number 类型:true 转为 1,false转为 0
let flag = +false; alert(flag); // 0
-
-
其他类型转为boolean
-
number 类型转换为 boolean 类型:0和NaN转为false,其他的数字转为true
-
string 类型转换为 boolean 类型:空字符串转为false,其他的字符串转为true
-
null类型转换为 boolean 类型是 false
-
undefined 转换为 boolean 类型是 false
代码如下:
// let flag = 3; // let flag = ""; let flag = undefined; if(flag){ alert("转为true"); }else { alert("转为false"); }
-
使用场景:
在 Java 中使用字符串前,一般都会先判断字符串不是null,并且不是空字符才会做其他的一些操作,JavaScript也有类型的操作,代码如下:
let str = "abc";
//健壮性判断
if (str != null && str.length > 0) {
alert("转为true");
} else {
alert("转为false");
}
但是由于 JavaScript 会自动进行类型转换,所以上述的判断可以进行简化,代码如下:
let str = "abc";
//健壮性判断
if(str){
alert("转为true");
}else {
alert("转为false");
}
3.6 流程控制语句
JavaScript 中提供了和 Java 一样的流程控制语句,如下
-
if
-
switch
-
for
-
while
-
dowhile
3.6.1 if 语句
let count = 3;
if (count == 3) {
alert(count);
}
3.6.2 switch 语句
let num = 3;
switch (num) {
case 1:
alert("星期一");
break;
case 2:
alert("星期二");
break;
case 3:
alert("星期三");
break;
case 4:
alert("星期四");
break;
case 5:
alert("星期五");
break;
case 6:
alert("星期六");
break;
case 7:
alert("星期日");
break;
default:
alert("输入的星期有误");
break;
}
3.6.3 for 循环语句
let sum = 0;
for (let i = 1; i <= 100; i++) { //建议for循环小括号中定义的变量使用let
sum += i;
}
alert(sum);
3.6.4 while 循环语句
let sum = 0;
let i = 1;
while (i <= 100) {
sum += i;
i++;
}
alert(sum);
3.6.5 dowhile 循环语句
let sum = 0;
let i = 1;
do {
sum += i;
i++;
}
while (i <= 100);
alert(sum);
3.7 函数
函数(就是Java中的方法)是l被设计为执行特定任务的代码块;JavaScript 函数通过 function 关键词进行定义。
3.7.1 定义格式
函数定义格式有两种:
-
方式1
function 函数名(参数1,参数2..){ 要执行的代码 }
-
方式2
let 函数名 = function (参数列表){ 要执行的代码 }
==注意:==
形式参数不需要类型。因为JavaScript是弱类型语言
function add(a, b){ return a + b; }上述函数的参数 a 和 b 不需要定义数据类型,因为在每个参数前加上 var 也没有任何意义。
返回值也不需要定义类型,可以在函数内部直接使用return返回即可
3.7.2 函数调用
函数调用函数:
函数名称(实际参数列表);
eg:let result = add(10,20);
注意:
JS中,函数调用可以传递任意个数参数
例如
let result = add(1,2,3);
它是将数据 1 传递给了变量a,将数据 2 传递给了变量 b,而数据 3 没有变量接收。
4. JavaScript常用对象
JavaScript 提供了很多对象供使用者来使用。这些对象总共分类三类
基本对象 | BOM对象 | DOM对象 |
Array | Window | Document |
Boolean | Navigator | Anchor |
String | Screen | Area |
Number | History | |
Date | Location | |
Math | ||
RegExp | ||
Function |
4.1 基本对象
接下来是基本对象的详细介绍和使用方式
4.1.1 Array(数组)
用于存储和操作多个值的有序集合。它提供了许多用于操作数组元素的方法,如push、pop、slice、forEach等
- 创建数组:使用数组字面量或构造函数。
// 使用数组字面量创建数组 const numbers = [1, 2, 3, 4, 5]; // 使用构造函数创建数组 const fruits = new Array('apple', 'banana', 'orange');
- 访问数组元素:
console.log(numbers[0]); // 输出:1 console.log(fruits.length); // 输出:3
- 数组方法示例:
numbers.push(6); // 在末尾添加元素 fruits.pop(); // 移除末尾的元素 numbers.splice(2, 1); // 从索引2开始移除1个元素 fruits.join(', '); // 将数组元素以逗号分隔的字符串形式返回
4.1.2. Boolean(布尔)
用于表示真(true)或假(false)的逻辑值的对象。它提供了一些用于逻辑运算的方法,如逻辑与(&&)、逻辑或(||)等。
- 创建布尔值:
const isTrue = true; const isFalse = false;
- 逻辑运算示例:
const result = isTrue && isFalse; // 逻辑与运算 console.log(result); // 输出:false const result2 = isTrue || isFalse; // 逻辑或运算 console.log(result2); // 输出:true
4.1.3. String(字符串)
用于表示和操作文本数据的对象。它提供了许多用于处理字符串的方法,如charAt、toUpperCase、substring等。
- 创建字符串:
const message = 'Hello, world!';
- 字符串方法示例:
message.length; // 字符串长度 message.toUpperCase(); // 转为大写 message.toLowerCase(); // 转为小写 message.indexOf('world'); // 查找子串的索引 message.substring(0, 5); // 获取子串
4.1.4 Number(数字)
用于表示和处理数字的对象。它提供了许多用于进行数学运算和数字转换的方法,如toFixed、toString、Math等。
- 创建数字:
const age = 25;
- 数字方法示例:
age.toString(); // 转为字符串 Math.random(); // 生成一个0到1之间的随机数 Math.floor(3.7); // 向下取整,输出:3 Math.ceil(3.2); // 向上取整,输出:4
4.1.5 Date(日期)
用于表示和操作日期和时间的对象。它提供了方法来获取和设置日期、进行日期运算、格式化日期等。
- 创建日期对象:
const now = new Date();
- 日期方法示例:
now.getFullYear(); // 获取年份 now.getMonth(); // 获取月份(0-11,0代表一月) now.getDate(); // 获取日期 now.getHours(); // 获取小时 now.getMinutes(); // 获取分钟
4.1.6 Math(数学)
提供了一组用于数学运算的静态方法和常量,如Math.floor、Math.random、Math.PI等。
例子:
Math.random(); // 返回0到1之间的随机数
Math.floor(3.7); // 向下取整,返回3
Math.ceil(3.2); // 向上取整,返回4
4.1.7 RegExp(正则表达式)
用于模式匹配和文本搜索的对象。它提供了一组用于创建和操作正则表达式的方法,如test、exec等。
- 创建正则表达式对象:
const pattern = /hello/;
- 正则表达式方法示例:
pattern.test('hello world'); // 匹配测试,返回true 'hello world'.match(pattern); // 返回匹配到的数组
4.1.8 Function(函数)
用于定义可执行的代码块,并可以传递参数并返回值。函数本身也是一个对象,可以存储和传递。
- 创建函数:
function sayHello() { console.log('Hello!'); } const addNumbers = function(num1, num2) { return num1 + num2; };
- 函数调用:
sayHello(); // 输出:Hello! const sum = addNumbers(3, 5); // 赋值为8
4.2 BOM 对象(浏览器对象模型)
4.2.1 Window(窗口)
- Window对象表示浏览器中打开的窗口或标签页。
- 使用代码示例:
// 弹出对话框 window.alert('Hello World!'); // 打开新窗口 window.open('https://www.example.com', '_blank'); // 关闭当前窗口 window.close(); // 设置定时器 window.setTimeout(function() { console.log('定时器触发!'); }, 5000);
4.2.2 Navigator(导航器)
- Navigator对象提供有关浏览器的信息。
- 使用代码示例:
// 获取浏览器名称 const browserName = window.navigator.userAgent; // 检测浏览器是否支持某个特性 const isGeolocationSupported = 'geolocation' in window.navigator; // 检测当前网络是否在线 const isOnline = window.navigator.onLine;
4.2.3 Screen(屏幕)
- Screen对象表示用户的屏幕信息。
- 使用代码示例:
// 获取屏幕宽度和高度 const screenWidth = window.screen.width; const screenHeight = window.screen.height; // 获取屏幕可用宽度和高度(去除任务栏或工具栏等) const availableScreenWidth = window.screen.availWidth; const availableScreenHeight = window.screen.availHeight; // 获取屏幕像素密度(DPI,每英寸的像素数) const screenPixelDensity = window.screen.pixelDepth;
4.2.4 History(历史记录)
- History对象保存用户在浏览器窗口中访问的URL历史记录。
- 使用代码示例:
// 后退一页 window.history.back(); // 前进一页 window.history.forward(); // 前进两页(相对于当前页面) window.history.go(2); // 获取当前历史记录中的URL数量 const urlCount = window.history.length;
4.2.5 Location(位置)
- Location对象表示当前加载的文档的URL信息。
- 使用代码示例:
// 获取当前URL const currentURL = window.location.href; // 加载新的URL window.location.href = 'https://www.example.com'; // 获取当前页面的域名 const domain = window.location.hostname; // 获取当前页面的路径名 const path = window.location.pathname; // 重新加载当前页面(刷新) window.location.reload();
4.3 DOM对象(文档对象模型)
4.3.1 Document(文档)
- Document对象表示整个HTML文档,它是DOM的根节点。
-
作用:JavaScript 通过 DOM, 就能够对 HTML进行操作了
- 改变 HTML 元素的内容
- 改变 HTML 元素的样式(CSS)
- 对 HTML DOM 事件作出反应
- 添加和删除 HTML 元素
Document
对象中提供了以下获取Element
元素对象的函数
-
getElementById()
:根据id属性值获取,返回单个Element对象 -
getElementsByTagName()
:根据标签名称获取,返回Element对象数组 -
getElementsByName()
:根据name属性值获取,返回Element对象数组 -
getElementsByClassName()
:根据class属性值获取,返回Element对象数组
- 使用代码示例:
// 获取文档标题 const title = document.title; // 获取文档中的所有段落元素 const paragraphs = document.getElementsByTagName('p'); // 获取文档中ID为"myElement"的元素 const element = document.getElementById('myElement'); // 创建新的元素节点 const newElement = document.createElement('div'); // 将新的元素节点添加到文档中 document.body.appendChild(newElement);
4.3.2 Anchor(锚点)
- Anchor对象表示HTML文档中的锚点(链接)元素。
- 使用代码示例:
// 获取具有ID为"myLink"的锚点元素 const link = document.getElementById('myLink'); // 获取锚点的URL const href = link.href; // 设置锚点的目标位置 link.target = '_blank'; // 添加点击事件监听器 link.addEventListener('click', function(event) { event.preventDefault(); // 阻止默认行为 console.log('锚点被点击!'); });
4.3.3 Area(图像映射区域)
- Area对象表示HTML文档中图像映射的区域。
- 使用代码示例:
// 获取所有图像映射区域 const areas = document.getElementsByTagName('area'); // 获取第一个图像映射区域的坐标 const coords = areas[0].coords; // 获取第一个图像映射区域的目标URL const targetURL = areas[0].href; // 添加鼠标移入事件监听器 areas[0].addEventListener('mouseover', function() { console.log('鼠标移入图像映射区域!'); });
5. 事件
事件绑定:
JavaScript 提供了两种事件绑定方式:
-
方式一:通过 HTML标签中的事件属性进行绑定
如下面代码,有一个按钮元素,我们是在该标签上定义
事件属性
,在事件属性中绑定函数。onclick
就是单击事件
的事件属性。onclick='on()'
表示该点击事件绑定了一个名为on()
的函数<input type="button" onclick='on()’>
下面是点击事件绑定的
on()
函数function on(){ alert("我被点了"); }
-
方式二:通过 DOM 元素属性绑定
如下面代码是按钮标签,在该标签上我们并没有使用
事件属性
,绑定事件的操作需要在 js 代码中实现<input type="button" id="btn">
下面 js 代码是获取了
id='btn'
的元素对象,然后将onclick
作为该对象的属性,并且绑定匿名函数。该函数是在事件触发后自动执行document.getElementById("btn").onclick = function (){ alert("我被点了"); }
以下是主要的事件:
事件属性名 | 说明 |
---|---|
onclick | 鼠标单击事件 |
onblur | 元素失去焦点 |
onfocus | 元素获得焦点 |
onload | 某个页面或图像被完成加载 |
onsubmit | 当表单提交时触发该事件 |
onmouseover | 鼠标被移到某元素之上 |
onmouseout | 鼠标从某元素移开 |
6. 闭包
闭包的定义
闭包是指函数以及其相关的词法环境的组合。它包含两个部分:
- 函数:在JavaScript中,函数是一等公民,可以作为值被传递和赋值。
- 词法环境:词法环境是函数在定义时创建的作用域,在函数闭包中可以访问的变量集合。
闭包的特性和优势
闭包具有以下特性和优势:
- 访问外部变量:闭包允许函数访问其定义时的词法作用域中的变量,即使函数在其他地方执行也是如此。
- 保护变量:由于闭包中的变量无法从外部直接访问,可以将其用于创建私有变量和私有方法。
- 存储状态:通过保留对词法环境的引用,闭包可以存储函数执行时的状态,这对于处理异步操作或延迟执行非常有用。
- 实现模块化:闭包可以将一组相关的变量和方法封装在一个作用域内,形成一个独立且可复用的模块。
闭包的示例
下面是几个示例来演示闭包的用法:
示例 1:访问外部变量
function outerFunction() {
var outerVariable = 'I am outside!';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
var inner = outerFunction();
inner(); // 输出:I am outside!
在这个示例中,innerFunction
是一个闭包,因为它可以访问outerFunction
中定义的outerVariable
变量,即使innerFunction
在outerFunction
执行后调用。
示例 2:保护变量
function counter() {
var count = 0;
return function() {
count++;
console.log(count);
};
}
var increment = counter();
increment(); // 输出:1
increment(); // 输出:2
increment(); // 输出:3
在这个示例中,counter
函数返回一个闭包,其中包含一个局部变量count
。闭包内部的匿名函数可以访问和修改count
变量,但外部无法直接访问它。这种方式可以实现变量的封装和保护。
示例 3:延迟执行
function delayPrint(message, delay) {
setTimeout(function() {
console.log(message);
}, delay);
}
delayPrint('Hello, world!', 2000); // 2秒后输出:Hello, world!
在这个示例中,setTimeout
的回调函数是一个闭包。它可以在外部函数执行完毕后,延迟指定的时间后执行,并且仍然可以访问delayPrint
函数中的message
变量。
7. 异步编程
我们都知道,JavaScript是一门单线程的编程语言,意味着它一次只能处理一个任务。然而,现代的Web应用程序通常需要处理许多异步操作,例如网络请求、定时器和文件读写等。为了更好地管理和处理这些异步任务,JavaScript提供了多种异步编程模式和技术。现详细介绍JavaScript的异步编程,从基础的回调函数到最新的async/await模式。
7.1 回调函数
回调函数是最早和最常见的JavaScript异步编程模式。它的基本思想是将一个函数作为参数传递给另一个函数,在操作完成后调用该回调函数。例如网络请求、定时器和文件读写等。由于JavaScript是单线程的,回调函数允许我们在等待任务完成期间执行其他操作,以避免程序的阻塞。
7.1.1 单个回调函数
function fetchData(callback) {
// 模拟异步操作
setTimeout(function() {
var data = '这是从服务器返回的数据';
callback(data); // 执行回调函数
}, 1000);
}
function processData(data) {
console.log('处理数据:', data);
}
fetchData(processData);
在上述代码中,fetchData
函数模拟了一个异步操作,并在操作完成后调用传递的processData
回调函数来处理返回的数据。
7.1.2 回调函数地狱
在复杂的异步操作中,可能存在多个操作之间的依赖关系,导致回调函数嵌套,形成回调函数地狱,降低了代码的可读性和可维护性。
function fetchData(callback) {
setTimeout(function() {
var data1 = '第一个异步操作的结果';
callback(data1);
setTimeout(function() {
var data2 = '第二个异步操作的结果';
callback(data2);
// 更多嵌套的异步操作...
}, 1000);
}, 1000);
}
function processData(data) {
console.log('处理数据:', data);
}
fetchData(function(data) {
processData(data);
});
为了避免回调地狱,后续的JavaScript版本引入了Promise和async/await等新的异步编程模式。
7.2 Promise
Promise是一种对异步操作进行更好管理的方式,它提供了一种链式调用的方式来处理异步结果。
7.2.1 创建Promise对象
function fetchData() {
return new Promise(function(resolve, reject) {
// 模拟异步操作
setTimeout(function() {
var data = '这是从服务器返回的数据';
resolve(data); // 完成操作并传递数据
}, 1000);
});
}
fetchData().then(function(data) {
console.log('处理数据:', data);
});
在上述代码中,fetchData
函数返回一个Promise对象。可以使用.then()
方法注册处理异步操作成功的回调函数。
7.2.2 链式调用和错误处理
Promise对象可以进行链式调用,通过返回新的Promise对象实现多个异步操作的串行执行。
function fetchData() {
return new Promise(function(resolve, reject) {
// 模拟异步操作
setTimeout(function() {
var data = '这是从服务器返回的数据';
resolve(data); // 完成操作并传递数据
}, 1000);
});
}
function processData(data) {
console.log('处理数据:', data);
return new Promise(function(resolve, reject) {
// 模拟另一个异步操作
setTimeout(function() {
var result = '处理结果';
resolve(result);
}, 1000);
});
}
fetchData()
.then(function(data) {
return processData(data);
})
.then(function(result) {
console.log('处理结果:', result);
})
.catch(function(error) {
console.error('发生错误:', error);
});
在上述代码中,通过.then()
方法返回新的Promise对象,实现了串行执行异步操作fetchData
和processData
。
.catch()
方法用于捕获错误并进行相应的处理。
7.3. async/await
async/await是ES2017引入的一种更直观、更易读的异步编程模式。
4.3.1 async函数
通过在函数前加上async
关键字声明一个异步函数,异步函数会返回一个Promise对象。
async function fetchData() {
return new Promise(function(resolve, reject) {
// 模拟异步操作
setTimeout(function() {
var data = '这是从服务器返回的数据';
resolve(data); // 完成操作并传递数据
}, 1000);
});
}
async function processData() {
var data = await fetchData();
console.log('处理数据:', data);
}
processData();
在上述代码中,fetchData
函数返回一个Promise对象,并通过await
关键字等待异步操作的结果。
processData
函数必须也声明为async
函数才能使用await
。
7.3.2 await表达式
await
关键字可用于等待一个返回Promise对象的异步操作完成,并返回其结果。
async function fetchData() {
return new Promise(function(resolve, reject) {
// 模拟异步操作
setTimeout(function() {
var data = '这是从服务器返回的数据';
resolve(data); // 完成操作并传递数据
}, 1000);
});
}
async function processData() {
var data = await fetchData();
console.log('处理数据:', data);
}
processData();
7.3.3 异常处理
使用try/catch
块来捕获和处理await
表达式中的异常。
async function fetchData() {
return new Promise(function(resolve, reject) {
// 模拟异步操作
setTimeout(function() {
reject(new Error('请求失败'));
}, 1000);
});
}
async function processData() {
try {
var data = await fetchData();
console.log('处理数据:', data);
} catch (error) {
console.error('发生错误:', error.message);
}
}
processData();
在上述代码中,如果异步操作fetchData
返回的Promise对象被拒绝(rejected),await
会抛出一个异常,在catch
块中进行捕获。
7.4. 并行和串行执行异步任务
Promise和async/await模式可以很好地控制并行和串行执行异步任务。
7.4.1 并行执行
可以使用Promise.all()
方法并行执行多个异步任务,并在所有任务完成后获得结果。
async function fetchData1() {
return new Promise(function(resolve) {
setTimeout(function() {
resolve('数据1');
}, 1000);
});
}
async function fetchData2() {
return new Promise(function(resolve) {
setTimeout(function() {
resolve('数据2');
}, 2000);
});
}
async function fetchData3() {
return new Promise(function(resolve) {
setTimeout(function() {
resolve('数据3');
}, 1500);
});
}
async function processParallel() {
var [data1, data2, data3] = await Promise.all([fetchData1(), fetchData2(), fetchData3()]);
console.log('并行处理数据:', data1, data2, data3);
}
processParallel();
在上述代码中,通过Promise.all()
方法将多个异步任务统一封装为一个Promise对象,并使用解构赋值返回所有任务的结果。
7.4.2 串行执行
通过使用await
关键字和函数的顺序调用,可以实现多个异步任务的串行执行。
async function processSeries() {
var data1 = await fetchData1();
var data2 = await fetchData2();
var data3 = await fetchData3();
console.log('串行处理数据:', data1, data2, data3);
}
processSeries();
7.5 异步编程的最佳实践
- 尽量使用Promise和async/await,避免回调地狱。
- 注意错误处理,使用
.catch()
或try/catch块捕获异常。 - 并行执行多个异步任务时,使用
Promise.all()
获取结果。 - 考虑使用工具库如
axios
或fetch
来处理网络请求,它们已经提供了良好的异步支持。
7.6 异步编程结论
JavaScript的异步编程是处理复杂和并行任务的关键技术。通过回调函数、Promise和async/await模式,我们可以更好地管理和处理异步任务,提高应用的性能和响应性。在实际开发中,根据具体需求选择适合的异步编程方式,并注意良好的错误处理和最佳实践,以编写出高效、可维护的代码。
8. 总结
本次主要记录了Javascript的基础语法、常用对象使的使用以及事件等等基础知识,同时详解了JavaScript中的闭包、异步编程等等知识,接下来会讲述网路请求方面的知识并通过ajax和axios进行网络请求发送。