js基础
1 JavaScript 简介
JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。
1.1 JavaScript 是脚本语言
JavaScript 是一种轻量级的编程语言。
JavaScript 是可插入 HTML 页面的编程代码。
JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。
JavaScript 很容易学习。
1.2 JavaScript:直接写入 HTML 输出流
1.3 实例
1 | document.write("<h1>这是一个标题</h1>"); |
1
2
3
4
5
6
7
8
9
10
11
alert() 函数在 JavaScript 中并不常用,但它对于代码测试非常方便。
onclick 事件只是您即将在本教程中学到的众多事件之一。
## 1.5 JavaScript:改变 HTML 内容
使用 JavaScript 来处理 HTML 内容是非常强大的功能。
**实例**
x=document.getElementById(“demo”); //查找元素 x.innerHTML=”Hello JavaScript”;
//改变内容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
您会经常看到 **`document.getElementById("_some id_")`** 。这个方法是 HTML DOM 中定义的。
`DOM (Document Object Model)`(文档对象模型)是用于访问 HTML 元素的正式 W3C 标准。
您将在本教程的多个章节中学到有关 HTML DOM 的知识。
## 1.6 JavaScript:改变 HTML 图像
本例会动态地改变 HTML `<image>` 的来源(src):
### 1.6.1 点亮灯泡
点击以下灯泡查看效果:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<script>
function changeImage()
{
element=document.getElementById('myimage')
if (element.src.match("bulbon"))
{
element.src="[https://www.runoob.com/images/pic_bulboff.gif](https://www.runoob.com/images/pic_bulboff.gif)";
}
else
{
element.src="[https://www.runoob.com/images/pic_bulbon.gif](https://www.runoob.com/images/pic_bulbon.gif)";
}
}
</script>
<img id="myimage" onclick="changeImage()" src="[https://www.runoob.com/images/pic_bulboff.gif](https://www.runoob.com/images/pic_bulboff.gif)" width="100" height="180">
<p>点击灯泡就可以打开或关闭这盏灯</p>
</body>
</html>
以上实例中代码 element.src.match(“bulbon”) 的作用意思是:检索 < img id=”myimage” onclick=”changeImage()” src=”/images/pic_bulboff.gif” width=”100” height=”180”> 里面 src 属性的值有没有包含 bulbon 这个字符串,如果存在字符串 bulbon ,图片 src
更新为 bulboff.gif ,若匹配不到 bulbon 字符串,src 则更新为 bulbon.gif
JavaScript 能够改变任意 HTML 元素的大多数属性,而不仅仅是图片。
1.7 JavaScript:改变 HTML 样式
改变 HTML 元素的样式,属于改变 HTML 属性的变种。
实例
1 | x=document.getElementById("demo") //找到元素 |
1.8 JavaScript:验证输入
JavaScript 常用于验证用户的输入。
实例1
2
3if isNaN(x) {
alert("不是数字");
}
以上实例只是普通的验证,如果要在生产环境中使用,需要严格判断,如果输入的空格,或者连续空格 isNaN
是判别不出来的。可以添加正则来判断(后续章节会说明):
实例1
2
3
4if(isNaN(x)||x.replace(/(^\s*)|(\s*$)/g,"")=="")
{
alert("不是数字");
}
注意
JavaScript 与 Java 是两种完全不同的语言,无论在概念上还是设计上。
Java(由 Sun 发明)是更复杂的编程语言。
ECMA-262 是 JavaScript 标准的官方名称。
JavaScript 由 Brendan Eich 发明。它于 1995 年出现在 Netscape 中(该浏览器已停止更新),并于 1997 年被
ECMA(一个标准协会)采纳。
1.9 ECMAScript 版本
JavaScript 已经由 ECMA(欧洲电脑制造商协会)通过 ECMAScript 实现语言的标准化。
| 年份 | 名称 | 描述 |
|---|---|---|
| 1997 | ECMAScript 1 | 第一个版本 |
| 1998 | ECMAScript 2 | 版本变更 |
| 1999 | ECMAScript 3 | 添加正则表达式 |
| 添加 try/catch | ||
| ECMAScript 4 | 没有发布 | |
| 2009 | ECMAScript 5 | 添加 “strict mode”,严格模式 |
| 添加 JSON 支持 | ||
| 2011 | ECMAScript 5.1 | 版本变更 |
| 2015 | ECMAScript 6 | 添加类和模块 |
| 2016 | ECMAScript 7 | 增加指数运算符 (**) |
| 增加 Array.prototype.includes |
ECMAScript 6 也称为 ECMAScript 2015。
ECMAScript 7 也称为 ECMAScript 2016。
2 JavaScript 用法
HTML 中的 Javascript 脚本代码必须位于 <script>与</script> 标签之间。
Javascript 脚本代码可被放置在 HTML 页面的 <body> 和 <head> 部分中。
2.1 <script> 标签
如需在 HTML 页面中插入 JavaScript,请使用<script> 标签。
<script> 和 </script> 会告诉 JavaScript 在何处开始和结束。
<script>和 </script>之间的代码行包含了 JavaScript:
<script> alert("我的第一个 JavaScript"); </script>
您无需理解上面的代码。只需明白,浏览器会解释并执行位于 <script> 和 </script>之间的 JavaScript 代码
那些老旧的实例可能会在
<script>标签中使用 type=”text/javascript”。现在已经不必这样做了。JavaScript 是所有现代浏览器以及 HTML5 中的默认脚本语言。
2.2 <body>中的 JavaScript
在本例中,JavaScript 会在页面加载时向 HTML 的 <body> 写文本:
2.3 实例
1 | <!DOCTYPE html> |
2.4 JavaScript 函数和事件
上面例子中的 JavaScript 语句,会在页面加载时执行。
通常,我们需要在某个事件发生时执行代码,比如当用户点击按钮时。
如果我们把 JavaScript 代码放入函数中,就可以在事件发生时调用该函数。
2.5 在 <head> 或者<body>的JavaScript
您可以在 HTML 文档中放入不限数量的脚本。
脚本可位于 HTML 的 <body>或 <head>部分中,或者同时存在于两个部分中。
通常的做法是把函数放入 <head> 部分中,或者放在页面底部。这样就可以把它们安置到同一处位置,不会干扰页面的内容。
2.6 <head> 中的 JavaScript 函数
在本例中,我们把一个 JavaScript 函数放置到 HTML 页面的 <head> 部分。
该函数会在点击按钮时被调用:
实例
JavaScript
1 | <!DOCTYPE html> |
2.7 <body>中的 JavaScript 函数
在本例中,我们把一个 JavaScript 函数放置到 HTML 页面的 <body> 部分。
该函数会在点击按钮时被调用:
实例
1 | <!DOCTYPE html> |
2.8 外部的 JavaScript
也可以把脚本保存到外部文件中。外部文件通常包含被多个网页使用的代码。
外部 JavaScript 文件的文件扩展名是 .js。
如需使用外部文件,请在 <script> 标签的 “src” 属性中设置该 .js 文件:
2.9 实例
1 | <!DOCTYPE html> |
你可以将脚本放置于 <head>或者 <body>中,放在 <script>标签中的脚本与外部引用的脚本运行效果完全一致。
myScript.js 文件代码如下:
1 | function myFunction() |
外部脚本不能包含 <script> 标签。
3 Chrome 浏览器中执行 JavaScript
本章节为大家介绍如何在 Chrome 浏览器上进行 JavaScript 代码的运行与调试。
Chrome 是由 Google 开发的免费网页浏览器,对于前端开发来说(尤其是调试代码)非常方便。
Chrome 官网地址:https://www.google.com/intl/zh-CN/chrome/。
我们在 Chrome 浏览器中可以通过按下 F12 按钮或者右击页面,选择”检查”来开启开发者工具。
也可以在右上角菜单栏选择 “更多工具”=》”开发者工具” 来开启:
3.1 1、Console 窗口调试 JavaScript 代码
打开开发者工具后,我们可以在 Console 窗口调试 JavaScript代码,如下图:
上图中我们在 > 符号后输入我们要执行的代码 console.log(“runoob”),按回车后执行。
我们也可以在其他地方复制一段代码过来执行,比如复制以下代码到 Console 窗口,按回车执行:
1 | console.log("runoob-1") |
清空 Console 窗口到内容可以按以下按钮:
3.2 2、Chrome snippets 小脚本
我们也可以在 Chrome 浏览器中创建一个脚本来执行,在开发者工具中点击 Sources 面板,选择 Snippets 选项卡,在导航器中右击鼠标,然后选择 Create new snippet 来新建一个脚本文件:
如果你没看到 Snippets ,可以点下面板上到 >> 就能看到了。
点击 Create new snippet 后,会自动创建一个文件,你只需在右侧窗口输入以下代码,然后按 Command+S(Mac)或 Ctrl+S(Windows 和 Linux)保存更改即可。
1 | console.log("runoob-1") |
保存后,右击文件名,选择 “Run” 执行代码:
4 嵌入方式
4.1 内嵌式
理论上js可以插入任何一个地方,但是习惯上写在head标签或body下
JavaScript
1 | <script> |
4.2 外联式
JavaScript
1 | <script type="text/javascript" src="文件路径"></script> |
4.3 行内式
直接写在标签上,是一个简写的事件,所以又称为事件属性
JavaScript
1 | <input type="button" value="点我" onclick="alert('xss');"/> |
5 语句
1.在编程语言中,这些编程指令被称为语句
2.js由以下语句构成:
值、运算符、表达式、关键词和注释。
3.用分号(;)分割js语句
6 注释
单行注释: // 注释语句
多行注释: /注释语句/
注意:多行注释不能嵌套使用。
7 js保留关键字
Javascript 的保留关键字不可以用作变量、标签或者函数名。有些保留关键字是作为 Javascript 以后扩展使用。
| 关键字 | ||||
|---|---|---|---|---|
| abstract | arguments | boolean | break | byte |
| case | catch | char | class |
const |
| continue | debugger | default | delete | const |
| double | else | enum |
eval | do |
extends |
false | final | finally | export |
| for | function | goto | if | float |
import |
in | instanceof | int | interface |
| let | long | native | new | newnull |
| package | private | protected | public | return |
| short | static | super |
switch | synchronized |
| this | throw | throws | transient | true |
| try | typeof | var | void | volatile |
| while | with | yield |
标记的关键字是 ECMAScript5 中新添加的。
8 数据类型
JavaScript 共有八种数据类型,可以分为原始数据类型和引用数据类型:
- 原始数据类型(栈 Stack):
Undefined、Null、Boolean、Number、String,以及 ES6 新增的Symbol和BigInt。- 特点:直接存储在栈中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储。
- 引用数据类型(堆 Heap):
Object(包括对象、数组和函数等)。- 特点:存储在堆中的对象,占据空间大、大小不固定。引用数据类型在栈中只存储了一个指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会先检索其在栈中的地址,再从堆中获得实体。(如果全存在栈中,会严重影响程序运行性能)。
补充:操作系统中的堆栈概念
栈区内存由编译器自动分配释放(如函数的参数值、局部变量);堆区内存一般由开发者分配释放,若不释放,程序结束时由垃圾回收机制回收。
8.1 数字类型 (Number & BigInt)
JavaScript 没有整型和浮点型,只有一种数字类型,即 Number 类型(凡是数字都是数值型,不区分整数和小数)。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20var x = 10;
var y = 20;
````
**类型转换与特殊值:**
- `parseInt(...)`:将某值转化为数字(整数),不成功便是 `NaN`。
- `parseFloat(...)`:将某值转化为浮点数,不成功便是 `NaN`。
- **NaN (Not a Number)**:非数字。它是一个“警戒值”,用于指出数字类型中的错误情况(即执行数学运算失败)。
- `typeof NaN` 的结果是 `"number"`。
- `NaN` 是唯一一个非自反的值,即 `NaN === NaN` 不成立,`NaN !== NaN` 为 `true`。
- **判断方法**:`isNaN()` 会尝试进行隐式类型转换,传字符串也会返回 true,不够准确;推荐使用 ES6 的 `Number.isNaN()`,它只有在参数真的是 NaN 时才返回 true。
- **Infinity**:无穷大。可用 `isFinite()` 来判断。
**进阶:为什么 0.1 + 0.2 !== 0.3?如何让其相等?**
计算机底层通过二进制存储数据。`Number` 类型遵循 IEEE 754 标准,使用 64 位双精度浮点数。它的有效数字最多只能保留 53 位,剩余的需要根据“0舍1入”原则舍去。因为 0.1 和 0.2 的二进制是无限循环的,相加并截断后再转化为十进制就变成了 `0.30000000000000004`,导致精度丢失。
解决方案:引入机器精度(误差范围)。ES6 提供了 `Number.EPSILON`(值为 2 的 -52 次方),只要两者之差的绝对值小于它,即可判定相等:
function numberepsilon(arg1, arg2){
return Math.abs(arg1 - arg2) < Number.EPSILON;
}
console.log(numberepsilon(0.1 + 0.2, 0.3)); // true1
2
3
4
5
6
7
8
9
10
11
12
**进阶:BigInt 类型**
因为 Number 最大安全数字是 `9007199254740991` (Number.MAX_SAFE_INTEGER),超过这个范围就会出现精度丢失。官方提出 `BigInt` 来表示任意精度的整数,安全存储超大整数。
---
## 8.2 字符串类型 (String)
表示一系列文本字符数据。由 Unicode 字符、数字、标点组成的序列。首尾由一对单引号或双引号包裹(凡是引号包裹的都是字符串)。
console.log(“\u6B22\u8FCEl来到\”Javascript 世界\””)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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
**进阶:包装类型**
基本类型本没有属性和方法,但为了便于操作,JS 会隐式地将其转换为对象(包装类型)。比如访问 `'abc'.length` 时,后台会自动执行 `String('abc')`。
---
## 8.3 布尔类型 (Boolean)
布尔类型仅有两个值:`true` 和 `false`。底层逻辑中 true 常用 1 表达,false 常用 0 表达。
**其他值到布尔类型的转换规则(假值列表):**
以下 6 个值在转为布尔值时会被强制判定为 `false`(即假值):
`undefined`、`null`、`false`、`+0 / -0`、`NaN`、`""` (空字符串)。
从逻辑上说,除了假值列表以外的所有值,转换结果都是 `true`。
---
## 8.4 Null 与 Undefined
这两个基本数据类型分别都只有一个值,就是 `undefined` 和 `null`。
- **Undefined(未定义)**:只做声明,未初始化。一般变量声明了但还没定义时会返回 `undefined`。
- 安全获取:`undefined` 在 JS 中不是保留字,如果被当作变量名赋值会影响判断。使用 `void 0` 可以获得百分百安全的 undefined,因为 `void` 表达式不改变结果,但强制不返回值。
- **Null(空对象)**:代表的含义是空,主要用于赋值给一些可能会返回对象的变量,作为初始化。
- 历史遗留 Bug:**`typeof null` 的结果是 `"object"`**。因为在 JS 初代版本中,所有值存在 32 位单元中,低位用类型标签标识(1-3 bits)。其中对象类型标签是 `000`,而 null 的机器码 NULL 指针全是 0,导致它的标签也是 `000`,所以被误判为 Object。
> **比较**:`null == undefined` 会返回 `true`(隐式转换),而 `null === undefined` 会返回 `false`。
---
## 8.5 对象与数组 (Object)
对象类型包括普通对象、数组、函数等集合。
**1. 判断数组的方式有哪些?**
- `Object.prototype.toString.call(obj).slice(8,-1) === 'Array'`(最严谨准确)
- `Array.isArray(obj)`(ES6 推荐方法)
- `obj instanceof Array`
- `obj.__proto__ === Array.prototype`
- `Array.prototype.isPrototypeOf(obj)`
**2. 如何判断一个对象是空对象?**
- JSON 转换法:`if(JSON.stringify(Obj) == '{}') { console.log('空对象'); }`
- ES6 推荐法:`if(Object.keys(Obj).length === 0) { console.log('空对象'); }`
**3. 深拷贝与浅拷贝**
`Object.assign({}, outObj)` 和 扩展运算符 `{...outObj}` **都是浅拷贝**。
它们只复制对象的第一层属性,如果对象的属性还是个对象,则只会复制其内存地址(指针)。
---
## 8.6 类型转换核心机制
**1. 隐式类型转换 (ToPrimitive)**
JS 每个值都有自带的 `ToPrimitive` 方法,用于将对象转换为基本类型:
- 期望转为 **Number** 时:先调用对象的 `valueOf()`,如果是原始值则返回;否则调 `toString()`;再不行报错。
- 期望转为 **String** 时:先调用对象的 `toString()`,如果是原始值则返回;否则调 `valueOf()`;再不行报错。
**2. 运算符场景下的转换规则**
- **`+` 操作符**:只要有一方是字符串(或可被转为字符串),就执行**字符串拼接**;否则执行**数字加法**。
- **`-`、`*`、`/` 操作符**:会将操作数全部转为数字再计算(比如 `1 * '23' // 23`)。
- **`==` 操作符**:两边类型不一致时,会尽量都转为 Number 再比较。比如 `'0' == false` 返回 true(两者转数字都是 0)。
- **`<` 和 `>` 比较符**:如果两边都是字符串,则按字母表顺序比较;否则转成数字比较。
---
## 8.7 逻辑与比较运算符进阶
**1. `||` 和 `&&` 返回的是什么?**
它们返回的**不是 true 或 false**,而是其中一个操作数的**实际值**。
- `||` (或):左侧判断为 true,直接返回左侧的值;左侧为 false,返回右侧的值。
- `&&` (与):左侧判断为 true,返回右侧的值;左侧为 false,返回左侧的值。
**2. `Object.is()` 与 `===`、`==` 的区别?**
- `==`:类型不同会先做强制类型转换,再比较。
- `===`(全等):类型不同直接返回 false,不转换。
- `Object.is()`:基本等同于 `===`,但修复了两个特殊情况:让 `-0` 和 `+0` 不相等,让 `NaN` 和 `NaN` 相等。
**3. `instanceof` 的实现原理**
作用是判断右侧构造函数的 `prototype` 属性是否出现在左侧对象的原型链上。
function myInstanceof(left, right) {
let proto = Object.getPrototypeOf(left) // 获取对象的原型
let prototype = right.prototype; // 获取构造函数的原型
while (true) {
if (!proto) return false; // 找完了都没找到
if (proto === prototype) return true; // 匹配成功
proto = Object.getPrototypeOf(proto); // 沿着原型链向上找
}
}1
2
3
4
5
6
7
8
9# 9 内置函数
JavaScript 提供了一些全局可用的内置函数,可以直接在代码中使用,无需任何额外导入。
## 9.1 打印/输出函数 :
### 9.1.1 文字输出
var s = ‘My name is LiHua’
document.write(s)1
2
3
4
5
6
**注意**:在文档加载后使用 `document.write` 会覆盖整个文档。
### 9.1.2 控制台输出
console.log(s)1
2
3
4
5
## 9.2 弹出函数
### 9.2.1 警告框
alert(“中二病也要谈恋爱”);1
2
3
4
5
显示一个带有指定消息的警告框。
### 9.2.2 确认框
var flag = confirm(“你喜欢我吗?”);
console.log(flag);1
2
3
4
5
显示一个带有确认和取消按钮的确认框,返回布尔值,代表用户的选择
### 9.2.3 输入框
var flag = prompt(“你喜欢我吗?”);
console.log(flag);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
显示一个带有输入框的对话框,用于获取用户输入,并返回用户输入的字符串。
## 9.3 类型转换函数:
`parseInt()`:将字符串转换为整数。
`parseFloat()`:将字符串转换为浮点数。
`String()`:将其他数据类型转换为字符串。
`Number()`:将其他数据类型转换为数字。
`Boolean()`: 将其他数据类型转换为布尔类型。
## 9.4 代码执行函数
var s = “document.write(“My name is AJEST”)”;
eval(s);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
将字符串作为 JavaScript 代码执行。应该谨慎使用,因为它可能导致安全问题。
## 9.5 检查函数
`isNaN()`:检查一个值是否为 NaN (Not a Number)。
`typeof()`:返回变量的数据类型。
## 9.6 编码解码函数
`encodeURI()` 和 `decodeURI()`:用于编码和解码 URI。
`JSON.stringify()`:将 JavaScript 对象转换为 JSON 字符串。`JSON.parse()`:将 JSON 字符串转换为 JavaScript 对象。
## 9.7 定时器函数
`setTimeout()` 和 `setInterval()`:用于设置定时器。 `clearTimeout()` 和 `clearInterval()`: 用于取消定时器。
# 10 运算符
## 10.1 算数运算符
|**算数运算符**|**含义**|
|---|---|
|+|加法|
|-|减法|
|*|乘法|
|/|除法|
|%|求余数|
|++|自增|
|--|自减|
> **注意**:
>
> a++与++a:a++是先使用a,再自加;++a是先自加,再使用。
## 10.2 赋值运算符
JavaScript
var a = 10;
a+=31
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
## 10.3 关系运算符
|**关系运算符**|**说明**|
|---|---|
|>|大于|
|<|小于|
|>=|大于等于|
|==|等于|
|!=|不等于|
|===|全等|
|!==|不全等|
# 11 js函数
## 11.1 字符串函数 (String 对象的方法)
字符串对象提供了许多用于处理字符串的函数:
### 11.1.1 截取函数:
#### 11.1.1.1 slice(start, end)
提取字符串的某个部分,并以新的字符串返回被提取的部分。
- `start`: 必需。
- 指定提取部分的起始索引位置(包括该位置的元素)。
- 如果为负数,则从字符串或数组的末尾开始计算(例如,-1 表示最后一个元素,-2 表示倒数第二个元素)。
- `end`: 可选。
- 指定提取部分的结束索引位置(不包括该位置的元素)。
- 如果省略,则提取到字符串或数组的末尾。
- 如果为负数,则从字符串或数组的末尾开始计算
#### 11.1.1.2 substring(start, end)
提取字符串中两个指定的索引号之间的字符。
- 将所有负数的参数值都视为 `0`
- 如果 `start` 大于 `end`,则 `substring()` 会交换这两个参数,相当于使用了 `substring(end, start)`。
let str = “Hello, World!”;
let sub = str.substr(7, 5); // 从索引 7 开始,提取 5 个字符
console.log(sub); // 输出 “World”1
2
3
4
5
6
7
8
9
#### 11.1.1.3 substr(start, length)
从字符串中提取子字符串,它从指定的起始索引位置开始,提取指定数量的字符。
- `start`: 必需。要提取的子串的起始下标。必须是数值。如果是负数,那么该参数声明从字符串的尾部开始算起的位置。
- `length`: 可选。子串中的字符数。必须是数值。如果省略了该参数,那么返回直到字符串结尾的子串。
let str=’Hello,world’
console.log(substr(0,5))//输出Hello1
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
85
86
87
88
|**特性**|**slice(start, end)**|**substring(start,length)**|**substr(start, length)**|
|---|---|---|---|
|第二个参数|结束索引(不包含)|起始索引, 结束索引 (不包含)|要提取的字符数|
|负数索引|从末尾计算|将所有负数的参数值都视为 `0`|`start` 从末尾计算,`length` 负数返回空字符串|
|省略第二个参数|提取到末尾|省略 `end`,提取从 `start` 到字符串末尾的所有字符。|提取到末尾|
|`start` > `end`|返回空字符串|如果 `start` 是正数且大于或等于字符串长度,则返回空字符串。|行为取决于 `length` 的值|
### 11.1.2 查找/定位函数
#### 11.1.2.1 indexOf()
返回字符串中指定子字符串第一次出现的索引。
#### 11.1.2.2 lastIndexOf()
返回字符串中指定子字符串最后一次出现的索引
#### 11.1.2.3 charAt()
返回指定索引位置的字符
### 11.1.3 连接/分割函数
`concat()`:连接两个或多个字符串。
`split()`:将字符串分割成子字符串数组。
### 11.1.4 大小写转化函数
`toLowerCase()`:将字符串转换为小写。
`toUpperCase()`:将字符串转换为大写。
`trim()`:去除字符串两端的空白字符。
## 11.2 数组函数 (Array 对象的方法)
数组对象提供了许多用于处理数组的函数:
- `push()`:向数组末尾添加一个或多个元素。
- `pop()`:删除数组末尾的元素并返回该元素。
- `shift()`:删除数组的第一个元素并返回该元素。
- `unshift()`: 向数组的开头添加一个或更多元素,并返回新的长度。
- `concat()`:连接两个或多个数组。
- `join()`:将数组的所有元素连接成一个字符串。
- `slice()`:提取数组的一部分并返回一个新数组。
- `splice()`:从数组中添加或删除元素。
- `indexOf()`:在数组中查找指定元素第一次出现的索引。
- `lastIndexOf()`:在数组中查找指定元素最后一次出现的索引。
- `forEach()`: 为数组的每个元素调用一次函数。
- `map()`: 通过对每个元素调用函数来创建新数组。
- `filter()`: 创建一个新数组,其中包含通过测试的数组元素。
- `reduce()`: 针对数组的每个元素执行一个提供的 reducer 函数,将其汇总为单个返回值。
- `sort()`: 对数组的元素进行排序。
## 11.3 数字函数 (Math 对象的方法)
Math 对象提供了用于处理数字的函数
- `Math.random()`: 返回 0 到 1 之间的随机数。
- `Math.abs()`:返回数字的绝对值。
- `Math.round()`:将数字四舍五入到最接近的整数。
- `Math.ceil()`:将数字向上舍入到最接近的整数。
- `Math.floor()`:将数字向下舍入到最接近的整数。
- `Math.max()`:返回一组数字中的最大值。
- `Math.min()`:返回一组数字中的最小值。
- `Math.pow()`: 返回 x 的 y 次幂。
- `Math.sqrt()`:返回数字的平方根。
## 11.4 日期函数 (Date 对象的方法)
Date 对象提供了用于处理日期和时间的函数。
- `Date()`: 创建日期对象,例如获取当前时间、设置指定日期等
- `getFullYear()`: 以四位数字返回年份。
- `getMonth()`: 返回月份(0-11)。
- `getDate()`: 返回月份的某一天 (1-31)。
- `getHours()`: 返回小时 (0-23)。
- `getMinutes()`: 返回分钟 (0-59)。
- `getSeconds()`: 返回秒数 (0-59)。
- `getMilliseconds()`: 返回毫秒数 (0-999)。
- `getTime()`: 返回 1970 年 1 月 1 日至今的毫秒数。
## 11.5 自定义函数
开发者根据需求定义的函数,使用 `function` 关键字声明。
示例
function myFunction(param1, param2)
{//函数体
return result;
}
1 |
|
(2) 箭头函数没有自己的 this 箭头函数不会创建自己的 this,它只会在自己作用域的上一层继承 this。所以箭头函数中 this 的指向在它在定义时已经确定了,之后不会改变。可以理解为它是捕获其所在上下文的 this 值作为自己的 this。
(3) 箭头函数继承来的 this 指向永远不会改变
1 | var id = 'GLOBAL'; |
_注:定义对象的大括号 {} 是无法形成一个单独的执行环境的,它依旧是处于全局执行环境中。_
(4) call()、apply()、bind() 等方法不能改变箭头函数中 this 的指向
1 | var id = 'Global'; |
(5) 箭头函数不能作为构造函数使用(不能被 new) new 操作符的执行步骤中,有一步是将构造函数中的 this 指向新创建的对象。但由于箭头函数没有自己的 this,且不能改变指向,所以不能当作构造函数使用。
(6) 箭头函数没有自己的 arguments 在箭头函数中访问 arguments 实际上获得的是它外层函数的 arguments 值。可以使用 ...rest 参数代替。
(7) 箭头函数没有 prototype
(8) 箭头函数不能用作 Generator 函数,不能使用 yield 关键字
12.4 扩展运算符 (…) 的作用及场景
扩展运算符 (...) 用于取出参数对象或数组中的所有可遍历属性,拷贝到当前对象之中。注意:扩展运算符的拷贝属于浅拷贝。
(1) 对象扩展运算符
1 | let bar = { a: 1, b: 2 }; |
如果自定义属性放在扩展运算符后面,则同名属性会被覆盖掉,常用于方便地修改对象部分属性:
1 | let bar = {a: 1, b: 2}; |
(2) 数组扩展运算符 可以将一个数组转为用逗号分隔的参数序列,且每次只能展开一层数组。常见应用场景:
- 将数组转换为参数序列
1
2
3
function add(x, y) { return x + y; }
const numbers = [1, 2];
add(...numbers) // 3
- 复制数组
1
2
const arr1 = [1, 2];
const arr2 = [...arr1];
合并数组
1
2const arr1 = ['two', 'three'];
const arr2 = ['one', ...arr1, 'four', 'five']; // ["one", "two", "three", "four", "five"]与解构赋值结合生成新数组 (扩展运算符只能放在参数最后一位)
1
const [first, ...rest] = [1, 2, 3, 4, 5]; // first: 1, rest: [2, 3, 4, 5]
将字符串转为真正的数组
1
[...'hello'] // [ "h", "e", "l", "l", "o" ]
使用 Math 函数获取数组极值
1
2const numbers = [9, 4, 7, 1];
Math.min(...numbers); // 1
12.5 rest 参数
扩展运算符被用在函数形参上时(称为 rest 参数),可以把一个分离的参数序列整合成一个数组。常用于获取函数的多余参数,或处理参数个数不确定的情况:
1 | function mutiple(...args) { |
12.6 对象与数组的解构赋值
解构是 ES6 提供的一种新的提取数据的模式。
(1) 数组的解构 以元素的位置为匹配条件来提取数据,可以使用空占位符跳过元素:
JavaScript
1 | const [a, b, c] = [1, 2, 3]; |
(2) 对象的解构 以属性的名称为匹配条件。严格以属性名作为定位依据,位置调换不影响:
1 | const stu = { name: 'Bob', age: 24 }; |
(3) 提取高度嵌套的对象属性 通过 冒号 + {目标属性名} 的形式,一层层剥开解构:
1 | const school = { |
12.7 模板语法与字符串处理
(1) 模板字符串 (`) ES6 允许使用反引号包裹字符串,并通过 ${} 的方式嵌入变量。优势:
- 保留格式:空格、缩进、换行都会被保留,非常适合书写 HTML 模板。
- 支持表达式:可以在
${}里完成计算或调用函数。
1 | var name = 'css', career = 'coder'; |
(2) 字符串新增方法
- 存在性判定(返回布尔值):
includes():判断字符串与子串的包含关系。startsWith():判断是否以某个字符开头。endsWith():判断是否以某个字符结尾。
- 自动重复:
repeat(n):将同一个字符串连续复制输出 n 次。
