8060 字
40 分钟
【WEB】客户端编程与JavaScript语言

前言#

经过前两章的学习,我们知道:

  • HTML 是一种标记语言,用来结构化我们的网页内容并赋予内容含义,例如定义段落、标题和数据表,或在页面中嵌入图片和视频。
  • CSS 是一种样式规则语言,可将样式应用于 HTML 内容,例如设置背景颜色和字体,在多个列中布局内容。

而这样的网页仍然是个静态的网页,不能对结果做出反应。而现实中我们希望网站能与用户进行一些交互与反馈,例如输入账号密码后登录,动态检测账号密码正不正确,给出反馈。

于是我们就有一个解决方案,使用 JavaScript。JavaScript 是一种脚本语言,可以用来创建动态更新的内容,控制多媒体,制作图像动画,还有很多。

接下来这一章将介绍基础的 JavaScript 相关知识。

特别参考: MDN · W3School


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 中引用它。

我们一般有这样的步骤:

  1. 首先,在刚才的 HTML 文件所在的目录下创建一个名为 script.js 的新文件。请确保扩展名为 .js,只有这样才能被识别为 JavaScript 代码。

  2. <head> 元素或者 <body> 元素中添加引用元素 <script>,这里是:

    <script src="script.js" async></script>
  3. script.js 文件中,添加之前的例子代码。

  4. 保存并刷新浏览器,即可成功引用 JavaScript 代码。

当然,和外部 CSS 一样,我们的 src 属性处填写的是地址,它可以包括绝对地址与相对地址。

JavaScript语法#

知道了如何引入 JavaScript 后,我们就正式进入 JavaScript 语法的介绍。

注释与分号#

与 Java 和 C++ 中一样,JavaScript 中的注释也是用 ///* */ 表示的。

变量与数据类型#

一个变量,就是一个用于存放数值的容器。这个数值可能是一个用于累加计算的数字,或者是一个句子中的字符串。变量的独特之处在于它存放的数值是可以改变的。

在 JavaScript 中,声明一个变量的语法是在 varlet 关键字之后加上这个变量的名字

例如:

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)
);

img

img

您可能会想:“为什么我们需要两个关键字来定义变量?”,“为什么有 varlet 呢?”

使用 var 关键字重新声明变量会带来问题,而使用 let 关键字重新声明变量可以解决这个问题。即 var 和我们平时定义变量规则相同,而 let 在更小的代码块中可以重新定义。

// 使用 var
var x = 10;
// 此处 x 为 10
{
var x = 6;
// 此处 x 为 6
}
// 此处 x 为 6
// 使用 let
var x = 10;
// 此处 x 为 10
{
let x = 6;
// 此处 x 为 6
}
// 此处 x 为 10

对于变量名的命名规则,我们有以下规则:

  • 你不应当使用规则之外的其他字符,因为它们可能引发错误,或对国际用户来说难以理解。
  • 变量名不要以下划线开头—— 以下划线开头的被某些 JavaScript 设计为特殊的含义,因此可能让人迷惑。
  • 变量名不要以数字开头。这种行为是不被允许的,并且将引发一个错误。
  • 一个可靠的命名约定叫做 “小写驼峰命名法 ”,用来将多个单词组在一起,小写整个命名的第一个字母然后大写剩下单词的首字符。例如 myName
  • 让变量名直观,它们描述了所包含的数据。不要只使用单一的字母/数字,或者长句。
  • 变量名大小写敏感——因此 myagemyAge 是 2 个不同的变量。
  • 最后也是最重要的一点—— 你应当避免使用 JavaScript 的保留字给变量命名。保留字,即是组成 JavaScript 的实际语法的单词!因此诸如 varfunctionletfor 等,都不能被作为变量名使用。浏览器将把它们识别为不同的代码项,因此你将得到错误。

数据类型转换#

JavaScript 中有一些数据类型自动转换的功能。例如转换为布尔类型:

img

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

img

img

JavaScript输出#

和其他语言不同的是,JavaScript 不提供任何内建的打印或显示函数。

于是 JavaScript 的输出一般用不同方式“显示”数据:

  • 使用 window.alert() 写入警告框
  • 使用 document.write() 写入 HTML 输出
  • 使用 innerHTML 写入 HTML 元素
  • 使用 console.log() 写入浏览器控制台

其中数据的内容可以是表达式也可以是变量。

我们最常用的就是 window.alert() 它会弹出一个对话框输出文字,例如:

window.alert(5 + 6);

img

而如果我们的输出要到 HTML 中的话,一般在 HTML 中使用 document.write()。但是这样会导致清空文档流内容,重新渲染。例如这是一个内联脚本:

<body>
<h2>我的第一张网页</h2>
<p>我的第一个段落。</p>
<button type="button" onclick="document.write(5 + 6)">试一试</button>
</body>

img

当我们点击按钮后,就会变成:

img

此时之前的一个二级标题和段落被清空了,取而代之的是一个表达式的值。

因为 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>

img

此时 id 为 textp 元素内容被 innerHTML 替换了。而其他元素则不变。

最后我们还可以在浏览器中,使用 console.log() 方法在控制台中显示数据。通过 F12 来激活浏览器控制台,并在菜单中选择“控制台”。就可以看到我们的输出了,例如:

