使用 javascript

HTML 中的 Javascript 脚本代码必须位于 <script></script> 标签之间。

Javascript 脚本代码可被放置在 HTML 页面的 <body><head> 部分中

javascript 的基础语法

输出

js有四种不同的方法来输出数据:

  • 使用 window.alert() 弹出警告框
  • 使用 document.write() 方法将内容写到 HTML 文档中
  • 使用 innerHTML 写入到 HTML 元素
  • 使用 console.log() 写入到浏览器的控制台

alertconsole.log 都没什么好说的,比较特别的是 document.writeinnerHTML 是两个 DOM 方法,其使用方法为:

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

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>

<script>

document.write("<h1>这是一个标题</h1>");

</script>

</body>

</html>

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 lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>
<h1 id="title"></h1>

<script>

document.getElementById("title").innerHTML = "innerHTML修改的标题";

</script>

</body>

</html>

变量的声明

在 js 中,我们可以使用关键字 var 来声明一个变量,并不需要明确其类型,js 是一种动态类型,弱类型的语言,也就是说可以先赋值为整型接着再将其变为字符串类型

1
2
var val = 5;
val = '123';

在 es6 标准后,可使用 letconst 来声明变量,避免 var 声明变量导致的变量提升问题
1
2
let val = 5;         // 声明一个可变的变量
const c_val = 5; // 声明一个常量

数据类型

值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。

引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)

1
2
3
4
5
let length = 16;                                  // Number 通过数字字面量赋值
let points = length * 10; // Number 通过表达式字面量赋值
let lastName = 'Johnson'; // String 通过字符串字面量赋值
let cars = ['Saab', 'Volvo', 'BMW']; // Array 通过数组字面量赋值
let person = {firstName:'John', lastName:'Doe'}; // Object 通过对象字面量赋值

可以使用 typeof 来查看变量的类型

1
2
3
4
5
6
7
let a = 5;
let str = '1234';
let flag = false;

console.log(typeof a); // number
console.log(typeof str); // string
console.log(typeof flag); // boolean

js中的函数

函数的声明方式

1
2
3
function [functionname]([args]) {
// dosomething
}

例如使用 js 函数实现线性插值:
1
2
3
function lerp(from, to, fac) {
return from + fac * (to - from);
}

匿名函数:

因为在 js 中函数是第一公民,所以我们可以使用函数之间当参数,此处就是使用了一个匿名函数来返回 fac 的值,注意在 lerp 函数体重需要先获取 facFn 的值,否则函数得出的结果将是 NaN (Not a number)
1
2
3
4
5
6
7
8
9
10
function lerp(from, to, facFn) {
const fac = facFn();
return from + fac * (to - from);
}

let res = lerp(0, 1, function () {
return 0.25;
});

console.log(res);

在 es6 之后,我们还可以使用箭头函数的方式来创建匿名函数
1
2
3
4
5
6
7
8
function lerp(from, to, facFN) {
const fac = facFN();
return from + fac * (to - from);
}

let res = lerp(0, 1, () => {
return 0.25;
});

js中的对象

对象声明以花括号分隔,对象的属性以名称和值的键值对方式存储,属性使用逗号分隔:

1
2
3
4
let person = {
name: 'nico',
age: 16
};

对象属性的访问方法用两种:
1
2
person.name;
person["name"];

class

es6 以后,我们可以使用新引入的 class 来拥有定义类的能力

类的定义方式

1
2
3
4
5
// 类声明
class A {}

// 类表达式
const A = class {}

注意: 函数声明和类声明之间的一个重要区别在于,函数声明会提升,类声明不会。需要先声明类,然后再访问它,否则就会出现ReferenceError

构造函数

一个类只能拥有一个名为 constructor 构造函数,不能出现多个,如果定义了多个 constructor 构造函数,则将抛出 一个 SyntaxError错误

如果没有定义 constructor 构造函数,class 会默认添加一个空的 constructor 构造函数。

