携程前端训练营JavaScript/ES6
JavaScript (简称 JS) 是前端开发“三件套”中至关重要的一环,三者各司其职,共同构建了现代 Web 的基石:
- HTML (结构):定义网页的骨架和内容。
- CSS (表现):负责网页的美化和布局。
- JavaScript (行为):赋予网页灵魂,负责用户交互、动态渲染及逻辑处理。
正如 Jeff Atwood 提出的著名的 Atwood 定律 所言:“Any application that can be written in JavaScript, will eventually be written in JavaScript.”
如今的 JS 生态早已超越了浏览器的边界,它的触角延伸到了软件开发的各个领域:
- Web 前端:传统的网页开发核心。
- 移动端:借助 React Native、Weex、Uniapp 等框架实现跨平台 App 开发。
- 桌面端:利用 Electron 开发跨操作系统的桌面应用(如 VS Code, Slack)。
- 服务端:Node.js 让 JS 能够编写高性能的后端服务。
- 机器学习:TensorFlow.js 等库让浏览器也能进行 AI 模型训练与推理。
var, let 与 const
在 ES6 之前,var 是声明变量的唯一方式。然而,随着应用规模的扩大,var 的设计缺陷逐渐暴露,导致了许多难以排查的 Bug。ES6 引入了 let 和 const,从语法层面规范了变量的生命周期。
var 的经典问题与隐患
var 的作用域只有“全局”和“函数”两级,缺乏“块级作用域”的概念。此外,它还存在变量提升 (Hoisting) 和重复声明静默覆盖的问题。
最经典的莫过于“循环闭包陷阱”,以及对全局对象 (window) 的污染:
实操示例:循环中的陷阱与全局污染
1 | // [隐患] var 的陷阱 |
最佳实践原则
在现代 JavaScript 开发中,建议遵循以下优先级:
- const (优先使用):用于声明常量或引用地址不变的对象。这能明确表达“该变量不应被重新赋值”的意图,增加代码可读性与安全性。
- let (次之):仅在确实需要修改变量值(如计数器、循环变量)时使用。
- var (避免使用):除非维护遗留的老旧项目,否则在现代化开发中应完全废弃。
JavaScript 数据类型与类型转换
JavaScript 是一门弱类型(动态)语言,变量没有静态签名束缚,这虽然带来了灵活性,但也意味着类型检查被推迟到了运行时,并且伴随着大量的隐式类型转换。
基本数据类型
JS 包含 7 种基本数据类型,它们的特点是值不可变 (immutable) 且保存在栈内存中:
- undefined: 变量声明但未赋值、访问对象不存在的属性、函数无 return 值时的默认结果。
- null: 表示“空对象引用”或“无值”。
- 注意:
typeof null返回'object'是 JS 早期的一个历史遗留 Bug,实际上它属于基本类型。
- 注意:
- boolean: 逻辑上的
true/false。 - number: 只有一种数字类型,基于 IEEE-754 双精度浮点数标准。
- 这意味着 JS 中没有 int, float 之分,所有数字本质上都是浮点数。
- string: UTF-16 编码的文本序列。
- bigint: 用于处理超出
Number安全范围的任意精度整数(以n结尾,如123n)。 - symbol: ES6 引入的唯一、不可变的标识符,常用于定义对象的私有属性键。
实操示例:类型检测与精度陷阱
1 | // undefined vs null |
类型转换技巧
掌握显式转换可以避免隐式转换带来的 Bug:
转字符串:
String(x):最安全,适用于 null/undefined。x.toString():无法处理 null/undefined。- 模板字符串
${x}:推荐写法,直观且兼容性好。
转数字:
Number(x):整体转换。parseInt(x)/parseFloat(x):从左向右解析,直到遇到非数字字符。
转布尔: Boolean(x)。
- Falsy 值 (假值):在条件判断中会被视为 false 的值,包括
0,""(空字符串),null,undefined,NaN,false。 - 注意:空数组
[]和空对象{}在 JS 中属于对象,转换结果为true。
运算符与逻辑控制
相等运算符
== (宽松相等):会先进行隐式类型转换再比较。
- 例如:
1 == '1'(true),null == undefined(true)。这种特性容易导致难以预测的代码行为。
=== (严格相等):只有当值和类型完全一致时才返回 true。
- 例如:
1 === '1'(false),null === undefined(false)。
为了代码的健壮性,永远优先使用
===,除非极其明确需要利用隐式转换的特性。
逻辑与短路运算
逻辑运算符不仅用于布尔判断,还常用于值的提取和保护,利用的是短路 (Short-circuit) 机制:
&&(与):遇到假值立即停止并返回该假值;若全为真,返回最后一个值。||(或):遇到真值立即停止并返回该真值;若全为假,返回最后一个值。
1 | // 短路运算实操场景 |
数组与对象的高级操作
数组 (Array)
数组在 JS 中是一组按顺序排列的值,本质上属于对象。ES6 提供了极丰富的内置方法来处理数据集合。
实操示例:数组迭代、筛选与变换
1 | const methods = ['PayMe', 'LinePay', 'Transfer', null, {a:1}]; |
对象 (Object)
对象用于描述实体。ES6 极大地简化了对象的创建语法。
1 | const name = 'Vintor'; |
函数、This 与 闭包
函数与 This 绑定机制
this 指针是 JavaScript 中最复杂也最强大的机制之一。核心原则是:this 的指向取决于函数的调用方式,而不是定义位置。
- 普通函数:
this动态指向调用者。如果直接调用,指向全局对象(严格模式下为 undefined)。 - 箭头函数: 没有自己的
this,它会捕获定义时外层上下文的this。
实操示例:显式绑定 (call, apply, bind)
JS 提供了三种手动修改 this 指向的方法:
1 | function sayHello(msg, punctuation) { |
闭包 (Closure)
闭包是指有权访问另一个函数作用域中变量的函数。可以把它理解为一个“背包”,函数被返回时,背着它定义时的作用域一起走了。
应用场景:数据隐藏(私有变量)、函数工厂、状态保持(如防抖节流)。
实操示例:数据隐藏与计数器
1 | function createCounter() { |
异步编程:从 Callback 到 Promise
JavaScript 是单线程语言,异步编程是其核心。传统 AJAX 使用 XMLHttpRequest 配合回调函数,容易陷入多层嵌套的“回调地狱 (Callback Hell)”。
ES6 引入 Promise 代表未来的值,ES2017 引入 async/await,让异步代码写起来像同步代码。
实操示例:Fetch API 与 Promise 链
1 | // Fetch 是现代浏览器替代 XMLHttpRequest 的标准 API |
ES6 核心特性详解
ES6 是一次彻底的现代化升级,解决了 ES5 的诸多痛点,为大型应用开发提供了语法支撑。
解构赋值 (Destructuring)
从数组或对象中提取值,代码更简洁,不再需要反复使用点语法。
1 | // 数组解构:按位置提取 |
展开运算符 (Spread Operator)
使用 ... 将可迭代对象“打散”。
1 | // 数组合并与克隆 |
箭头函数 (Arrow Function)
除了语法简洁,箭头函数最重要的特性是词法作用域的 this,即它自动捕获外层的 this,非常适合用作回调函数。
1 | // 传统写法 |
类 (Class) 与 继承
ES6 的 class 使得面向对象编程更加直观,但本质上它仍是构造函数 + 原型链的语法糖。
实操示例:类的定义、继承与静态方法
1 | class Person { |
Getter / Setter
利用存取器属性(Accessor Properties),我们可以对对象属性的读取和赋值行为进行拦截和控制,实现更加健壮的数据封装。
1 | class Circle { |

