文章目录
前言
经过前两章的学习,我们知道:
- HTML 是一种标记语言,用来结构化我们的网页内容并赋予内容含义,例如定义段落、标题和数据表,或在页面中嵌入图片和视频。
- CSS 是一种样式规则语言,可将样式应用于 HTML 内容,例如设置背景颜色和字体,在多个列中布局内容。
而这样的网页仍然是个静态的网页,不能对结果做出反应。而现实中我们希望网站能与用户进行一些交互与反馈,例如输入账号密码后登录,动态检测账号密码正不正确,给出反馈。
于是我们就有一个解决方案,使用 JavaScript。JavaScript 是一种脚本语言,可以用来创建动态更新的内容,控制多媒体,制作图像动画,还有很多。
接下来这一章将介绍基础的 JavaScript 相关知识。
JavaScript基本语法
JavaScript简介
JavaScript(缩写:JS)是一门完备的动态编程语言,可为网站添加交互功能(例如:游戏、动态样式、动画以及在按下按钮或收到表单数据时做出的响应等)。
下面从 JavaScript 的简单概念介绍开始,认识 JavaScript 的基本语法。
动态与静态
没有动态更新内容的网页叫做“静态 ”页面,它是由 HTML 以及 CSS 组成的。在访问中,里面的元素不会被改变。
“动态 ”一词既适用于客户端 JavaScript,又适用于描述服务器端语言。是指通过按需生成新内容来更新 web 页面 / 应用,使得不同环境下显示不同内容。服务器端代码会在服务器上动态生成新内容,例如从数据库中提取信息。而客户端 JavaScript 则在用户端浏览器中动态生成新内容,比如说创建一个新的 HTML 表格,用从服务器请求到的数据填充,然后在网页中向用户展示这个表格。两种情况的意义略有不同,但又有所关联,且两者(服务器端和客户端)经常协同作战。
客户端与服务端
JavaScript 是一个客户端语言,客户端(client-side) 代码是在用户的电脑上运行的代码,在浏览一个网页时,它的客户端代码就会被下载,然后由浏览器来运行并展示。
而服务器端代码在服务器上运行,接着运行结果才由浏览器下载并展示出来。
JavaScript 一般作为客户端代码,但是也可以作为服务端代码。
解释代码与编译代码
- 解释(interpret)代码:在解释型语言中,代码自上而下运行,且实时返回运行结果。代码在由浏览器执行前,不需要将其转化为其他形式。代码将直接以文本格式(text form)被接收和处理。
- 编译(compile)代码:编译型语言需要先将代码转化(编译)成另一种形式才能运行。比如 C/C++ 先被编译成汇编语言,然后才能由计算机运行。程序将以二进制的格式运行,这些二进制内容是由程序源代码产生的。
JavaScript 是轻量级 解释型语言。浏览器接受到 JavaScript 代码,并以代码自身的文本格式运行它。
应用程序接口(API)
应用程序接口(Application Programming Interfaces(API)) 是已经建立好的一套代码组件,可以让开发者实现原本很难甚至无法实现的程序。
简单来说,我们可以通过 API 获取到一些内容,这些也许是一些函数的结果或者获取一些特殊信息。
API 一般分为浏览器 API 与第三方 API:
- 浏览器 API 内建于 web 浏览器中,它们可以将数据从周边计算机环境中筛选出来,还可以做实用的复杂工作。例如通过浏览器获取用户的位置、IP 等等信息。
- 第三方 API 并没有默认嵌入浏览器中,一般要从网上取得它们的代码和信息。例如 Hoyue 博客中的随机图采用了自建的 API,它可以获取一个随机图片的地址,这就是一个第三方 API。
JavaScript使用
介绍完了 JavaScript,我们还需要知道 JavaScript 如何在 HTML 中使用。当然 JavaScript 不止在 HTML 中使用,但这里只讨论在 web 中 HTML 脚本使用。
内联JavaScript
可以像添加 CSS 那样将 JavaScript 添加到 HTML 页面中。同样的,我们可以给一些标签添加元素引用 JavaScript 脚本,例如下面的例子:
<button onclick="createParagraph()">点我呀</button>在 html 中存在用 <script> 元素包含 JavaScript 代码,其中包含了上述函数的定义:
function createParagraph() { const para = document.createElement('p'); para.textContent = '你点击了这个按钮!'; document.body.appendChild(para);}然而请不要这样做。 这将使 JavaScript 污染到 HTML,而且效率低下。对于每个需要应用 JavaScript 的按钮,你都得手动添加 onclick="createParagraph()" 属性。
内部JavaScript
内部 JavaScript 用得比较多,我们一般在 <head> 元素中插入以下代码:
<script> // 在此编写 JavaScript 代码</script>接下来我们就可以在 <script> 元素中添加 JavaScript 即可给 HTML 添加脚本内容,例如:
document.addEventListener("DOMContentLoaded", function() { function createParagraph() { let para = document.createElement('p'); para.textContent = '你点击了这个按钮!'; document.body.appendChild(para); } const buttons = document.querySelectorAll('button'); for (let i = 0; i < buttons.length; i++) { buttons[i].addEventListener('click', createParagraph); }});当然这里只是一个例子,关于语法之后会提及。
外部JavaScript
我们使用最多的就是外部 JavaScript。与外部 css 一样,我们可以把 JavaScript 代码放在一个单独的文件,而在 HTML 中引用它。
我们一般有这样的步骤:
-
首先,在刚才的 HTML 文件所在的目录下创建一个名为
script.js的新文件。请确保扩展名为.js,只有这样才能被识别为 JavaScript 代码。 -
在
<head>元素或者<body>元素中添加引用元素<script>,这里是:<script src="script.js" async></script> -
在
script.js文件中,添加之前的例子代码。 -
保存并刷新浏览器,即可成功引用 JavaScript 代码。
当然,和外部 CSS 一样,我们的 src 属性处填写的是地址,它可以包括绝对地址与相对地址。
JavaScript语法
知道了如何引入 JavaScript 后,我们就正式进入 JavaScript 语法的介绍。
注释与分号
与 Java 和 C++ 中一样,JavaScript 中的注释也是用 // 和 /* */ 表示的。
变量与数据类型
一个变量,就是一个用于存放数值的容器。这个数值可能是一个用于累加计算的数字,或者是一个句子中的字符串。变量的独特之处在于它存放的数值是可以改变的。
在 JavaScript 中,声明一个变量的语法是在 var 或 let 关键字之后加上这个变量的名字。
例如:
var myName;let myAge;和其他语言一样,我们的变量有一些内置的数据类型,在 JavaScript 中有六种基本数据类型:
- 数字类型(Number)
- 字符串(String)
- 布尔类型(Boolean (values true and false))
- 对象(Object)
- 空(Null (only value of this type is null))
- 未定义(Undefined)
与其他语言不同的是,它出现了空类型与未定义的类型。空类型是指空的值,例如空对象、空字符串。
而未定义表示的是定义变量时定义了变量,但没有赋值。此时就是一个未定义的状态。
我们可以使用 typeof 运算符知晓变量的类型,它的语法格式是,其中 operand 表示要返回类型的对象或基本类型的表达式。
typeof operand下面是一个例子:
var myName;var myAge = 18;var addRess = "address";
window.alert( "myName: " + (typeof myName) + "\nmyAge: " + (typeof myAge) + "\naddRess: " + (typeof addRess));