console.log("from script file");

img


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[]、.方括号和点符号 (成员访问)
18new对象创建
17++、—自增/自减
16!、~、+、-、typeof、void、delete逻辑非、按位取反、一元加/减、类型检测、无操作、对象属性删除
15*、/、%乘法、除法、取模
14+、-加法、减法
13<<、>>、>>>左移、右移 (带符号/不带符号)
12<、<=、>、>=、in、instanceof比较、属性存在性测试、实例关系测试
11==、!=、===、!==相等性测试
10&按位与
9^按位异或
8|按位或
7&&逻辑与
6||逻辑或
5?:条件运算符
4=、+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、^=、|=赋值运算符
3yield生成器函数中的产出操作
2,逗号运算符 (多个表达式串联)
1await异步函数中的暂停操作

其中,在优先级相同的情况下,大部分 JavaScript 会按 从左到右 的顺序依次计算运算符。但是下面类型的语句则是 从右到左 的顺序执行。

  1. 赋值运算符:赋值运算符的右侧表达式先执行,然后结果被赋值给左侧变量。

    let a, b;
    a = (b = 5); // 先将 5 赋值给 b, 然后 b 的值再赋值给 a
  2. 条件(ternary)运算符(?:):从右向左计算,在条件为真时执行第一个表达式,否则执行第二个表达式。

    let x = true ? 1 : 2; // x 为 1
    let y = false ? 1 : 2; // y 为 2
  3. 逗号运算符(,):从左到右执行,但返回的是最右边表达式的值。

    let a = (1, 2, 3, 4); // a 的值为 4
  4. 属性访问符(.)和数组下标访问符([]):都是从左到右计算,但是当多次使用时,则是从左到右依次执行,并且数组下标访问符在这种情况下比属性访问符优先级更高。

    const obj = { a: { b: 1 } };
    console.log(obj.a.b); // 从左到右
    const arr = [1,;
    console.log(arr[0]); // 从左到右

自动类型转换#

在执行运算符时,与其他语言不同的是,JavaScript 会执行自动类型转换。例如转换成 Number 与 String 类:

x = 7 + 8; // Number
y = "7" + 8; // Number
z = "Hello" + 7; // String

其中 y 将字符串 “7” 转换成了 number 型,进行相加,返回为 number 型。z 则是把数字 7 转换成了字符型,返回为 “Hello7”。一般来说,数字 + 字符串结果为字符串

而对于比较运算符,比较不同类型的数据也许会出现不可预料的结果。

案例
2 < 12true
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 & 10101 & 000100011
|5 | 10101 | 000101015
~~ 5~0101101010
^异或5 ^ 10101 ^ 000101004
<<逻辑左移5 << 10101 << 1101010
>>逻辑右移5 >> 10101 >> 100102
>>>算术右移5 >>> 10101 >>> 100102

其中逻辑右移和算术右移的区别在于,逻辑右移后左侧补 0,适用于无符号。算术右移后左侧补符号位,适用于有符号。


字面量#

字面量是由语法表达式定义的 常量;或通过由一定字词组成的语词表达式定义的常量。

在 JavaScript 中,你可以使用各种字面量。这些字面量是脚本中按字面意思给出的固定的值,而不是变量。

数字字面量#

对于整数,根据数字系统,整数可以用十进制(基数为 10)、十六进制(基数为 16)、八进制(基数为 8)以及二进制(基数为 2)表示。

  • 十进制整数字面量由一串数字序列组成,且没有前缀 0。
  • 八进制的整数以 0(或 0O、0o)开头,只能包括数字 0-7。
  • 十六进制整数以 0x(或 0X)开头,可以包含数字(0-9)和字母 af 或 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"

常见转义:

字符意思
\0Null 字节
\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 = 1
obj.b = 2
obj.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);

img

在这里 o2 引用了 o1 的地址,故此时对 o2 的数据改变即对 o1 的数据改变,它们同时都被改变了,因为地址相同。此时的 o2 相当于 o1 的引用(Reference)。

同理在作为函数参数时,对象参数也为对象的引用而不是复制一份。

方法#

创建与使用方法#

一个方法是关联到某个对象的函数,或者简单地说,一个方法是一个值为某个函数的对象属性。JavaScript 在处理函数上都是以方法来处理的:

  1. 创建一个专门的函数对象去表示函数。
  2. 创建一个与函数同名的变量(或赋给对象的某个属性)。
  3. 为这个变量(或属性)赋予指向函数对象的引用。

使用时调用: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());

img img

也可以直接创建方法:

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);

img

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 === 0
  • ary2.length === 3

数组下标#

JavaScript 数组不是关联数组,下标必须是非负整数,从 0 开始:

  • ary2[0] = 4
  • ary2[1] = true
  • ary2[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++ => 4
ary2.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,8
console.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.Infinitywindow.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/trunc
  • Math.max/min/pow/sqrt/random
  • Math.sin/cos/tan/asin/acos/atan/atan2
  • Math.log/exp
  • Math.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 的基础学习笔记部分。

【WEB】客户端编程与JavaScript语言
https://hoyue.fun/web_4.html
作者
Hoyue
发布于
2023-04-09
最后更新于
2023-05-17
许可协议
CC BY-NC-SA 4.0
评论