1
2
3
4
5
class A {}
// 等同于
class A {
constructor() {}
}

继承

使用 super 可以调用父类的构造函数,属性,函数。只能在构造函数中使用且必须在使用 this 之前

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A {
constructor() {
this.name = "A";
}
}

class B extends A{
constructor() {
super();
}
}

let a = new B();
console.log(a.name); // output A

js的字符串

声明:

1
let str = 'hello world';

获取其中某个字符:
1
2
3
const str = 'hello world';
// the range of index is [0, length)
let c = str[0]; // 'h'

获取长度:
1
2
const str = 'hello world';
let str_len = str.length; // 11

字符串模板:

模板字符串使用反引号 ` 作为字符串的定界符分隔的字面量。

模板字面量是用反引号()分隔的字面量,允许多行字符串、带嵌入表达式的字符串插值和一种叫带标签的模板的特殊结构。 例如:

1
2
3
4
5
6
7
let person = {
name: 'nico',
age: 12
};

const str = `the person is ${person.name} and she is ${person.age} years old`;
// the person is nico and she is 12 years old
这算是一种拼接字符串的高效方式,<s>不过我更喜欢 c++ 的std::format或者 rust 的format!` </s>

js的循环语句

以下三种循环和 c 系语言都大同小异一模一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for (let i = 0; i < 5; i++) {
console.log(i);
}

let i = 0;
while (i < 5) {
console.log(i);
i++;
}

let i = 0;
do {
console.log(i);
i++;
} while (i < 5);

值得注意的是 js 中的 foreach 语法:

for...in 是用来遍历对象中的属性的,例如以下代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let object = {
a: 1,
b: 2,
c: 3
};
for (let x in object) {
console.log(x);
}

/* output:
a
b
c
*/

for..of 语法是用来遍历可迭代对象中的元素的,即原型应该为:
1
2
3
for (variable of iterable) {
// dosomething
}

因此可以使用其来遍历 Map 这种可迭代对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const kvMap = new Map();
kvMap.set('key1', 'value1');
kvMap.set('key2', 'value2');
kvMap.set('key3', 'value3');

for (const [key, value] of kvMap) {
console.log(key, value);
}

/* output:
key1 value1
key2 value2
key3 value3
*/

同时还有一种,在 js 中,数组、Map、Set、类数组对象(例如 HTMLCollection、NodeList)等类型内置了 forEach 方法,配合匿名函数,能很优雅地写出对其的操作
1
2
3
4
const arr = [1, 3, 4, 7, 9];
arr.forEach((x) => {
console.log(x);
})

DOM 对象

文档对象模型(Document Object Model,简称 DOM),是一种与平台和语言无关的模型,用来表示 HTML 或 XML 文档。文档对象模型中定义了文档的逻辑结构,以及程序访问和操作文档的方式。

当我们打开网页加载的时候,浏览器就会自动创建当前页面的文档对象模型(DOM),所有 元素属性文本 等就会被组织为一棵树状结构,每一个结点都是一个对象,我们可以使用 js 访问 Document 对象及其接口

基本的方法

方法 描述
document.getElementsByClassName() 返回文档中所有具有指定类名的元素集合
document.getElementById() 返回文档中具有指定 id 属性的元素
document.getElementsByName() 返回具有指定 name 属性的对象集合
document.getElementsByTagName() 返回具有指定标签名的对象集合
document.querySelector() 返回文档中具有指定 CSS 选择器的第一个元素
document.querySelectorAll() 返回文档中具有指定 CSS 选择器的所有元素

以上是一些基本的获取 dom 中元素的接口,例如要获取一个文本框中的内容:

1
2
3
4
5
6
7
8
9
10
11
<input type="text" id="username">
<button id="btn">alert一下</button>

<script>

let username = document.getElementById("username");
document.getElementById("btn").onclick = () => {
alert(username.value);
};

</script>