大一全栈生:JS原理深挖与AI应用实战全记录
不少前端学习者一上来就扑向 React 和 Vue,但真正能走远的,往往是那些先把底层语言吃透的人。JavaScript 并非天生完美的语言——1995 年 Brendan Eich 仅用 10 天创造的“浏览器副产品”,携带着若干与生俱来的“瑕疵”。不理解这些底层机制,后期写业务代码就像在陷阱区狂奔,防不胜防。
这篇文章围绕 var / let / const 展开,但这绝不仅仅是三个关键字的区别。它牵扯出来的,是整个 JavaScript 的执行机制链条:
- 作用域链
- 变量提升(Hoisting)
- 暂时性死区(TDZ)
- for + setTimeout 经典面试题
- 栈内存与堆内存
二、var 的问题到底在哪?
2.1 没有块级作用域
var age = 100;
if (age > 12) {
var dog = age * 7; // 块内用 var 声明
console.log(dog); // 700
}
console.log(dog); // 700 —— 块外也能访问!
var 声明的变量,仅在函数体内拥有局部作用域,对 {} 代码块完全无视。这就导致变量会泄漏到外层,污染全局作用域。
这也是为何早期 JS 项目要用立即执行函数(IIFE)来模拟块级作用域——在 let 出现之前,只有函数能真正隔离变量。
2.2 变量提升(Hoisting)—— 最反直觉的坑
console.log(pizza); // undefined —— 不报错!
var pizza = 'Deep Dish';
这段代码不会报错,而是打印 undefined。原因在于 JS 引擎在执行代码前有一个编译阶段:
编译阶段:创建执行上下文 → pizza 被赋值为 undefined
执行阶段:console.log(pizza) → undefined
pizza = 'Deep Dish' → 赋值
你的代码书写顺序 ≠ 实际执行顺序,这种不一致正是许多 bug 的根源。ES6 引入 let 和 const,就是要终结这个问题。
三、let & const 的正确打开方式
3.1 let:支持块级作用域
{
const name = 'DeepSeek';
console.log(name); // 'DeepSeek'
}
console.log(name); // ReferenceError: name is not defined
{} 形成了一个独立的块级作用域,变量在花括号外面直接“消失”了。变量查找遵循冒泡规则:
当前作用域 → 外层作用域 → ... → 全局作用域 → 找不到 → ReferenceError
3.2 const:常量还是“常量引用”?
这是很多初学者踩坑的地方——const 修饰的是引用,不是值:
// 简单数据类型:值不可变
const key = 'abc123';
key = 'ABC123'; // ❌ TypeError: Assignment to constant variable
// 复杂数据类型:引用不变,但内容可以改
const person = {
name: '李玉刚',
age: 18
};
person.age++; // ✅ 没问题!
console.log(person); // { name: '李玉刚', age: 19 }
person = '111'; // ❌ TypeError: Assignment to constant variable
原理:JavaScript 中,简单类型值存在栈内存,复杂类型值存在堆内存,变量存的是堆地址的引用。const 锁定的是栈里的那根“指针”,不让你指向别的东西,但堆里的内容是可变的。
| 类型 | const 行为 |
|---|---|
| number / string / boolean | 值不可改 |
| object / array | 引用不可改,内容可改 |
3.3 let 声明和赋值可以分开,const 不行
let a; // ✅ 先声明,值是 undefined
a = 51; // ✅ 后赋值
const item; // ❌ SyntaxError: Missing initializer in const declaration
这条规则简单但重要:const 声明时必须初始化。
四、一道面试题搞懂 for + setTimeout
这道面试高频题,是理解 var vs let 最直观的场景:
// 版本一:var
for (var i = 0; i < 10; i++) {
setTimeout(function () {
console.log(`This number is ${i}`);
}, 1000);
}
// 输出:10 10 10 10 10 10 10 10 10 10
为什么全是 10?
var不认块级作用域 → for 循环只有一个全局的isetTimeout是异步的,在同步的 for 循环结束后才执行- 此时
i已经变成了 10
// 版本二:let
for (let i = 0; i < 10; i++) {
setTimeout(function () {
console.log(`This number is ${i}`);
}, 1000);
}
// 输出:0 1 2 3 4 5 6 7 8 9
为什么 let 就对了?
let支持块级作用域 → 每次迭代都创建了一个独立的i- 10 个
setTimeout各自闭包捕获的是自己那一轮的i
五、推门入 AI:从 Jupyter Notebook 到第一个大模型应用
5.1 从 ModelScope 和 HuggingFace 说起
学 AI 避不开两个名字:海外的 HuggingFace 和国内的 ModelScope(魔搭)。
HuggingFace 2016 年成立,被称作「AI 界 GitHub」——它不是一个模型,而是一个开源社区。上面汇聚了海量预训练模型和数据集,覆盖 NLP、CV、多模态,同时提供了 Transformers 这类让开发者直接调用的工具库。ModelScope 是阿里出品的国内对标平台,理念相同:让模型可复用、可发布、可协作。
graph LR
subgraph 社区层
HF[HuggingFace]
MS[ModelScope 魔搭]
end
subgraph 能力层
TR[Transformers 库]
DS[数据集服务]
end
subgraph 应用层
APP[你的 AI 应用]
end
HF --> TR --> APP
MS --> DS --> APP
这两个平台教会我们一个关键认知:站在巨人肩膀上,不是一句鸡汤。你不需要从零训练一个模型,社区里已经有成千上万个现成的预训练模型,你的工作是用代码把它们「用起来」——这就是调 API、写 Prompt、做应用层的意义。
5.2 Jupyter Notebook:实验型编程的最佳拍档
NLP 实验、数值运算、算法验证——这些场景有一个共同点:你需要边写边看结果。传统 IDE 的「写完 → 编译 → 运行 → 看输出」循环太慢了。Jupyter Notebook 的设计哲学完全不同:随时编写,随时运行。
# 在 Notebook 里,每个 cell 都是一个独立的实验单元
# 你可以改一行,立刻看输出,不需要重新跑整个文件
# Python 列表切片 —— 优雅到令人发指
L = ['高强', 500, '张', '俊']
L[:3] # ['高强', 500, '张']
L[-2:] # ['张', '俊']
接触过 JS 的数组方法再来看 Python 切片,会觉得 Python 对数据的操作确实简洁。不同语言的思维切换,也是全栈路上的必修课。
5.2 调用 DeepSeek API 生成商品文案
from openai import OpenAI
client = OpenAI(
api_key="sk-xxxxxxxx", # 替换为你的 key
base_url="https://api.deepseek.com/v1"
)
COMPLETION_MODEL = "deepseek-chat"
prompt = """Consideration product : 工厂现货PVC充气青蛙夜市地摊热卖充气玩具发光蛙儿童水上玩具
1. Compose human readable product title used on Amazonin English within 20 words.
2. Write 5 selling points for the products in Amazon.
3. Evaluate a price range for this product in U.S.
Output the result in json format with three propertiescalled title, selling_points and price_range."""
def get_response(prompt):
response = client.chat.completions.create(
model=COMPLETION_MODEL,
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
print(get_response(prompt))
API 返回结果:
{
"title": "Inflatable PVC Light-Up Frog Toy for Pool, Beach, Night Market Fun",
"selling_points": [
"Built-in LED lights make the frog glow brightly at night...",
"Made from durable, non-toxic PVC material...",
"Designed for versatile water fun...",
"Eco-friendly rechargeable or battery-operated design...",
"Eye-catching frog shape with bright colors..."
],
"price_range": "$8.99 – $14.99"
}
5.3 这段代码教会我们的事
- Prompt Engineering 是核心能力:同样的模型,喂不同的 Prompt,输出质量天差地别。想清楚你要什么格式、什么语气、什么场景,比调参数更重要。
- JSON 输出是关键规范:让模型返回结构化数据,这样代码可以自动化处理,而不是拿到一堆自然语言还要手动解析。
- AI 只是工具,你才是决策者:模型生成的文案和定价只能参考,最终还是要结合真实市场数据做决策。
六、我的学习路线总结
技术路线图
graph TB
subgraph 基础层
A1[JS 语法 & 数据类型]
A2[作用域链 & 闭包]
A3[var/let/const 底层]
A4[异步 & Event Loop]
end
subgraph 工程层
B1[Node.js 运行时]
B2[React 组件化]
B3[HTTP & RESTful]
end
subgraph AI 层
C1[Python 数据处理]
C2[LLM API 调用]
C3[Prompt Engineering]
C4[RAG / Agent]
end
A1 --> A2 --> A3 --> A4
A4 --> B1 --> B2 --> B3
C1 --> C2 --> C3 --> C4
B3 --> D[全栈 + AI]
C4 --> D
大一阶段,几个核心感悟值得分享:
| 感悟 | 说明 |
|---|---|
| 先深后广 | 把一个知识点(如 var/let/const)彻底搞懂,比泛泛看 10 个教程有用 |
| 写代码 > 看视频 | 抄一遍代码,加自己的注释,调 BUG,这个过程不可替代 |
| 笔记要有观点 | 不是照搬文档,而是记录“为什么这么设计”“坑在哪里” |
| 全栈不是全会 | 全栈的核心是打通前后端+AI 的链路,而不是每项技术都精通 |
| AI 是杠杆 | 大一会用 AI 工具,相当于进了加速通道,但基础原理仍然是地基 |
七、写在最后
这不是偶然的。
2026 年入门编程,和五年前最大的不同是:AI 不再是选修课,而是必修课。你不需要成为算法研究员,但你必须知道怎么调用大模型、怎么写 prompt、怎么把 AI 能力嵌入到你的应用里。
对于刚上路的大一学生来说,未来还有很长的路要走——从 JS 底层到 Node.js 服务端,从 Python 脚本到真正的 AI 应用落地,中间隔着无数个 Debug 的深夜。
但学编程最有趣的地方就在于:你每搞懂一个底层原理,就好像点亮了技能树上的一盏灯,原本黑暗的地图慢慢变得清晰起来。
```