typescript
html / CSS
主要介绍 html/css 入门知识,用来做 typescript 的前置知识。配套课程文件
html
HTML(Hypertext Markup Language):The language your web browser uses to describe the content and structure of web pages
如果整个网页当作人体,那么 html 就是骨架,决定每一资源放置的位置
1 |
|

文档对象模型(DOM)通过将文档的结构(例如表示网页的 HTML)以对象的形式存储在内存中,将网页与脚本或编程语言连接起来。尽管将 HTML、SVG 或 XML 文档建模为对象并不是 JavaScript 核心语言的一部分,但它通常与 JavaScript 相关。
DOM 使用逻辑树的形式来表示文档。树的每个分支末端都是一个节点,每个节点都包含对象。DOM 方法允许以编程方式来访问树。借助这些方法,你可以改变文档的结构、样式或内容。
节点还可以附加事件处理器。一旦事件被触发,相应的事件处理器就会被执行。
html 是按照 “DOM” (Document Object Model) 的结构进行表达的。因此,上述代码中包含一个 header 和 一个 body。
其中 header 是不可见的,其中包含有
tag
html 中的 tag 是由两部分组成的,分别叫做 Opening Tag 和 Closing Tag
1 | <tagName> content </tagName> |
除此之外,tag 中还可以加入属性(attribute)
HTML Attribute(HTML 属性) 是写在开始标签内部的额外信息,用于配置或修饰该元素的行为、样式或内容。
1 | <tagName ABC = "XYZ"> content </tagName> |
此外,还有一类特殊的标签——它们没有内容,因此可以省略闭合标签 ,这类标签称为 Void Elements(空元素 / 自闭合标签)。例如:
| 标签 | 作用 |
|---|---|
<img> |
嵌入图片 |
<br> |
换行 |
<hr> |
水平分隔线 |
<input> |
输入框 |
<meta> |
元信息 |
<link> |
引入外部资源(如 CSS) |
<area> |
图像映射区域 |
<base> |
基准 URL |
<col> |
表格列属性 |
<embed> |
嵌入外部内容 |
<param> |
对象参数 |
<source> |
媒体资源 |
<track> |
媒体字幕 |
<wbr> |
可选换行点 |
使用方法如下:
1 | <!-- 简洁写法(推荐) --> |
header
Common tag
1 | <!-- 插入链接 --> |
其中比较特殊的是 <div> 和 <span>:<div> 本质上是创建了一个 box(块级容器),用于将所有内容封装到一个独立的盒子中;<span> 本质上则是一个 行内标记,用于在文本流中包裹小段内容而不打断布局。
1 |
|

