JavaScript 零基础教程 · 第四章
数组与对象
核心数据结构 —— 以后装数据,全靠这两个。
1这一章学什么
前面几章我们用的都是单个的值:一个名字、一个数字。真实项目里数据总是一堆一堆的:一批节点、一份配置。 这一章学的对象和数组,就是专门用来「装一堆数据」的两个容器。
2概念
① 对象:一堆带名字的数据
对象用大括号 { } 包起来,里面每条数据都有自己的名字(叫属性名), 名字后面跟冒号,冒号后面是值,条目之间用逗号隔开。就像一张登记表:姓名、类型、端口,各有各的栏。
const node = { name: "香港01", type: "vless", port: 443, tls: true };
// 一个节点对象:name 是名字,port 是端口号,tls 是「真」表示开了加密
取值有两种写法,结果一样:
node.name // 点号取属性 → "香港01"
node["port"] // 方括号取属性 → 443,括号里放属性名的文字
- 点号写法最常用,看着最清楚:node.name。
- 方括号写法在属性名存在一个变量里时用,比如 const key = "port"; node[key],名字是「算出来的」就只能用方括号。
- 加新属性:直接赋值就行 —— node.speed = 120,对象里就多了一条 speed。
- 删属性:用 delete —— delete node.tls,tls 这一条就没了。
② 数组:排成一队的列表
数组用方括号 [ ] 包起来,里面的东西按顺序排队,每个位置有一个编号,叫下标。
const list = ["香港", "日本", "美国"];
// 0 号是"香港",1 号是"日本",2 号是"美国"
- list[0] → "香港",取 0 号位置的东西。
- list.length → 3,length 是「一共有几个」。
- list.push("韩国") → 在末尾加一个,数组变成 4 个。
③ 数组的四个必会方法
数组自带一些「加工工具」,叫方法,写成 数组.方法名(...)。 下面四个是最常用的。它们大多要传一个「处理办法」进去,写法是 x => ……:x 代表「当前这一个元素」,箭头后面写拿它做什么。这是固定写法,照着用就行。
-
.filter(fn) —— 筛选。逐个拿元素去问 fn,留下 fn 说「真」(true)的,组成新数组。
list.filter(x => x.includes("港")) // 只留下名字里带"港"的 -
.map(fn) —— 逐个加工。把每个元素按 fn 加工一遍,结果组成一个新数组,长度不变。
[1, 2, 3].map(x => x * 2) // → [2, 4, 6],每个都乘 2 -
.find(fn) —— 找第一个符合的。找到就返回那一个元素;一个都没有,返回
undefined(意思是「没有这个东西」)。
list.find(x => x === "日本") // → "日本" list.find(x => x === "英国") // → undefined,没找到 -
.join(s) —— 拼成字符串。用 s 当「胶水」,把数组粘成一句话。
["a", "b"].join("-") // → "a-b"它和 split 是一对反操作:split 是把字符串拆成数组,join 是把数组拼回字符串。
另外两个顺手记下:
- .includes(x) —— 问「数组里有没有 x」,回答 true 或 false。比如 list.includes("日本") 是 true。
- .sort() —— 排序。但要注意:默认是按文字排的,排数字会排错;排数字必须传一个比较办法:[3, 1, 2].sort((a, b) => a - b) → [1, 2, 3]。
④ 解构与展开:拆开和摊开
解构是把对象或数组「拆」成一个个变量,一次写好,不用一行一行取:
const { name, port } = node;
// 把 node 的 name、port 拆出来,变成两个变量
// 效果等于 const name = node.name; const port = node.port;
const [first, second] = list;
// 数组按位置拆:first 是 0 号,second 是 1 号
展开是三个点 ...,意思是「把里面的东西摊开倒出来」, 最常见的用法是复制一份再改一点,原件不动:
const merged = { ...node, port: 8443 };
// 先把 node 整个摊开复制,再把 port 改成 8443
// node 本身一点没变,还是 443
const all = [...list, "新加坡"];
// 把 list 摊开,再在末尾接一个"新加坡",拼成新数组
3动手试
下面的代码框可以直接改,点「运行」就能在页面里真正执行,看看输出是什么。故意改错也没关系,出错会用中文告诉你错在哪类。
试一试 1:对象的两种取值
看点号和方括号取出来的值,再看看加了新属性之后对象长什么样。
试一试 2:数组的下标和长度
看 list[0] 是什么、length 是几,再看 push 之后的变化。
试一试 3:filter、map、join 三个方法
筛选留下一部分、加工换个样子、拼接成一句话。
试一试 4:解构拆对象
一行把 name 和 port 从对象里拆成变量。
4练一练
五道题,点一个选项立刻判对错。选错了会告诉你错在哪,再选一次就行。
已答对 0 / 55适用案例
这一章的东西不是摆设,你自己的项目里天天在用:
1tg-bot 里的节点列表
机器人手里的一批节点,就是一个数组,每个元素是一个节点对象。 想只看香港的节点,就是对数组用 filter 筛一遍;想把每个节点拼成一行展示文字,就是用 map 逐个加工。
const hk = nodes.filter(n => n.name.includes("香港"));
// nodes 是节点数组,n 代表当前这一个节点
// 筛出名字带"香港"的,剩下的再逐个加工成要发的文字
2KV 里存的订阅配置
Cloudflare KV 里存的订阅配置,本质是一份 JSON 对象:带名字的字段一排排躺在里面。 程序读出来之后,取某个字段就是这一章的点号写法,比如取配置里的名字、取更新间隔。
const config = { name: "我的订阅", updateHour: 3 };
console.log(config.name); // → "我的订阅"
console.log(config.updateHour); // → 3
3订阅转换:换一种格式
订阅转换做的事,就是把一批节点对象逐个改成另一种格式的文字:输入是对象数组,输出是新数组。 这正是 map 的活儿——个数不变,每个都被加工一遍。
const lines = nodes.map(n => n.name + ":" + n.port);
// 每个节点对象 → 一行 "名字:端口" 的文字
// 再用 lines.join("\n") 就能拼成一整份订阅内容
本章小结
一句话记住:对象装带名字的数据,数组装排成队的数据; filter 筛、map 加工、find 找一个、join 拼起来;解构是拆、展开是摊开复制。