JavaScript语法
JavaScript 语法 = 类型系统 + 变量声明 + 函数 + 原型与模块,这四块是后续一切机制(作用域与闭包、异步编程)的底座。本文只讲语法层,运行环境相关见 Node.js开发。本文是 JavaScript 的语法基础分册。
语言定位
JavaScript 1995 年由 Brendan Eich 在网景公司十天设计完成,最初只是浏览器脚本语言。ES6(2015)之后语言能力大幅增强:块级作用域、箭头函数、class、模块化,如今已是前后端通用的主流语言。
提示
JavaScript 与 Java 除了名字相似没有血缘关系——设计初衷只是"看起来像 Java",语法上更接近 C 与 Self(原型继承)。
数据类型
7 种原始类型 + 对象:
| 类型 | 说明 | 示例 |
|---|---|---|
number | 数字(含 NaN/Infinity) | 42、3.14 |
string | 字符串 | 'hi'、`模板` |
boolean | 布尔 | true / false |
null | 空值(typeof 返回 object,历史遗留) | null |
undefined | 未定义 | let a |
symbol | 唯一值 | Symbol('id') |
bigint | 大整数 | 10n |
object | 对象/数组/函数等引用类型 | {}、[] |
判断类型用 typeof;区分引用类型用 Array.isArray() / instanceof。
隐式类型转换与 /=
JavaScript 的类型转换规则是"尽量转成能比较的形态",这是 == 与 === 差异的根源。=== 先比较类型,类型不同直接 false;== 会做隐式转换后再比较,规则复杂且容易踩坑:
1 == '1' // true:数字与字符串比较,字符串转数字
null == undefined // true:两者相等是特例
0 == false // true:布尔转数字
'' == false // true:都转成 0
[] == false // true:空数组转 '' → 0
[1] == 1 // true:数组转字符串 '1',再转数字 1
NaN == NaN // false:NaN 不与任何值相等,包括自身一律用 ===
业务代码统一使用 === / !==,禁用 ==——隐式转换的规则靠记忆不可靠,== 带来的隐蔽 bug(如 0 == '' 意外为 true)排查成本远高于打两个等号的成本。判断空值用 x == null(同时匹配 null 与 undefined)是少数可接受的例外。
显式转换则是可控的:String(x) / Number(x) / Boolean(x) 或 +x、x + ''。字符串拼接时 + 会优先转字符串(1 + '2' === '12'),这与其他语言的规则不同。
变量声明
| 关键字 | 作用域 | 提升 | 可重赋值 |
|---|---|---|---|
var | 函数级 | 提升为 undefined | 是 |
let | 块级 | 暂时性死区 | 是 |
const | 块级 | 暂时性死区 | 否(对象属性可改) |
let count = 0
const max = 10 // 不可重新赋值
var old = 1 // 旧代码常见,新代码避免优先 const,需要重赋值才用 let,var 只在兼容旧代码时出现。提升与暂时性死区的细节见 作用域与闭包。
函数
三种写法等价:
function add(a, b) { return a + b } // 函数声明(有提升)
const add = function(a, b) { return a + b } // 函数表达式
const add = (a, b) => a + b // 箭头函数- 默认参数:
(a, b = 1),未传参时用默认值 - rest 参数:
(...args)收集剩余参数为数组 - 展开:
Math.max(...arr)把数组展开为参数 - 箭头函数不绑定
this,详见 作用域与闭包
数组与对象
const arr = [1, 2, 3]
arr.push(4) // 尾部添加
arr.map(x => x * 2) // 映射出新数组
arr.filter(x => x > 1) // 过滤
arr.reduce((s, x) => s + x, 0) // 归约求和
const obj = { name: 'js', year: 1995 }
obj.type = 'dynamic' // 动态添加属性
Object.keys(obj) // ['name', 'year', 'type']map/filter/reduce 是函数式三件套;对象解构 const { name } = obj 与数组解构 const [a, b] = arr 是 ES6 高频语法。
原型链与 class
对象通过原型链继承:访问属性时沿 __proto__ 向上查找,直到 Object.prototype。class 是 ES6 对原型继承的语法糖:
class Animal {
constructor(name) { this.name = name }
speak() { return `${this.name} 叫了` }
}
class Dog extends Animal {
speak() { return super.speak() + ' 汪汪' }
}extends 设置原型链,super 调用父类构造与方法。真正的原型机制比 class 更灵活,但日常开发 class 已足够。
模块化
两套体系并存:
| 体系 | 关键字 | 运行环境 |
|---|---|---|
| CommonJS | require / module.exports | Node.js |
| ES Module | import / export | 浏览器 + Node.js(现代) |
// CommonJS(Node.js 传统写法)
const fs = require('fs')
module.exports = { read: fs.readFileSync }
// ES Module(现代写法)
import fs from 'fs'
export const read = fs.readFileSyncNode.js 侧现代项目已逐步转向 ES Module,但生态里 CommonJS 存量巨大,两套都要能读。依赖管理细节见 npm包管理。
类型决定数据规则、作用域决定可见性(作用域与闭包)、事件循环决定时序(Node.js开发)——机制的全貌见 JavaScript 的领域地图。