Js 高级语法

🍹 JavaScript高级语法包括异步编程、模块化、高阶函数、装饰器、生成器、对象解构等,提升代码可读性和管理复杂性。

1 JSON

  • JSON
    • JavaScript Object Notation,即JavaScript对象标记法,一种存储和交换数据的语法。
    • 当数据在浏览器与服务器之间进行交换时,这些数据只能是文本形式,而JSON属于文本。
    • JavaScript对象与JSON可互相转换,将数据作为JavaScript对象来处理,无需复杂的解析。
    • JSON中,每一个数据项都是由一个键值对组成的,但键必须是字符串并且由双引号包围。
      • 值必须是字符串、对象、数组、布尔、null数据类型之一。
      • 而JSON值不可以是函数、日期、undefined数据类型之一。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>JSON</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 通过JavaScript,可创建对象并向其分配数据
var person = { name: "刘一", age: 20, city: "北京" };
console.log(person);

// JSON 字符串
var p1 = { name: "陈二" };
// JSON 数字
var p2 = { age: 21 };
// JSON 对象
var p3 = { employee: { name: "张三", age: 22, city: "厦门" } };
// JSON 数组
var p4 = {
employees: ["李四", "王五", "赵六", "孙七", "周八", "吴九", "郑十"],
};
// JSON 布尔
var p5 = { sale: true };
// JSON null
var p6 = { middlename: null };

// JSON字符串转JSON对象,JSON对象在IE7及以下的浏览器中不支持
var personStr = '{ "name": "刘一", "age": 20, "city": "北京" }';
var obj = JSON.parse(personStr);
console.log(obj);

// JSON对象转JSON字符串
var personStr = JSON.stringify(obj);
console.log("JSON对象转JSON字符串:", personStr);
</script>
</body>

</html>

2 AJAX

  • AJAX
    • 即Asynchronous Javascript And XML,一种用于创建快速动态网页的技术。
    • 核心是XMLHttpRequest对象,所有现代浏览器都支持XMLHttpRequest对象。
    • 通过在后台与服务器进行少量的数据交换,从而使网页实现异步更新。
    • 即:可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
    • 查看页面是否使用AJAX技术的方法
      • F12>Network>查看请求类型为XHR或Fetch的请求。
      • 在页面源代码处搜索XMLHttpRequest或fetch关键字。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>AJAX</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 创建XMLHttpRequest
variable = new XMLHttpRequest();

// 老版本的IE5和IE6使用ActiveX对象
// variable = new ActiveXObject("Microsoft.XMLHTTP");

// 为应对所有浏览器,检查是否支持XMLHttpRequest对象
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
console.log(xhttp);
} else {
// 支持IE5和IE6
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
console.log(xhttp);
}
</script>
</body>

</html>

2-1 Get请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>Get请求</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 出于安全原因,现代浏览器不允许跨域访问
// 即:尝试加载的网页和XML文件都必须位于相同的服务器上
// 请求users.json数据,需要启动本地服务
// 文件和项目在同个服务器上才能正常显示
// 可以使用VSCode的Live Server插件在本地启动一个HTTP服务器

// 创建新的XMLHttpRequest异步对象
var ajax = new XMLHttpRequest();
// 设置请求的url参数,参数一是请求类型,参数二是请求url
ajax.open("get", "./users.json");
// 发送请求
ajax.send();
// 注册事件onreadystatechange状态改变就会调用
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
// 如果能够进到该判断,说明数据完美地返回,并且请求的页面存在
console.log(ajax.responseText);
}
}
</script>
</body>

</html>

2-2 Post请求*

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>Post请求</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 出于安全原因,现代浏览器不允许跨域访问
// 即:尝试加载的网页和XML文件都必须位于相同的服务器上

// 创建新的XMLHttpRequest异步对象
var ajax = new XMLHttpRequest();
// 设置请求的url参数,参数一是请求类型,参数二是请求url
ajax.open("post", "./users.json");
// POST请求必定要添加请求头,否则报错
ajax.setRequestHeader("content-type", "application/x-www-form-urlencoded");
// 发送请求
ajax.send();
// 注册事件onreadystatechange状态改变就会调用
ajax.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
// 如果能够进到该判断,说明数据完美地返回,并且请求的页面存在
console.log(ajax.responseText);
}
}

// Failed to load resource: the server responded with a status of 405 (Method Not Allowed)
</script>
</body>

</html>