但是,在后续的 html5 中引入了语义化标签,可以明显添加可读性,然后简化语法,可以减少使用 <div> 的使用。
CSS
CSS(Cascading Style Sheets):The rules that tell your web browser how stuff looks
如果说 html 是整个网页的骨架,那么 css 就是用来美化这些骨架的衣服。可以让我们的网页变的更加的美观。
基础的语法为
1 | selector { |
一个基础的示例为:
1 | /* 这是注释 */ |
这部分直接使用 <style> 将 css 嵌入到 html 中
1 |
|
另外我们还可以使用 . 来进行选择指定的 class 属性,比如下面就直接使用匹配 info
1 | .info { |
1 |
|
或者使用 # 直接匹配对应的 id
1 | #info { |
1 |
|
css 生效优先级
由于每个元素只能拥有一个 id,因此 id 通常用于定义唯一的、完整的样式规则。相比之下,一个元素可以拥有多个 class,每个 class 负责不同的样式维度——例如一个控制布局尺寸,另一个控制颜色字体。此外,class 可以被多个元素复用,从而减少重复代码,提高开发效率。
由于可能存在有多种格式,因此 css 具体要相关的层级:
| 层级 | 来源 | 说明 |
|---|---|---|
| 1 | !important |
最高优先级,慎用 |
| 2 | 行内样式(Inline) | <div style="..."> |
| 3 | ID 选择器 | #header |
| 4 | 类 / 伪类 / 属性 | .btn、:hover、[type] |
| 5 | 元素 / 伪元素 | div、::before |
| 6 | 通用选择器 | * |
| 7 | 继承(Inherited) | 父元素传给子元素 |
| 8 | 浏览器默认样式 | User Agent Stylesheet |
css 变量
CSS 变量 = 用 --name 定义,用 var() 调用,通常放在 :root 里做全局配色/尺寸配置,方便统一管理和维护。
1 | :root { |
Box Model
所有HTML元素可以看作盒子,在CSS中,box model这一术语是用来设计和布局时使用。
CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。
盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。
下面的图片说明了盒子模型(Box Model):

不同部分的说明:
- Margin(外边距) - 清除边框外的区域,外边距是透明的。
- Border(边框) - 围绕在内边距和内容外的边框。
- Padding(内边距) - 清除内容周围的区域,内边距是透明的。
- Content(内容) - 盒子的内容,显示文本和图像。
最终元素的总宽度计算公式是这样的:
总元素的宽度=宽度+左填充+右填充+左边框+右边框+左边距+右边距
元素的总高度最终计算公式是这样的:
总元素的高度=高度+顶部填充+底部填充+上边框+下边框+上边距+下边距
html + css
如何将 html 和 css 文件结合起来,最佳做法是在 <head> 元素中添加一个 <link> 元素,并带上 rel 和 href 属性。
rel 是 relationship(关系)的缩写。
另外注意,这看起来可能和之前超链接页面的示例有点像——但那个用的是<a>标签,而这里用的是<link>标签。<link>实际上是专门用于链接外部资源(比如 CSS 文件)的场景。
规范
8pt Grid System
8pt Grid System(8 点网格系统) 是一种 UI 设计规范,要求所有元素的尺寸、间距、边距都使用 8 的倍数。
javaScript
该部分内容建立在有 golang, python 和 C 的基础上进行补充学习。
JavaScript(简称 js) 是一种控制网页的脚本语言,可以完成 html 和 css 之间的互动。
js 是一个大小写敏感,如果一条语句独占一行的话,那么分号是可以省略的。但如果一行中有多条语句,那么这些语句必须用分号进行分隔。
在一条语句的末尾总是加上分号被认为是最佳实践,即使是在非严格需要的时候。这个习惯可以大大减少代码出问题的可能性。
你可能也会在一些 JavaScript 文件的开头见到像 #!/usr/bin/env node 这样的第三种注释。它叫做 hashbang 注释语法,是一种用于指定执行脚本的特定 Javascript 引擎路径的特殊注释。
type
js 一共有五种主要的数据类型:
- Boolean(true,false)
- Number(0, -12.1, 123.12)
- String
- Null
- undefined
- BigInt
- Symbol 其实例是唯一且不可变的数据类型。
operators
常规运算符
| 符号 | 名称 | 示例 | 结果 |
|---|---|---|---|
+ |
加 | 5 + 3 |
8 |
- |
减 | 5 - 3 |
2 |
* |
乘 | 5 * 3 |
15 |
/ |
除 | 5 / 2 |
2.5 |
% |
取余 | 5 % 2 |
1 |
** |
幂运算 | 2 ** 3 |
8 |
++ |
自增 | a++ / ++a |
先返回再加 / 先加再返回 |
-- |
自减 | a-- / --a |
先返回再减 / 先减再返回 |
| 符号 | 名称 | 示例 | 等价于 |
|---|---|---|---|
= |
赋值 | a = 5 |
— |
+= |
加等 | a += 3 |
a = a + 3 |
-= |
减等 | a -= 3 |
a = a - 3 |
*= |
乘等 | a *= 3 |
a = a * 3 |
/= |
除等 | a /= 3 |
a = a / 3 |
%= |
余等 | a %= 3 |
a = a % 3 |
**= |
幂等 | a **= 3 |
a = a ** 3 |
| 符号 | 名称 | 示例 | 说明 |
|---|---|---|---|
== |
相等 | 5 == "5" |
true(值相等,类型可不同) |
=== |
严格相等 | 5 === "5" |
false(值和类型都相同) |
!= |
不等 | 5 != 3 |
true |
!== |
严格不等 | 5 !== "5" |
true |
> |
大于 | 5 > 3 |
true |
< |
小于 | 5 < 3 |
false |
>= |
大于等于 | 5 >= 5 |
true |
<= |
小于等于 | 5 <= 3 |
false |
| 符号 | 名称 | 示例 | 说明 |
|---|---|---|---|
&& |
逻辑与 | a && b |
两者都为真才为真 |
\|\| |
逻辑或 | a \|\| b |
至少一个为真即为真 |
! |
逻辑非 | !a |
取反 |
?? |
空值合并 | a ?? b |
a 为 null 或 undefined 时返回 b |
| 符号 | 名称 | 示例 |
|---|---|---|
& |
按位与 | 5 & 3 → 1 |
\| |
按位或 | 5 \| 3 → 7 |
^ |
按位异或 | 5 ^ 3 → 6 |
~ |
按位非 | ~5 → -6 |
<< |
左移 | 5 << 1 → 10 |
>> |
右移 | 5 >> 1 → 2 |
| 符号 | 名称 | 示例 | 说明 |
|---|---|---|---|
? : |
三元运算符 | a > b ? "大" : "小" |
条件判断简写 |
typeof |
类型检测 | typeof 123 → "number" |
返回数据类型 |
instanceof |
实例检测 | arr instanceof Array |
判断是否某类的实例 |
... |
展开运算符 | [...arr] / fn(...args) |
展开数组或对象 |
?. |
可选链 | obj?.name |
避免访问 null 报错 |
??= |
逻辑空赋值 | a ??= b |
a 为空时赋值为 b |
- 在使用 + 运算符的表达式中涉及数字和字符串,JavaScript 会把数字转换成字符串。在使用其他运算符时,JavaScript 不会把数字转换成字符串。
- 将字符串转换为数字的另一种方法是使用 +(一元加)运算符。
1 | "1.1" + "1.1" = "1.11.1" |
一元运算符
delete
delete操作符,删除一个对象的属性或者一个数组中某一个键值。
1 | delete objectName.property; |
当前 with 已经被废弃,他会导致作用域混乱,性能下降。
在严格模式(“use strict”)下,对不可删除的属性使用 delete 会抛出 TypeError,而非静默返回 false。
- 如果 delete 操作成功,属性或者元素会变成 undefined。如果 delete可行会返回true,如果不成功返回false。
- 删除数组中的元素时,数组的长度是不变的,例如删除 a[3], a[4],a[4] 和 a[3] 仍然存在变成了 undefined。delete 删除数组中的一个元素,这个元素就不在数组中了。例如,trees[3]被删除,trees[3] 仍然可寻址并返回 undefined。
1 | // 正常删除 |
typeof
1 | typeof operand; |
typeof 操作符返回一个表示 operand 类型的字符串值。operand 可为字符串、变量、关键词或对象,其类型将被返回。operand 两侧的括号为可选。
void
1 | void expression; |
void 运算符,表明一个运算没有返回值。expression 是 javaScript 表达式,括号中的表达式是一个可选项,当然使用该方式是一种好的形式。
你可以使用 void 运算符指明一个超文本链接。该表达式是有效的,但是并不会在当前文档中进行加载。
in
in操作符,如果所指定的属性确实存在于所指定的对象中,则会返回true,语法如下:
1 | propNameOrNumber in objectName; |
在这里 propNameOrNumber可以是一个代表着属性名的字符串或者是一个代表着数组索引的数值表达式,而objectName则是一个对象名。
1 | // Arrays |
instanceof
如果所判别的对象确实是所指定的类型,则返回true。其语法如下:
1 | objectName instanceof objectType; |
objectName 是需要做判别的对象的名称,而objectType是假定的对象的类型,例如Date或 Array.
当你需要确认一个对象在运行时的类型时,可使用instanceof. 例如,需要 catch 异常时,你可以针对抛出异常的类型,来做不同的异常处理。
this
this关键字被用于指代当前的对象,通常,this指代的是方法中正在被调用的对象。用法如下:
1 | this["propertyName"]; |
()
分组操作符()控制了表达式中计算的优先级。举例来说,你可以改变先乘除后加减的顺序,转而先计算加法。
new
你可以使用 new 运算符创建一个自定义类型或者是预置类型的对象实例。用法如下:
1 | var objectName = new objectType([param1, param2, ..., paramN]); |
super
super 关键字可以用来调用一个对象父类的函数,它在用来调用一个类的父类的构造函数时非常有用,比如:
1 | super([arguments]); // calls the parent constructor. super.functionOnParent([arguments]); |
运算优先级
| 优先级 | 运算符类型 | 结合性 | 运算符 |
|---|---|---|---|
| 19 | 分组 | n/a | ( … ) |
| 18 | 成员访问 | 从左到右 | … . … |
| 18 | 需计算的成员访问 | 从左到右 | … [ … ] |
| 18 | new(带参数列表) | n/a | new … ( … ) |
| 18 | 函数调用 | 从左到右 | … ( … ) |
| 18 | 可选链(Optional chaining) | 从左到右 | ?. |
| 17 | new(无参数列表) | 从右到左 | new … |
| 16 | 后置递增 | n/a | … ++ |
| 16 | 后置递减 | n/a | … -- |
| 15 | 逻辑非 (!) |
从右到左 | ! … |
| 15 | 按位非 (~) |
从右到左 | ~ … |
| 15 | 一元加法 (+) |
从右到左 | + … |
| 15 | 一元减法 (-) |
从右到左 | - … |
| 15 | 前置递增 | 从右到左 | ++ … |
| 15 | 前置递减 | 从右到左 | -- … |
| 15 | typeof |
从右到左 | typeof … |
| 15 | void |
从右到左 | void … |
| 15 | delete |
从右到左 | delete … |
| 15 | await |
从右到左 | await … |
| 14 | 幂 (**) |
从右到左 | … ** … |
| 13 | 乘法 (*) |
从左到右 | … * … |
| 13 | 除法 (/) |
从左到右 | … / … |
| 13 | 取余 (%) |
从左到右 | … % … |
| 12 | 加法 (+) |
从左到右 | … + … |
| 12 | 减法 (-) |
从左到右 | … - … |
| 11 | 按位左移 (<<) |
从左到右 | … << … |
| 11 | 按位右移 (>>) |
从左到右 | … >> … |
| 11 | 无符号右移 (>>>) |
从左到右 | … >>> … |
| 10 | 小于 (<) |
从左到右 | … < … |
| 10 | 小于等于 (<=) |
从左到右 | … <= … |
| 10 | 大于 (>) |
从左到右 | … > … |
| 10 | 大于等于 (>=) |
从左到右 | … >= … |
| 10 | in |
从左到右 | … in … |
| 10 | instanceof |
从左到右 | … instanceof … |
| 9 | 相等 (==) |
从左到右 | … == … |
| 9 | 不相等 (!=) |
从左到右 | … != … |
| 9 | 严格相等 (===) |
从左到右 | … === … |
| 9 | 严格不相等 (!==) |
从左到右 | … !== … |
| 8 | 按位与 (&) |
从左到右 | … & … |
| 7 | 按位异或 (^) |
从左到右 | … ^ … |
| 6 | 按位或 (\|) |
从左到右 | … \| … |
| 5 | 逻辑与 (&&) |
从左到右 | … && … |
| 4 | 逻辑或 (\|\|) |
从左到右 | … \|\| … |
| 4 | 空值合并 (??) |
从左到右 | … ?? … |
| 3 | 条件(三元)运算符 | 从右到左 | … ? … : … |
| 2 | 赋值 | 从右到左 | … = … |
| 2 | 加等赋值 | 从右到左 | … += … |
| 2 | 减等赋值 | 从右到左 | … -= … |
| 2 | 幂等赋值 | 从右到左 | … **= … |
| 2 | 乘等赋值 | 从右到左 | … *= … |
| 2 | 除等赋值 | 从右到左 | … /= … |
| 2 | 余等赋值 | 从右到左 | … %= … |
| 2 | 左移等赋值 | 从右到左 | … <<= … |
| 2 | 右移等赋值 | 从右到左 | … >>= … |
| 2 | 无符号右移等赋值 | 从右到左 | … >>>= … |
| 2 | 按位与等赋值 | 从右到左 | … &= … |
| 2 | 按位异或等赋值 | 从右到左 | … ^= … |
| 2 | 按位或等赋值 | 从右到左 | … \|= … |
| 2 | 逻辑与等赋值 | 从右到左 | … &&= … |
| 2 | 逻辑或等赋值 | 从右到左 | … \|\|= … |
| 2 | 空值合并等赋值 | 从右到左 | … ??= … |
| 1 | 逗号 / 序列 | 从左到右 | … , … |
declaration
- var:声明一个变量,可选择将其初始化为一个值。可以用来声明局部,或者全局变量
- let:声明一个块级作用域的局部变量,可选择将其初始化为一个值。用来声明块级作用域的局部变量。
- const:声明一个块级作用域的只读命名常量。
另外,js 还有解构语法用于解包值
1 | let a, b, rest; |
array
- 数组
- 布尔值数组
- 数字数组
- 对象数组
- 字符串数组
- RegExp 数组
数组字面量中的多余逗号
1 | const fish = ["Lion", , "Angel"]; |
打印出数组的形式为:
1 | console.log(fish); |
注意,第二项是“empty”,与实际的 undefined 值完全不同。当使用数组遍历方法(例如,Array.prototype.map)时,空槽会被跳过。然而,索引访问 fish[1] 仍会返回 undefined。
如果你在元素列表的尾部添加了一个逗号,它将会被忽略。
在书写代码时,应该显式地将缺失的元素声明为 undefined,或者至少插入一个注释以突出元素缺失。这样做能提高代码的清晰度和维护性。
另外,还有一种形式,数组长度为 4:
1 | const myList = ["home", , "school", ,]; |
这个可以省略最后一个逗号
1 | const myList = ["home", , "school", ]; |
尾后逗号在多行数组中能保持 git diff 整洁,因为向末尾添加元素只需要添加一行,而不需要修改前面的行。
对象字面值
对象字面值是由一对花括号 ({}) 括起来的包含零个或者多个属性名和相关值的列表。如果合法,那么使用 . 来访问,如果名字非法,那么使用 [] 来访问。
1 | const car = { manyCars: { a: "Saab", b: "Jeep" }, 7: "Mazda" }; |
此外,还有增强型对象字面量
1 | // 1. 定义原型对象,其 toString() 返回 42 |
RegExp 字面值
一个正则表达式字面量是字符被正斜杠围成的表达式。下面是正则表达式字面量的一个示例。
1 | const re = /ab+c/; |
关键字
1 | // ========== 控制流 ========== |
假值
下面这些值求值为 false(也叫做假值):
- false
- undefined
- null
- 0
- NaN
- 空字符串("")
对面字面量恒为真
布尔值和 Boolean 对象有一定区别,下面代码中 b 为 Boolean 对象,对象值恒为真
1 | const b = new Boolean(false); |
for in 和 for of 实现逻辑
1 | const arr = [3, 5, 7]; |
为什么他们的输出逻辑不一样,这个是 JavaScript 的底层逻辑决定的:
1 | arr = { |
for…of 不直接遍历对象的属性,而是调用数组的 [Symbol.iterator] 迭代器。这个迭代器的内部逻辑是:
empty slot 不会被跳过,而是返回 undefined(因为迭代器会访问 arr[3],发现没有值,就返回 undefined)
1 | // 伪代码:数组迭代器的内部实现 |
for…in 遍历的是对象所有可枚举(enumerable)的属性名,包括继承自原型链上的可枚举属性。其内部逻辑大致为:
1 | // 伪代码:for...in 的内部实现 |
此外,底层的存储方式是:如果是一个连续的数组,那么就会直接使用一串连续的内存来保存对应的数组值。如果是加入了大量其他的属性、或者数组变得极度稀疏(如 arr[10000] = 1),那么就会退化成 hash 表。但是退化之后,数字索引部分还是会按照数值进行排序存储,字符串属性则按插入顺序排列,以保证 for…in 和 for…of 的输出顺序符合 ECMAScript 规范。
函数
示例
1 | function square(number) { |
参数本质上是按值传递给函数的——因此,即使函数体的代码为传递给函数的参数赋了新值,这个改变也不会反映到全局或调用该函数的代码中。
但是数组和对象传入到函数中被修改了,因为这部分是引用类型,只有基础类型(string,string,bigint,bigint,undefined,symbol,null)传入才不会反映到全局。
匿名函数
1 | const square = function (number) { |
1 | const factorial = function fac(n) { |
函数提升
函数定义可以放在任意位置,因为 js 解释器会自动将函数定义放在当前作用域顶部。但是,函数提升仅适用于函数声明,而不适用于函数表达式。以下代码无法运行:
1 | console.log(square(5)); // ReferenceError: Cannot access 'square' before initialization |
嵌套函数 / 闭包
闭包是可以拥有独立变量以及绑定了这些变量的环境(“封闭”了表达式)的表达式(通常是函数)。
闭包形成的三个条件:
- 存在嵌套函数(函数内部定义了另一个函数)
- 内部函数引用了外部函数的变量
- 内部函数被返回或传递到外部作用域执行
1 | function outer() { |
outer() 执行完后,按理说 count 应该被垃圾回收。但因为 inner 函数引用了 count,引擎会保留这个变量,形成闭包。
用法:
1 | function createCounter() { |
1 | function createCounter() { |
arguments 对象
示例
1 | function myConcat(separator) { |
默认参数
1 | function multiply(a, b = 1) { |
剩余参数
1 | function multiply(multiplier, ...theArgs) { |
箭头函数
箭头函数总是匿名函数,没有单独的 this
1 | const a = ["Hydrogen", "Helium", "Lithium", "Beryllium"]; |