您可能会想:“为什么我们需要两个关键字来定义变量?”,“为什么有 var 和 let 呢?”
使用 var 关键字重新声明变量会带来问题,而使用 let 关键字重新声明变量可以解决这个问题。即 var 和我们平时定义变量规则相同,而 let 在更小的代码块中可以重新定义。
// 使用 varvar x = 10;// 此处 x 为 10{ var x = 6; // 此处 x 为 6}// 此处 x 为 6
// 使用 letvar x = 10;// 此处 x 为 10{ let x = 6; // 此处 x 为 6}// 此处 x 为 10对于变量名的命名规则,我们有以下规则:
- 你不应当使用规则之外的其他字符,因为它们可能引发错误,或对国际用户来说难以理解。
- 变量名不要以下划线开头—— 以下划线开头的被某些 JavaScript 设计为特殊的含义,因此可能让人迷惑。
- 变量名不要以数字开头。这种行为是不被允许的,并且将引发一个错误。
- 一个可靠的命名约定叫做 “小写驼峰命名法 ”,用来将多个单词组在一起,小写整个命名的第一个字母然后大写剩下单词的首字符。例如
myName。 - 让变量名直观,它们描述了所包含的数据。不要只使用单一的字母/数字,或者长句。
- 变量名大小写敏感——因此
myage与myAge是 2 个不同的变量。 - 最后也是最重要的一点—— 你应当避免使用 JavaScript 的保留字给变量命名。保留字,即是组成 JavaScript 的实际语法的单词!因此诸如
var、function、let和for等,都不能被作为变量名使用。浏览器将把它们识别为不同的代码项,因此你将得到错误。
数据类型转换
JavaScript 中有一些数据类型自动转换的功能。例如转换为布尔类型:

同理还有其他类型,例如:


JavaScript输出
和其他语言不同的是,JavaScript 不提供任何内建的打印或显示函数。
于是 JavaScript 的输出一般用不同方式“显示”数据:
- 使用
window.alert()写入警告框 - 使用
document.write()写入 HTML 输出 - 使用
innerHTML写入 HTML 元素 - 使用
console.log()写入浏览器控制台
其中数据的内容可以是表达式也可以是变量。
我们最常用的就是 window.alert() 它会弹出一个对话框输出文字,例如:
window.alert(5 + 6);
而如果我们的输出要到 HTML 中的话,一般在 HTML 中使用 document.write()。但是这样会导致清空文档流内容,重新渲染。例如这是一个内联脚本:
<body> <h2>我的第一张网页</h2> <p>我的第一个段落。</p> <button type="button" onclick="document.write(5 + 6)">试一试</button></body>
当我们点击按钮后,就会变成:

此时之前的一个二级标题和段落被清空了,取而代之的是一个表达式的值。
因为 document.write() 会导致文档清空重新渲染,不推荐使用这种方法。而使用 innerHTML 写入 HTML 元素则不会清空其他元素。
因为所有的元素都有一个属性 innerHTML,更改它的值将修改该元素的内容。更改 HTML 元素的 innerHTML 属性是在 HTML 中显示数据的常用方法。为了精确定位到某个元素,它的格式一般为 id.innerHTML,其中 id 通过 document.getElementById(id) 方法获取。例如:
<h1>我是一个标题。</h1><p id="text">123456</p><script> document.getElementById("text").innerHTML = 5 + 6;</script>
此时 id 为 text 的 p 元素内容被 innerHTML 替换了。而其他元素则不变。
最后我们还可以在浏览器中,使用 console.log() 方法在控制台中显示数据。通过 F12 来激活浏览器控制台,并在菜单中选择“控制台”。就可以看到我们的输出了,例如:
console.log("from script file");
JavaScript语句和运算符
JavaScript语句
JavaScript 语句是由 web 浏览器“执行”的“指令”。JavaScript 有三种语句,分别为表达式语句、块语句和关键词语句。
JavaScript 语句由这些部分构成:值、运算符、表达式和关键词。在每条 JavaScript 语句后,使用分号“;”隔开。
表达式语句
完全由表达式组成,最经典的就是 算法表达式语句与赋值,例如:
var x, y, z;x = 22;y = 11;z = x + y;同样的,JavaScript 和 C/C++ 中一样,存在自增和自减运算符,即反复把一个变量加 1 或减 1,使用增量(++)和递减(--)运算符来完成。下面语句是相同的:
x++;x = x + 1;块语句
JavaScript 语句可以用花括号({})组合在代码块中。代码块的作用是定义一同执行的语句。
关键词语句
JavaScript 语句常常通过某个关键词来标识需要执行的 JavaScript 动作。我们一般有下面这些关键词:
| 关键词 | 描述 |
|---|---|
| break | 终止 switch 或循环。 |
| continue | 跳出循环并在顶端开始。 |
| debugger | 停止执行 JavaScript,并调用调试函数(如果可用)。 |
| do … while | 执行语句块,并在条件为真时重复代码块。 |
| for | 标记需被执行的语句块,只要条件为真。 |
| function | 声明函数。 |
| if … else | 标记需被执行的语句块,根据某个条件。 |
| return | 退出函数。 |
| switch | 标记需被执行的语句块,根据不同的情况。 |
| try … catch | 对语句块实现错误处理。try 中包含可疑的代码,一旦它报错则立刻到 catch 中执行。 |
| throw | 抛出一个异常对象,可以包含任何有关发生错误的信息。throw 语句后面的语句将不被执行。 |
| var | 声明变量。 |
运算符
JavaScript 的运算符大多与 Java、C/C++ 相似,相同的就不再赘述。
优先级
一些运算符将在计算算式(在编程中称为表达式)的结果时先于其他运算符被执行。
| 优先级 | 运算符 | 描述 |
|---|---|---|
| 20 | () | 圆括号 (函数调用、分组) |
| 19 | []、. | 方括号和点符号 (成员访问) |
| 18 | new | 对象创建 |
| 17 | ++、— | 自增/自减 |
| 16 | !、~、+、-、typeof、void、delete | 逻辑非、按位取反、一元加/减、类型检测、无操作、对象属性删除 |
| 15 | *、/、% | 乘法、除法、取模 |
| 14 | +、- | 加法、减法 |
| 13 | <<、>>、>>> | 左移、右移 (带符号/不带符号) |
| 12 | <、<=、>、>=、in、instanceof | 比较、属性存在性测试、实例关系测试 |
| 11 | ==、!=、===、!== | 相等性测试 |
| 10 | & | 按位与 |
| 9 | ^ | 按位异或 |
| 8 | | | 按位或 |
| 7 | && | 逻辑与 |
| 6 | || | 逻辑或 |
| 5 | ?: | 条件运算符 |
| 4 | =、+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、^=、|= | 赋值运算符 |
| 3 | yield | 生成器函数中的产出操作 |
| 2 | , | 逗号运算符 (多个表达式串联) |
| 1 | await | 异步函数中的暂停操作 |
其中,在优先级相同的情况下,大部分 JavaScript 会按 从左到右 的顺序依次计算运算符。但是下面类型的语句则是 从右到左 的顺序执行。
-
赋值运算符:赋值运算符的右侧表达式先执行,然后结果被赋值给左侧变量。
let a, b;a = (b = 5); // 先将 5 赋值给 b, 然后 b 的值再赋值给 a -
条件(ternary)运算符(
?:):从右向左计算,在条件为真时执行第一个表达式,否则执行第二个表达式。let x = true ? 1 : 2; // x 为 1let y = false ? 1 : 2; // y 为 2 -
逗号运算符(
,):从左到右执行,但返回的是最右边表达式的值。let a = (1, 2, 3, 4); // a 的值为 4 -
属性访问符(
.)和数组下标访问符([]):都是从左到右计算,但是当多次使用时,则是从左到右依次执行,并且数组下标访问符在这种情况下比属性访问符优先级更高。const obj = { a: { b: 1 } };console.log(obj.a.b); // 从左到右const arr = [1,;console.log(arr[0]); // 从左到右
自动类型转换
在执行运算符时,与其他语言不同的是,JavaScript 会执行自动类型转换。例如转换成 Number 与 String 类:
x = 7 + 8; // Numbery = "7" + 8; // Numberz = "Hello" + 7; // String其中 y 将字符串 “7” 转换成了 number 型,进行相加,返回为 number 型。z 则是把数字 7 转换成了字符型,返回为 “Hello7”。一般来说,数字 + 字符串结果为字符串。
而对于比较运算符,比较不同类型的数据也许会出现不可预料的结果。
| 案例 | 值 |
|---|---|
| 2 < 12 | true |
| 2 < “12” | true |
| 2 < “Bill” | false |
| 2 > “Bill” | false |
| 2 == “Bill” | false |
| ”2” < “12” | false |
| ”2” > “12” | true |
| ”2” == “12” | false |
当比较两个字符串时,我们一般是 字典序比较,同位比较。例如 “2” 和 “12”,在第一位上 2>1 则 "2" > "12" 正确。
对于普通的比较运算符外,JavaScript 还引入了全等运算符:
| 运算符 | 名称 | 作用 | 示例 |
|---|---|---|---|
=== | 严格等于 | 测试左右值是否相同 | 5 === 2 + 4 |
!== | 严格不等于 | 测试左右值是否不相同 | 5 !== 2 + 3 |
它们与普通的 == 或 != 的区别为后者测试值是否相同,但是数据类型可能不同,而前者的 严格版本测试值和数据类型是否相同。返回为布尔类型的 true/false。
除了这些外,逻辑运算符 || && ! 等它们还会默认转换成布尔类型进行比较。
位运算符
位运算符处理 32 位数。该运算中的任何数值运算数都会被转换为 32 位的数。结果会被转换回 JavaScript 数。
| 运算符 | 描述 | 例子 | 等同于 | 结果 | 十进制 |
|---|---|---|---|---|---|
| & | 与 | 5 & 1 | 0101 & 0001 | 0001 | 1 |
| | | 或 | 5 | 1 | 0101 | 0001 | 0101 | 5 |
| ~ | 非 | ~ 5 | ~0101 | 1010 | 10 |
| ^ | 异或 | 5 ^ 1 | 0101 ^ 0001 | 0100 | 4 |
| << | 逻辑左移 | 5 << 1 | 0101 << 1 | 1010 | 10 |
| >> | 逻辑右移 | 5 >> 1 | 0101 >> 1 | 0010 | 2 |
| >>> | 算术右移 | 5 >>> 1 | 0101 >>> 1 | 0010 | 2 |
其中逻辑右移和算术右移的区别在于,逻辑右移后左侧补 0,适用于无符号。算术右移后左侧补符号位,适用于有符号。
字面量
字面量是由语法表达式定义的 常量;或通过由一定字词组成的语词表达式定义的常量。
在 JavaScript 中,你可以使用各种字面量。这些字面量是脚本中按字面意思给出的固定的值,而不是变量。
数字字面量
对于整数,根据数字系统,整数可以用十进制(基数为 10)、十六进制(基数为 16)、八进制(基数为 8)以及二进制(基数为 2)表示。
- 十进制整数字面量由一串数字序列组成,且没有前缀 0。
- 八进制的整数以 0(或 0O、0o)开头,只能包括数字 0-7。
- 十六进制整数以 0x(或 0X)开头,可以包含数字(0-9)和字母 a
f 或 AF。 - 二进制整数以 0b(或 0B)开头,只能包含数字 0 和 1。
例如:
0, 117, -345 // 十进制015, 0001, -0o77 // 八进制0x1123, 0x00111, -0xF1A7 // 十六进制0b11, 0b0011, -0b11 // 二进制如果数字不是整数的话,我们一般可以用科学计数法和小数形式表示:
3.14-.2345789 // -0.23456789-3.12e+12 // -3.12*10^12.1e-23 // 1e-24在 JavaScript 中,数字类型使用 64 位双精度浮点数表示。这意味着它可以表示的数字范围大约是 -1.7976931348623157 × 10^308 到 1.7976931348623157 × 10^308。
字符串字面量
字符串字面量是由双引号(“)对或单引号(‘)括起来的零个或多个字符。字符串被限定在同种引号之间;也即,必须是成对单引号或成对双引号。
"foo"'bar'"1234""one line \n another line""John's cat"常见转义:
| 字符 | 意思 |
|---|---|
| \0 | Null 字节 |
| \b | 退格符 |
| \f | 换页符 |
| \n | 换行符 |
| \r | 回车符 |
| \t | 制表符 |
| \v | 垂直制表符 |
| ’ | 单引号 |
| ” | 双引号 |
| \ | 反斜杠 |
| \uXXXX | 四位十六进制的 Unicode 字符 |
例如在字符串中插入引号:
"He read \"The Cremation of Sam McGee\" by R.W. Service."输出:He read “The Cremation of Sam McGee” by R.W. Service.
JavaScript函数
函数声明
一个函数定义(也称为函数声明,或函数语句)由一系列的 function 关键字组成:
- 函数的名称。
- 函数参数列表,包围在括号中并由逗号分隔。
- 定义函数的 JavaScript 语句,用大括号
{}括起来。
例如:
function square(number) { return number * number;}其中,不需要给函数返回值和参数定义类型。
函数作用域
当同一个作用域下两个参数或者变量同名时,就会产生命名冲突。更近的作用域有更高的优先权,所以最近的优先级最高,最远的优先级最低。例如:
var j = 6; // 作用域为当前工作区function test() { var j; // 作用域为 function test() 内 j = 7;}test();window.alert(j);此时 j 的命名冲突了,在函数 test 里面,j 具有优先权,则此时 j=7。但是它的作用域止步于函数内,而在整个工作区中的变量 j 仍然是 6,故最后输出为 6。可以把工作区的 j 看成是全局变量,而函数中的则为局部变量。
如果想要在函数中改变 j 的值,我们需要把它的值存储起来,一般当成 window 的内联对象的属性使用。例如把 j = 7 改为:
window.j = 7;JavaScript对象
对象和属性
在 JavaScript 中,一个对象可以是一个单独的拥有属性和类型的实体。
一个 JavaScript 对象有很多属性。一个对象的属性可以被解释成一个附加到对象上的变量。对象的属性和普通的 JavaScript 变量基本没什么区别,仅仅是属性属于某个对象。属性定义了对象的特征。你可以通过点符号来访问一个对象的属性。
它是形如:objectName.propertyName 的调用形式,同时我们还可以使用 方括号 访问。例如:
myCar["make"] = "Ford";myCar["model"] = "Mustang";myCar["year"] = 1969;一个对象的属性名(不是属性值)可以是 任何有效的 JavaScript 字符串,或者可以被转换为字符串的任何类型,包括空字符串。然而,一个属性的名称如果不是一个有效的 JavaScript 标识符(例如,一个由空格或连字符,或者以数字开头的属性名),就只能通过 方括号 标记访问。
接下来就是创建对象了,和申明变量一样,只需要申明为对象即可,我们可以通过 new 语句来申明。new 语句可以添加对象或者属性,以及继承结构。它的格式为:new constructor(),例如:
var obj = new Object();obj.year = 2023;delete obj.year;与 C/C++ 不同的是,JavaScript 可以随时申明对象,且 JavaScript 没有类的定义,但是有一些类的特征。
如上例子,我们通过 delete 语句,它可以删除对象中的属性,在例子中它删除了 obj 的 year 属性。
我们默认的构造函数为 Object() 它不会直接向创建的对象添加属性或方法,而是直接修改对象,并继承一些属性与方法,例如 toString() 和 valueOf()。
除此之外,JavaScript 还提供了一个对象初始化器(Object initializer),可以隐式调用构造函数创建对象的同时也创建属性,例如:
var myHonda = { color: "red", wheels: 4, engine: { cylinders: 4, size: 2.2 } };枚举属性
JavaScript 提供了 for...in 语句以任意顺序迭代一个对象的可枚举属性,包括继承的可枚举属性。语法:
for (varName in object) statement例如:
var obj = { a: 1, b: 2, c: 3 };for (var i in obj) { console.log("obj." + i + " = " + obj[i]);}输出:
obj.a = 1obj.b = 2obj.c = 3对象引用
在 JavaScript 中,如果变量代表一个对象, 那么 存储在该变量中的内容就是一个指向该对象的引用(指针),而不是对象本身。
var o1 = new Object();o1.data = "Hello";var o2 = o1;o2.data += " World!";console.log("o1.data = " + o1.data + "\no2.data" + o2.data);
在这里 o2 引用了 o1 的地址,故此时对 o2 的数据改变即对 o1 的数据改变,它们同时都被改变了,因为地址相同。此时的 o2 相当于 o1 的引用(Reference)。
同理在作为函数参数时,对象参数也为对象的引用而不是复制一份。
方法
创建与使用方法
一个方法是关联到某个对象的函数,或者简单地说,一个方法是一个值为某个函数的对象属性。JavaScript 在处理函数上都是以方法来处理的:
- 创建一个专门的函数对象去表示函数。
- 创建一个与函数同名的变量(或赋给对象的某个属性)。
- 为这个变量(或属性)赋予指向函数对象的引用。
使用时调用:objectName.methodName(params)。例如:
对象创建:
function makeBTNode(value) { var node = new Object(); node.left = node.right = null; node.value = value; node.isLeaf = leaf; // 指针指向 leaf(),此时 isLeaf 是方法 return node;}创建 leaf():
function leaf() { return this.left == null && this.right == null;}使用方法:
var node1 = makeBTNode(3);var node2 = makeBTNode(7);node1.right = node2;window.alert("node1 is a leaf: " + node1.isLeaf());window.alert("node2 is a leaf: " + node2.isLeaf());

也可以直接创建方法:
node.isLeaf = function () { return this.left == null && this.right == null;};当把 leaf 看作方法(而不是独立函数)时,不能直接调用 leaf(),而应调用 isLeaf()。
this指针
JavaScript 有一个特殊的关键字 this,它可以在方法中使用以指代当前对象(类似 C++ 中的 this 指针)。例如:
myFather.name = function () { return this.firstName + " " + this.lastName;};构造函数
默认构造函数 Object() 外,我们也可以自己创建构造函数。我们把构造的对象称为构造函数的一个实例(instance)。
例如创建 Car 类型:
function Car(make, model, year) { this.make = make; this.model = model; this.year = year;}创建对象:
var mycar = new Car("Eagle", "Talon TSi", 1993);此时 mycar.make === "Eagle" 等。检测实例:
console.log(mycar instanceof Car);
Object.create()
对象也可以用 Object.create() 方法创建,并指定 原型对象。语法:Object.create(origin_object)。
例如:
var person = { isHuman: false, printIntroduction: function() { console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`); }};
var me = Object.create(person);me.name = 'Matthew';me.isHuman = true;me.printIntroduction();JavaScript数组
我们之前学习知道,JavaScript 对象是可以使用数组表示法来表示的,所以又可以把对象称为关联数组。此外,在 JavaScript 中,数组不是基本类型,而是内置的具有数组特征的 Array 对象。
创建数组
使用构造函数:
var ary1 = Array();var ary2 = Array(4, true, "OK");数组中数据可以是不同类型。
length属性
length 返回或设置数组元素个数:
ary1.length === 0ary2.length === 3
数组下标
JavaScript 数组不是关联数组,下标必须是非负整数,从 0 开始:
ary2[0] = 4ary2[1] = trueary2[2] = "OK"
点号表示法不能访问数字开头的属性,因此 ary2.1 是错误的。
数组初始化器
数组字面量 []:
var ary3 = [4, true, "OK"];多维数组:
var ary4 = [ ["00", "01", "02"], ["10", "11", "12"], ["10", "11", "12"]];
ary4.length === 3;ary4.length === 3;ary4 === "11";动态改变数组
通过下标和 length 动态修改:
var ary2 = Array(4, true, "OK");ary2 = -12.6; // 自动 length++ => 4ary2.length = 2; // 截断到 2 个元素注意:当 Array() 构造函数只有一个 Number 参数时,表示分配固定长度但不初始化:
var ary5 = new Array(5);ary5.length === 5; // 元素未初始化数组方法(常用)
| 方法 | 描述 | 参数 |
|---|---|---|
push() | 尾部添加元素,返回新长度 | 若干元素 |
pop() | 删除并返回尾部元素 | - |
shift() | 删除并返回头部元素 | - |
unshift() | 头部添加元素,返回新长度 | 若干元素 |
sort() | 排序,默认按字符串 Unicode;可传比较函数 | compareFn(a,b) |
splice() | 删除/替换/插入 | start, deleteCount, ...items |
slice() | 返回片段(不含 end) | start, end? |
concat() | 合并数组,返回新数组 | 若干数组 |
join() | 连接为字符串 | 分隔符 |
indexOf() | 返回第一次出现的下标 | 元素 |
reverse() | 反转 | - |
sort()
默认按字符串比较,因此数字需提供比较函数:
const nums = [3, 1, 4, 1, 5, 9];nums.sort((a, b) => a - b); // 升序// 降序:nums.sort((a, b) => b - a);splice()
splice(start)splice(start, deleteCount)splice(start, deleteCount, item1[, item2...])start:起始下标,负数表示从末尾开始deleteCount:删除个数(省略/过大 => 删除到末尾;<=0 不删)items...:要插入的新元素
示例:
var a = [1,2,3,4,5,6,7,8,9];
a.splice(2, 0, 2.5); // 插入// a: 1,2,2.5,3,4,5,6,7,8,9
a.splice(5, 3); // 删除// a: 1,2,2.5,3,4,8,9
// 返回被删除/替换的内容console.log([1,2,3,4,5,6,7,8,9].splice(5,3).toString()); // 5,6,7
// 替换var b = [1,2,3,4,5,6,7,8,9];console.log(b.splice(5,3,10,11).toString()); // 6,7,8console.log(b.toString()); // 1,2,3,4,5,10,11,9
// 只增加var c = [1,2,3,4,5,6,7,8,9];console.log(c.splice(3,0,10,11).toString()); // ""console.log(c.toString()); // 1,2,3,10,11,4,5,6,7,8,9栈与队列实现
- 栈(后进先出):
push+pop - 队列(先进先出):
push+shift
var stack = [];stack.push('H');stack.push('i');stack.push('!');var c3 = stack.pop();var c2 = stack.pop();var c1 = stack.pop();window.alert(c1 + c2 + c3); // "Hi!"JavaScript内置对象
常见内置对象及描述:
| 对象 | 描述 |
|---|---|
Object | 通用对象;可动态添加/删除属性 |
Array | 数组;多种操作方法 |
String | 字符串;常用方法 indexOf/slice/replace/... |
Number | 数字;toFixed/toPrecision/valueOf/... |
Boolean | 布尔;valueOf() |
Date | 日期时间;getFullYear/getTime/... |
Math | 数学常量与函数;Math.random/sin/... |
RegExp | 正则表达式;test/exec |
Function | 函数对象 |
全局对象(Window)
在浏览器中,全局对象为 window:
- 任何全局变量/内置对象都可通过
window属性访问。
var foo = "foobar";foo === window.foo; // true
function greeting() { console.log("Hi!");}window.greeting();例如:window.Infinity、window.alert() 等。
String、Number与Boolean
String(), Number(), Boolean() 作为构造器会包装为对象:
var wrappedNumber = new Number(5.625);window.alert(typeof wrappedNumber.valueOf()); // "number"Number 常用方法:
| 方法 | 描述 |
|---|---|
toFixed() | 指定小数位数 |
toExponential() | 指数表示 |
toPrecision() | 指定有效位数 |
toString() | 转字符串(可传基数) |
valueOf() | 原始值 |
Number.isNaN() | 是否 NaN |
Number.isFinite() | 是否有限 |
Number.parseInt()/parseFloat() | 字符串转整数/浮点 |
Number.MAX_VALUE/MIN_VALUE | 最大/最小正数 |
Number.NEGATIVE_INFINITY/POSITIVE_INFINITY | 负/正无穷 |
示例:
window.alert(wrappedNumber.toFixed(2));window.alert(wrappedNumber.toExponential(2));window.alert(wrappedNumber.toString(2));String 也有 length 与众多方法(charAt/indexOf/slice/split/replace/...)。
Date
Date 用于日期与时间:
new Date();new Date(value);new Date(dateString);new Date(year, monthIndex[, day[, hours[, minutes[, seconds[, milliseconds]]]]]);常用:
| 方法 | 描述 |
|---|---|
Date.now() | 自 1970-01-01 UTC 的毫秒数 |
Date.getFullYear()/getMonth()/getDate() | 年/月/日 |
Date.getHours()/getMinutes()/getSeconds()/getMilliseconds() | 时/分/秒/毫秒 |
toLocaleDateString()/toLocaleTimeString()/toLocaleString() | 本地格式 |
示例:
var now = new Date();window.alert("Current date and time: " + now.toLocaleString());计时:
var startTime = new Date();// ... do work ...var endTime = new Date();window.alert("Processing required " + (endTime - startTime) / 1000 + " seconds.");Math
Math 不是构造函数,直接静态调用。示例方法(部分):
Math.abs/ceil/floor/round/truncMath.max/min/pow/sqrt/randomMath.sin/cos/tan/asin/acos/atan/atan2Math.log/expMath.sign
内置对象的字面量
可用字面量代替构造器:
var x1 = {}; // 对象var x2 = ""; // 字符串var x3 = 0; // 数字var x4 = false; // 布尔var x5 = []; // 数组var x6 = /()/; // 正则var x7 = function(){}; // 函数正则表达式
正则表达式的创建与测试
RegExp(Regular Expression)用于将文本与一个模式匹配,可用于搜索/替换/校验等。
例如测试三位数字(严格整串):
var acTest = /^\d\d\d$/;if (!acTest.test(areaCode)) { window.alert(areaCode + " is not a valid area code.");}说明:
^开头,$结尾,\d匹配数字。也可用构造器:new RegExp("^\\d\\d\\d$")。
元字符(常用)
| 元字符 | 描述 |
|---|---|
. | 匹配除换行外任意单字符 |
\b | 单词边界 |
\w / \W | 字母数字下划线 / 非上述 |
\d / \D | 数字 / 非数字 |
\s / \S | 空白 / 非空白 |
[abc] / [^abc] | 字符集合 / 取反 |
[a-z] [A-Z] [0-9] | 范围 |
^ / $ | 开头 / 结尾 |
() | 分组/捕获 |
\n | 换行(注意与 \b 区分) |
多行模式下 ^/$ 变成匹配每行开头/结尾。
示例:匹配 “hi … Lucy”:
\bhi\b.*\bLucy\b特殊符号(需转义)
| 符号 | 描述 |
|---|---|
\ | 转义 |
| `^ $ . { } ( ) [ ] | ` |
示例:并集(或)\d|\s:数字或空白。
限定符
| 限定符 | 含义 |
|---|---|
* | 前一个元素 0 次或多次 |
+ | 1 次或多次 |
? | 0 次或 1 次 |
{n} | 恰好 n 次 |
{n,} | 至少 n 次 |
{n,m} | n 到 m 次 |
示例:三位数字 \d{3};密码 5-12 位 \d{5,12}
后记
以上为 JavaScript 的基础学习笔记部分。