2-3 请求整合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>请求整合</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 出于安全原因,现代浏览器不允许跨域访问
// 即:尝试加载的网页和XML文件都必须位于相同的服务器上

var Ajax = {
get: function (url, fn) {
var xhr = new XMLHttpRequest();
xhr.open("get", url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) {
fn.call(this, xhr.responseText);
}
};
xhr.send();
},
post: function (url, data, fn) {
var xhr = new XMLHttpRequest();
xhr.open("post", url, true);
xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
fn.call(this, xhr.responseText);
}
};
xhr.send(data);
}
};

// 演示GET请求
Ajax.get("./file/users.json", function (response) {
console.log(response);
});

// 演示POST请求
Ajax.post("./file/users.json", "", function (response) {
console.log(response);
});
</script>
</body>

</html>

2-4 users.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[
{
"name": "刘一",
"age": 20,
"gender": "男"
},
{
"name": "陈二",
"age": 21,
"gender": "男"
},
{
"name": "张三",
"age": 22,
"gender": "男"
},
{
"name": "李四",
"age": 23,
"gender": "男"
},
{
"name": "王五",
"age": 24,
"gender": "男"
}
]

3 Cookie*

  • Cookie
    • Cookie是一些数据,存储在电脑的文本文件中。
    • 当用户访问web页面时,客户端的用户信息可以记录在Cookie中。
    • 在用户下一次访问该页面时,可以在Cookie中读取用户访问记录。
    • JavaScript使用document.cookie属性来创建 、读取、删除Cookie。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>Cookie</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// Cookie创建,没有指定expires过期时间,可能读取不到
document.cookie = "username=刘一";
// 添加一个过期时间(UTC或GMT时间),默认情况下,Cookie在浏览器关闭时删除
// document.cookie = "username=刘一; expires=Thu, 29 Aug 2024 23:00:00 GMT";
// 使用path参数告诉浏览器Cookie的路径,默认情况下,Cookie属于当前页面
// document.cookie = "username=刘一; expires=Thu, 29 Aug 2024 23:00:00 GMT; path=/";

// Cookie读取
var cookies = document.cookie;
console.log(cookies);

// Cookie删除,设置expires参数为以前的时间即可删除
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";
var cookies = document.cookie;
console.log(cookies);

/**
* 设置Cookie
* @param cname cookie名称
* @param cvalue cookie值
* @param exdays 过期天数
*/
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
var expires = "expires=" + d.toGMTString();
// SameSite=Strict:仅在同一站点请求中发送Cookie,不允许跨站请求
// SameSite=None; Secure:允许跨站请求发送Cookie
// 但需使用Secure标志,意味着Cookie仅在HTTPS请求中发送
// 默认值,允许在导航到同一站点的情况下发送Cookie,但在跨站请求中会限制发送
var sameSite = "SameSite=Lax";
document.cookie = cname + "=" + cvalue + "; " + expires + "; path=/";
}

/**
* 获取Cookie
* @param cname cookie名称
* @returns {string}
*/
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = document.cookie.split(";");
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == " ") {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}

/**
* 删除 Cookie
* @param cname cookie名称
*/
function deleteCookie(cname) {
document.cookie = cname + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;";
}

setCookie("username", "陈二", 7);
var user = getCookie("陈二");
// 为啥获取不到值???
console.log("用户名:" + user);
deleteCookie("username");
console.log("删除后:" + getCookie("username"));
</script>
</body>

</html>

4 Closure

  • Closure
    • 闭包是能够读取其他函数内部变量的函数,本质上就是将函数内部和函数外部连接起来。
    • 当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包。
    • 作用:读取函数内部的变量、让这些变量的值始终保持在内存中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>Closure</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
function fun1() {
var a = 2;
function subFun() {
a++;
console.log(a);
}
return subFun;
}

var f1 = fun1();
f1();
f1();
console.log("***");

function fun2() {
var a = 2;
function subFun() {
a--;
console.log(a);
}
return subFun;
}

var f2 = fun2();
f2();
f2();
</script>
</body>

</html>

4-1 生命周期

  • 生命周期
    • 产生:在嵌套内部函数定义执行完时就产生了。
    • 死亡:在嵌套的内部函数成为垃圾对象时死亡。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>生命周期</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
function fn1() {
// 此时闭包就已经产生(函数提升, 内部函数对象已经创建)
var a = 2;
function fn2() {
a++;
console.log(a);
}
return fn2;
}

var f = fn1();
f();
f();
// 闭包死亡(包含闭包的函数对象成为垃圾对象)
f = null;
</script>
</body>

