一、基本语法规则
1. 大小写敏感
JavaScript 区分大小写:
let myVar = 1;
let MyVar = 2; // 完全不同的变量
❗ 错误示例:console.log 写成 Console.Log 将报错。
2. 分号(Semicolon)
- 推荐始终添加分号,避免 ASI(自动分号插入)带来的潜在问题。
// ✅ 推荐
let a = 1;
console.log(a);
// ❌ 不推荐(可能出错)
let b = 1
[1, 2, 3].forEach(console.log) // 解析为 let b = 1[1,2,3]... → 报错!
3. 注释方式
// 单行注释
/*
* 多行注释
* 可跨行
*/
4. 标识符命名规则
- 只能包含:字母、数字、
$、_ - 不能以数字开头
- 不能使用保留关键字(如
if,for,class,function等) - 推荐使用 驼峰命名法(camelCase)
✅ 合法命名:
userName, $input, _privateVar, fetchDataById
❌ 非法命名:
123name, my-name, function, class
二、变量声明规则
| 关键字 | 作用域 | 是否可重新赋值 | 是否存在提升 | 初始值 |
|---|---|---|---|---|
var | 函数作用域 | 是 | 是 | undefined |
let | 块级作用域({}) | 是 | 是(但不初始化) | 暂时性死区(TDZ) |
const | 块级作用域 | 否(仅一次赋值) | 是(但不初始化) | 必须初始化 |
⚠️ 注意:const 声明的对象/数组内容仍可修改:
const arr = [1, 2];
arr.push(3); // ✅ 允许
arr = []; // ❌ 报错:Assignment to constant variable.
三、数据类型与类型判断
7 种原始类型 + Object
typeof "hello" → "string"
typeof 42 → "number"
typeof true → "boolean"
typeof undefined → "undefined"
typeof null → "object" // ❗历史 bug
typeof Symbol() → "symbol"
typeof BigInt(10) → "bigint"
typeof {} → "object"
typeof [] → "object"
typeof function(){}→ "function"
类型判断建议
| 场景 | 推荐方法 |
|---|---|
| 判断原始类型 | typeof |
| 判断数组 | Array.isArray(arr) |
| 判断 null | value === null |
| 判断对象是否为空 | Object.keys(obj).length === 0 |
| 判断 NaN | Number.isNaN(value) |
❗不要用 typeof 判断 null 或数组!
四、运算符与比较规则
1. 相等比较
| 运算符 | 名称 | 是否类型转换 | 示例 |
|---|---|---|---|
== | 宽松相等 | 是 | 5 == "5" → true |
=== | 严格相等 | 否 | 5 === "5" → false |
✅ 建议:始终使用 === 和 !==,避免类型隐式转换导致的错误。
2. 布尔转换(Falsy 值)
以下值在布尔上下文中为 false:
false, 0, -0, 0n, "", null, undefined, NaN
其余均为 truthy。
五、函数与作用域
1. 函数定义方式
// 函数声明(存在提升)
function sayHello() { ... }
// 函数表达式
const sayHi = function() { ... };
// 箭头函数(无 this,无 arguments)
const greet = (name) => `Hello, ${name}`;
2. this 指向差异
| 函数类型 | this 指向 |
|---|---|
| 普通函数 | 调用时决定(动态绑定) |
| 箭头函数 | 定义时外层作用域中的 this(词法绑定) |
const obj = {
name: "Alice",
normal: function() { console.log(this.name); },
arrow: () => { console.log(this.name); } // this 指向外层(通常是 window/global)
};
obj.normal(); // "Alice"
obj.arrow(); // undefined(在浏览器中)
六、异步编程规则
1. Promise 使用
fetch('/api/data')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
2. async/await(推荐)
async function getData() {
try {
const res = await fetch('/api/data');
const data = await res.json();
console.log(data);
} catch (err) {
console.error('请求失败:', err);
}
}
✅ 优势:代码更清晰,易于调试和处理异常。
七、常见陷阱与注意事项(⚠️ 必看)
| 陷阱 | 描述 | 解决方案 |
|---|---|---|
NaN !== NaN | NaN 与自身不相等 | 使用 Number.isNaN(value) |
typeof null === "object" | 历史 bug | 用 value === null 判断 |
| 浮点数精度问题 | 0.1 + 0.2 !== 0.3 | 使用 toFixed() 或数学库(如 decimal.js) |
| 变量提升(Hoisting) | var 提升但未初始化为 undefined | 使用 let/const,避免提前使用 |
| 暂时性死区(TDZ) | let/const 在声明前访问会报错 | 确保先声明后使用 |
| 数组是对象 | typeof [] === "object" | 使用 Array.isArray(arr) 判断数组 |
| 对象引用问题 | 多个变量指向同一对象 | 使用深拷贝(如 JSON.parse(JSON.stringify(obj)) 或 Lodash) |
| 闭包中的循环变量 | var 在循环中共享变量 | 使用 let 替代 var,或 IIFE 包裹 |
this 丢失 | 回调函数中 this 指向改变 | 使用箭头函数或 .bind(this) |
八、最佳实践建议
✅ 推荐做法:
- 使用
const/let替代var - 使用模板字符串替代拼接:
`Hello, ${name}`
- 使用严格相等:
===和!== - 使用
Array.isArray()判断数组 - 异步操作优先使用
async/await - 使用 ESLint + Prettier 统一代码风格
- 避免全局变量污染,使用模块化开发(ES Module / CommonJS)
❌ 避免做法:
- 使用
with、eval()(安全风险) - 修改原型链(如
Array.prototype.xxx) - 在循环中定义函数(性能差)
- 忽略
catch中的错误处理
九、附录:常用工具方法速查
| 功能 | 方法 |
|---|---|
| 判断数组 | Array.isArray(arr) |
| 深拷贝对象 | JSON.parse(JSON.stringify(obj))(简单情况) |
| 延迟执行 | setTimeout(fn, delay) |
| 类型安全判断 NaN | Number.isNaN(value) |
| 字符串转数字 | Number(str) 或 parseInt(str, 10) |
| 防抖函数 | 自定义或使用 Lodash 的 _.debounce |
| 节流函数 | 自定义或使用 Lodash 的 _.throttle |
十、结语
JavaScript 是一门灵活但容易“踩坑”的语言。掌握其基本规则并了解常见陷阱,是写出健壮、可维护代码的关键。
📌 记住一句话:
“The best way to avoid bugs is to understand how they happen.”
📄 文档用途建议:
- 新人入职培训材料
- 团队编码规范参考
- JS 面试复习提纲
- 个人知识总结归档
如需导出为 PDF / Markdown 文件,可复制此内容保存为 .md 文件,或使用工具转换为 PDF。
需要我为你生成一个可下载的 PDF 版本吗?欢迎继续提问!