</html>

4-2 闭包应用

  • 闭包应用
    • 具有特定功能的Js文件,模块的使用只需通过模块暴露的对象调用方法来实现对应的功能。
    • 只向外暴露一个包含n个方法的对象或函数,将所有数据和功能都封装在一个函数内(私有)。

(1) return

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>return</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
function myModule() {
// 私有数据
var msg = "Hello, World!";

// 操作数据的函数
function getUpper() {
console.log("getUpper() " + msg.toUpperCase());
}

function getLower() {
console.log("getLower() " + msg.toLowerCase());
}

// 向外暴露对象(给外部使用的方法)
return {
getUpper: getUpper,
getLower: getLower
}
}

var module = myModule();
module.getUpper();
module.getLower();
</script>
</body>

</html>

(2) window

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>window</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
(function (window) {
// 私有数据
var msg = "Hello, World!";

// 操作数据的函数
function getUpper() {
console.log("getUpper() " + msg.toUpperCase());
}

function getLower() {
console.log("getLower() " + msg.toLowerCase());
}

// 向外暴露对象(给外部使用的方法)
window.myModule = {
getUpper: getUpper,
getLower: getLower
}
})(window);

myModule.getUpper();
myModule.getLower();
</script>
</body>

</html>

(3) 第n个按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>第n个按钮</title>
</head>

<body style="text-align: center"><br />
<button id="btn1">按钮 1</button>
<button id="btn2">按钮 2</button>
<button id="btn3">按钮 3</button><br /><br />
<button id="btn4">按钮 4</button>
<button id="btn5">按钮 5</button>
<button id="btn6">按钮 6</button><br /><br />
<button id="btn7">按钮 7</button>
<button id="btn8">按钮 8</button>
<button id="btn9">按钮 9</button>

<!-- JavaScript由上到下执行 -->
<script>
var btns = document.getElementsByTagName("button");

// 将btn所对应的下标保存在btn上
// for (var i = 0, length = btns.length; i < length; i++) {
// var btn = btns[i];
// btn.index = i;
// btn.onclick = function () {
// alert("第 " + (this.index + 1) + " 个按钮!");
// }
// }

// 利用闭包延长局部变量的生命周期
for (var i = 0, length = btns.length; i < length; i++) {
(function (j) {
var btn = btns[j];
btn.onclick = function () {
alert("第 " + (j + 1) + " 个按钮!");
}
})(i);
}
</script>
</body>

</html>

5 Exception

  • Exception
    • 当错误发生时,JavaScript提供了错误信息的内置error对象,error对象包含两个属性。
    • Error对象属性:name设置或返回错误名、message设置或返回错误消息(一条字符串)。
    • name属性可返回的值
      • TypeError(已发生类型错误)、URIError(在encodeURI()中已发生的错误)。
      • SyntaxError(已发生语法错误)、EvalError(已在eval()函数中发生的错误)。
      • ReferenceError(已发生非法引用)、RangeError(已发生超出数字范围的错误)。
    • try-catch语句是JavaScript中处理异常的标准方式,也提供了finally语句。
      • try语句不发生错误,catch语句不执行,finally语句一定执行。
      • try语句发生错误,则执行catch语句,finally语句也一定执行。

5-1 try-catch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>try-catch</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
try {
console.log(a);
console.log("a未定义肯定报错,看不见我看不见我!");
} catch (error) {
// 发生错误执行的代码
console.log(error);
} finally {
// 无论是否出错都会执行的代码
console.log("finally正在执行中...肯定会被执行!!!")
}
</script>
</body>

</html>

5-2 EvalError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>EvalError</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
try {
// 缺少一个'会产生错误
eval("alert('Hello)");
} catch (error) {
console.log(error)
}
</script>
</body>

</html>

5-3 URIError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>URIError</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
try {
// 无法对百分号进行URI编码
decodeURI("%%%");
} catch (error) {
console.log(error)
}
</script>
</body>

</html>

5-4 TypeError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>TypeError</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
var num = 1;
try {
// 无法将数字转为大写
num.toUpperCase();
} catch (error) {
console.log(error)
}
</script>
</body>

</html>

5-5 RangeError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>RangeError</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
var num = 1;
try {
// 无法拥有500个有效数
num.toPrecision(500);
} catch (error) {
console.log(error)
}
</script>
</body>

</html>

5-6 SyntaxError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>SyntaxError</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
try {
// 缺少'会产生错误
eval("alert('Hello)");
} catch (error) {
console.log(error)
}
</script>
</body>

</html>

5-7 ReferenceError

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>ReferenceError</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
var x;
try {
// y无法被引用
x = y + 1;
} catch (error) {
console.log(error)
}
</script>
</body>

</html>

5-8 throw内置的异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>throw内置的异常</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 该函数接收一个数字,返回数字的平方
function foo(num) {
if (typeof num == "number") {
return num * num;
} else {
throw new TypeError("您输入的是一个非法数字!")
}
}

console.log(foo(4));
console.log(foo("abc"));
</script>
</body>

</html>

5-9 throw自定义异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>throw自定义异常</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 自定义错误
function MyError(message) {
this.message = "自定义错误";
this.name = "自定义错误";
}
MyError.prototype = new Error();

try {
throw new MyError("自定义的错误类型")
} catch (error) {
console.log(error.message)
}
</script>
</body>

</html>

6 WebStorage

  • WebStorage
    • HTML5中本地存储的解决方案之一,但并非为了取代Cookie而制定。
    • 在于解决本不应Cookie做,却不得不用Cookie本地存储的应用场景。
    • 分类
      • sessionStorage将数据保存在session中,浏览器关闭也就没有了。
      • localStorage一直将数据保存在客户端本地,两者使用的API相同。
    • localStorage和sessionStorage只能存储字符串类型,低版本IE使用json2.js。
    • 复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理。

6-1 localStorage

  • localStorage
    • 在本地永久性存储数据,除非显式地将其删除或清空。
    • 常见方法
      • 保存单个数据:localStorage.setItem(key,value);
      • 读取单个数据:localStorage.getItem(key);
      • 删除单个数据:localStorage.removeItem(key);
      • 删除所有数据:localStorage.clear();
      • 获取某个索引的key:localStorage.key(index);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>localStorage</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 保存单个数据
localStorage.setItem("username", "刘一");

// 读取单个数据
console.log(localStorage.getItem("username"));
console.log("*********************************");

// 删除单个数据
localStorage.removeItem("username");
console.log(localStorage.getItem("age"));
console.log("*********************************");

// 保存两个数据
localStorage.setItem("age", 20);
localStorage.setItem("sex", "男");
console.log("age=" + localStorage.getItem("age"));
console.log("sex=" + localStorage.getItem("sex"));
console.log("*********************************");

// 使用for循环来迭代localStorage中的键值对
for (var i = 0; i < localStorage.length; i++) {
// 获取索引的key
var key = localStorage.key(i);
var value = localStorage.getItem(key);
console.log(key + "=" + value);
}
console.log("*********************************");

// 删除所有数据
localStorage.clear();

// 使用for循环来迭代localStorage中的键值对、属性和方法
for (var key in localStorage) {
console.log(key + "=" + localStorage[key]);
}
</script>
</body>

</html>

6-2 sessionStorage

  • sessionStorage
    • sessionStorage对象存储当前窗口或标签页的数据,这些数据可跨越页面刷新而存在。
    • 一旦窗口或标签页被永久关闭,那么所有通过sessionStorage存储的数据也将被清空。
    • sessionStorage对象绑定于某个服务器会话,所以当文件在本地运行时则是不可用的。
    • 存储在sessionStorage中的数据只能由最初给对象存储数据的页面访问到,对多页面应用有限制。
    • 常见方法
      • 保存单个数据:sessionStorage.setItem(key,value);
      • 读取单个数据:sessionStorage.getItem(key);
      • 删除单个数据:sessionStorage.removeItem(key);
      • 删除所有数据:sessionStorage.clear();
      • 获取某个索引的key:sessionStorage.key(index);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>sessionStorage</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 保存单个数据
sessionStorage.setItem("username", "刘一");

// 读取单个数据
console.log(sessionStorage.getItem("username"));
console.log("*********************************");

// 删除单个数据
sessionStorage.removeItem("username");
console.log(sessionStorage.getItem("username"));
console.log("*********************************");

// 保存两个数据
sessionStorage.setItem("age", 20);
sessionStorage.setItem("sex", "男");
console.log("age=" + sessionStorage.getItem("age"));
console.log("sex=" + sessionStorage.getItem("sex"));
console.log("*********************************");

// 使用for循环来迭代sessionStorage中的键值对
for (var i = 0; i < sessionStorage.length; i++) {
var key = sessionStorage.key(i);
var value = sessionStorage.getItem(key);
console.log(key + "=" + value);
}
console.log("*********************************");

// 删除所有数据
sessionStorage.clear();

// 使用for循环来迭代sessionStorage中的键值对、属性和方法
for (var key in sessionStorage) {
console.log(key + "=" + sessionStorage[key]);
}
</script>
</body>

</html>

7 JavaScript新特性

  • JavaScript新特性
    • JavaScript作为一种不断发展的语言,不同版本引入了许多新特性。
    • ES5(2009),启用严格模式,增强代码安全性,原生支持JSON格式。
    • ES6(2015),let和const关键字的引入,简化函数语法等(主要介绍)。
    • ES7(2016)、ES8(2017)、ES9(2018)、ES10(2019)、ES11(2020)等。
    • ECMAScript官网可查发布的新功能:https://ecma-international.org/

7-1 关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>关键字</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}

.item {
width: 100px;
height: 50px;
border: solid 1px rgb(42, 156, 156);
float: left;
margin-right: 10px;
}
</style>
</head>

<body style="text-align: center">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>

<!-- JavaScript由上到下执行 -->
<script>
// 使用let关键字声明变量,获取div元素对象
let items = document.getElementsByClassName("item");

// 遍历并绑定事件
for (let i = 0; i < items.length; i++) {
items[i].onclick = function () {
// 以前的做法:this.style.background = "pink";
items[i].style.background = "greenyellow";
};
}

// const关键字声明常量
const MAX = 100;
console.log(MAX);

// 对于数组和对象的元素修改, 不算作对常量的修改, 不会报错
const TEAM1 = [1, 2, 3, 4];
const TEAM2 = [1, 2, 3, 4];
// 但是不能修改地址指向,否则报错
// TEAM2 = TEAM1;

// 声明对象类型使用const,非对象类型选择let
</script>
</body>

</html>

7-2 迭代器

  • 迭代器
    • Iterator,为各种不同的数据结构提供统一访问机制的接口。
    • 任何数据结构只要部署Iterator接口,就可以完成遍历操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>迭代器</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 遍历数据:声明一个数组
const people = ["刘一", "陈二", "张三", "李四"];
// 使用for...of遍历数组
for (let v of people) {
console.log(v);
}
// 获取迭代器对象
let iterator = people[Symbol.iterator]();
// 调用对象的next方法
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

// 自定义遍历数据:声明一个对象
const grade = {
name: "三班",
stus: [
"王五",
"赵六",
"孙七",
"周八",
"吴九",
"郑十"
],
[Symbol.iterator]() {
// 索引变量
let index = 0;
let _this = this;
return {
next: function () {
if (index < _this.stus.length) {
const result = { value: _this.stus[index], done: false };
// 下标自增
index++;
// 返回结果
return result;
} else {
return { value: undefined, done: true };
}
}
};
}
}
// 遍历这个对象
for (let v of grade) {
console.log(v);
}
</script>
</body>

</html>

7-3 rest参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>rest参数</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 作用与arguments类似
function add(...args) {
console.log(args);
}
add(1, 2, 3, 4, 5);

// rest参数必须是最后一个形参,非常适合不定个数参数函数的场景
function minus(a, b, ...args) {
console.log(a, b, args);
}
minus(100, 1, 2, 3, 4, 5, 19);
</script>
</body>

</html>

7-4 简化对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>简化对象</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
let name = "刘一";
let age = 20;
let speak = function () {
console.log(this.name);
};

// 属性和方法简写
let person = {
name,
age,
speak
};

console.log(person.name);
person.speak();
</script>
</body>

</html>

7-5 箭头函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>箭头函数</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 省略小括号
let f1 = num => {
return num * 10;
};
console.log(f1(10));

// 省略花括号
let f2 = score => score * 20;
console.log(f2(20));

// this指向声明时所在作用域中this的值
let f3 = () => {
console.log(this);
}
f3();

let school = {
name: "张三",
getName() {
let subFun = () => {
console.log(this);
}
subFun();
}
};
school.getName();
</script>
</body>

</html>

7-6 解构赋值

  • 解构赋值
    • 从数组和对象中提取值,对变量进行赋值,被称为解构赋值。
    • 频繁使用对象方法、数组元素,就可以使用解构赋值的形式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>解构赋值</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 数组的解构赋值
const arr = ["刘一", "陈二", "张三"];
let [liu, chen, zhang, li] = arr;
console.log(liu);
console.log(chen);
console.log(zhang);

// 简单对象的解构赋值
const lin = {
cname: "李四",
tags: ["歌手", "演员"]
};
let { cname, tags } = lin;
console.log(cname);
console.log(tags);

// 复杂对象的解构赋值
let zhaoliu = {
lname: "王五",
age: 18,
songs: ["红豆", "流年"],
history: [
{ name: "赵六" },
{ name: "孙七" }
]
};
let { lname, age, songs: [one, two], history: [first, second] } = zhaoliu;
console.log(lname);
console.log(one);
console.log(two);
console.log(first);
console.log(second);
</script>
</body>

</html>

7-7 模板字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>模板字符串</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 定义字符串
let str =
`<ul>
<li>刘一</li>
<li>陈二</li>
<li>张三</li>
<li>李四</li>
</ul>`;
console.log(str);

// 变量拼接
let name = "王五";
let result = `${name}:介绍一位名人给你认识,他姓王,名五。`;
console.log(result);
</script>
</body>

</html>

7-8 扩展运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>扩展运算符</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 扩展运算符spread也是三个点,好比rest参数的逆运算
// 将一个数组转为用逗号分隔的参数序列,再对数组进行解包操作

// 展开数组
let tfboys = ["刘一", "陈二"];
function fn() {
console.log(arguments);
}
fn(...tfboys);

// 展开对象
let skillOne = {
x: "暴击"
};
let skillTwo = {
y: "勇气"
};
let skillThree = {
z: "审判"
};
let skill = { ...skillOne, ...skillTwo, ...skillThree };
console.log(skill);
</script>
</body>

</html>

7-9 Symbol类型

  • Symbol类型
    • JavaScript的第七种数据类型,是一种类似于字符串的数据类型。
    • Symbol的值是独一无二的,用于解决命名冲突的问题,并且不能与其他数据进行运算。
    • 定义的对象属性不能用for...in循环遍历,用Reflect.ownKeys获取对象的所有键名。
    • 内置值(即魔术方法)
      • Symbol.species:创建衍生对象时,使用该属性。
      • Symbol.match:执行str.match(myObject)时,如果属性存在则调用。
      • Symbol.split:对象被str.split(myObject)调用时,返回该方法的返回值。
      • Symbol. toStringTag:对象上面调用toString方法时,返回该方法的返回值。
      • Symbol.search:对象被str.search (myObject)调用时,返回该方法的返回值。
      • Symbol.replace:对象被str.replace(myObject)调用时,返回该方法的返回值。
      • Symbol. unscopables:对象指定使用with关键字时,判断属性将会被with环境排除。
      • Symbol.iterator:对象进行for...of循环时调用该方法,返回该对象的默认遍历器。
      • Symbol.hasInstance:其他对象使用instanceof运算符,判断是否为该对象的实例时调用。
      • Symbol.isConcatSpreadable:对象用于Array.prototype.concat()时,判断是否可以展开。
      • Symbol.toPrimitive:对象被转为原始类型的值时调用该方法,返回该对象对应的原始类型值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>Symbol类型</title>
</head>

<body style="text-align: center">
<!-- JavaScript由上到下执行 -->
<script>
// 创建Symbol
let s1 = Symbol();
console.log(typeof s1);
console.log(s1);

// 添加标识的Symbol
let s2 = Symbol("张三");
let s2_2 = Symbol("张三");
// console.log(s2 === s2_2);
console.log(s2);
console.log(s2_2);

// 使用Symbol.for定义
let s3 = Symbol.for("张三");
let s3_2 = Symbol.for("张三");
// console.log(s3 === s3_2);
console.log(s3);
console.log(s3_2);

// 在方法中使用Symbol
let game = {
name: "狼人杀",
[Symbol("say")]: function () {
console.log("我可以发言")
},
[Symbol("zibao")]: function () {
console.log("我可以自爆");
}
};
console.log(game);

// Symbol.hasInstance
class Person {
static [Symbol.hasInstance](param) {
console.log("我被用来检测类型");
}
}
let o = {};
// console.log(o instanceof Person);

// Symbol.isConcatSpreadable
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
arr2[Symbol.isConcatSpreadable] = true;
console.log(arr1.concat(arr2));

const arr3 = [1, 2, 3];
const arr4 = [4, 5, 6];
arr4[Symbol.isConcatSpreadable] = false;
console.log(arr3.concat(arr4));
</script>
</body>

</html>

Js 高级语法
https://stitch-top.github.io/2024/09/13/web/web01-javascript/javascript06-js-gao-ji-yu-fa/
作者
Dr.626
发布于
2024年9月13日 23:00:00
许可协议