JavaScript 基本语法
目录
一、JavaScript 简介
二、基础结构
2.1 脚本嵌入方式
2.2 注释
三、变量与数据类型
3.1 变量声明
3.2 数据类型
3.2.1 原始类型(值类型)
3.2.2 引用类型
四、运算符
4.1 算术运算符
4.2 赋值运算符
4.3 比较运算符
4.4 逻辑运算符
4.5 三元运算符
4.6 特殊运算符
五、流程控制
5.1 条件语句
5.1.1 if-else 语句
5.1.2 if-else if-else 语句
5.1.3 switch 语句
5.2 循环语句
5.2.1 for 循环
5.2.2 while 循环
5.2.3 do-while 循环
5.2.4 for...in 循环
5.2.5 for...of 循环(ES6+)
六、函数
6.1 函数声明方式
6.1.1 函数声明
6.1.2 函数表达式
6.1.3 箭头函数(ES6+)
6.2 函数参数
6.3 作用域与闭包
七、对象
7.1 对象创建
7.2 对象操作
7.3 对象遍历
八、数组
8.1 数组创建
8.2 常用数组方法
8.3 数组遍历
九、ES6+ 新特性
9.1 模板字符串
9.2 解构赋值
9.3 展开运算符(...)
9.4 Set 与 Map(ES6+)
十、错误处理
一、JavaScript 简介
JavaScript(简称 JS)是一种轻量级、解释型的编程语言,主要用于为网页添加交互逻辑。它是一种动态类型、弱类型语言,支持面向对象、函数式和命令式编程范式。本文档聚焦于 JavaScript 核心语法,不涉及 DOM(文档对象模型)和 BOM(浏览器对象模型)相关内容。
二、基础结构
2.1 脚本嵌入方式
JavaScript 代码可通过以下方式嵌入到程序中(非浏览器环境下通常直接运行脚本文件):
- 行内脚本:直接在代码执行环境中编写(如 Node.js 终端)。
- 内部脚本:在脚本文件中编写完整代码(扩展名为
.js
)。 - 外部引入:通过
require
(CommonJS)或import
(ES Module)引入其他脚本文件。
2.2 注释
注释用于解释代码,不参与程序执行,分为两种类型:
// 单行注释:注释内容从 // 开始到行尾/* 多行注释:可跨越多行,以 /* 开头,*/ 结尾
*/
三、变量与数据类型
3.1 变量声明
JavaScript 中通过关键字声明变量,ES6 后新增 let
和 const
,替代了传统的 var
:
关键字 | 特点 | 作用域 | 变量提升 |
---|---|---|---|
var | 可重复声明、可重新赋值 | 函数级作用域 | 存在(声明提升到作用域顶部) |
let | 不可重复声明、可重新赋值 | 块级作用域({} 内) | 不存在(暂时性死区) |
const | 不可重复声明、不可重新赋值(常量) | 块级作用域 | 不存在(暂时性死区) |
示例:
var a = 10; // 函数级作用域,可重复声明(不推荐)
let b = 20; // 块级作用域,不可重复声明
const c = 30; // 常量,声明时必须赋值,不可修改
3.2 数据类型
JavaScript 数据类型分为原始类型和引用类型:
3.2.1 原始类型(值类型)
-
String(字符串):文本数据,用单引号
''
、双引号""
或模板字符串 `` ```` 包裹。let str1 = "hello"; let str2 = 'world'; let str3 = `hello ${str2}`; // 模板字符串支持变量嵌入
-
Number(数字):整数、浮点数或特殊值(
Infinity
、-Infinity
、NaN
)。let num1 = 100; // 整数 let num2 = 3.14; // 浮点数 let num3 = Infinity; // 无穷大 let num4 = NaN; // 非数字(typeof NaN 为 'number')
-
Boolean(布尔值):表示真或假,仅
true
和false
两个值。let isTrue = true; let isFalse = false;
-
Null:表示“空值”,主动定义一个空对象指针。
let empty = null; // typeof null 为 'object'(历史遗留问题)
-
Undefined:表示“未定义”,变量声明后未赋值时的默认值。
let undef; // 声明未赋值,值为 undefined
-
Symbol(符号,ES6+):唯一且不可变的值,用于对象属性的唯一标识。
let sym1 = Symbol('id'); let sym2 = Symbol('id'); console.log(sym1 === sym2); // false(即使描述相同,Symbol 也不相等)
-
BigInt(大整数,ES2020+):表示超出 Number 精度范围的整数,后缀加
n
。let bigNum = 9007199254740993n; // 超过 Number 最大安全整数
3.2.2 引用类型
引用类型的值存储在堆内存中,变量仅保存内存地址(引用):
- Object(对象):键值对集合,用于存储复杂数据。
- Array(数组):有序数据集合,元素可任意类型。
- Function(函数):可执行的代码块。
- 其他:如
Date
、RegExp
等内置对象。
四、运算符
4.1 算术运算符
用于数值计算:
let x = 10, y = 3;
console.log(x + y); // 13(加法)
console.log(x - y); // 7(减法)
console.log(x * y); // 30(乘法)
console.log(x / y); // 3.333...(除法)
console.log(x % y); // 1(取余)
console.log(x **y); // 1000(幂运算,等价于 Math.pow(x, y))
4.2 赋值运算符
为变量赋值,支持复合赋值:
let a = 5;
a += 3; // 等价于 a = a + 3 → 8
a *= 2; // 等价于 a = a * 2 → 16
a %= 5; // 等价于 a = a % 5 → 1
4.3 比较运算符
比较两个值,返回布尔值:
let m = 5, n = '5';
console.log(m == n); // true(宽松相等,自动类型转换)
console.log(m === n); // false(严格相等,不转换类型,推荐使用)
console.log(m != n); // false(宽松不等)
console.log(m !== n); // true(严格不等)
console.log(m > n); // false(数值比较)
4.4 逻辑运算符
用于逻辑判断:
let p = true, q = false;
console.log(p && q); // false(逻辑与:全为真才为真)
console.log(p || q); // true(逻辑或:有一个为真则为真)
console.log(!p); // false(逻辑非:取反)
4.5 三元运算符
简化条件判断的简写形式:
let score = 85;
let result = score >= 60 ? '及格' : '不及格'; // 条件 ? 成立时的值 : 不成立时的值
console.log(result); // 及格
4.6 特殊运算符
-
typeof
:返回变量的数据类型(注意typeof null
返回'object'
)。console.log(typeof 123); // 'number' console.log(typeof 'abc'); // 'string' console.log(typeof true); // 'boolean'
-
instanceof
:判断对象是否为某个构造函数的实例。let arr = []; console.log(arr instanceof Array); // true
五、流程控制
5.1 条件语句
根据条件执行不同代码块。
5.1.1 if-else 语句
let age = 18;
if (age >= 18) {console.log('成年');
} else {console.log('未成年');
}
5.1.2 if-else if-else 语句
多条件判断:
let score = 85;
if (score >= 90) {console.log('优秀');
} else if (score >= 60) {console.log('及格');
} else {console.log('不及格');
}
5.1.3 switch 语句
多分支匹配(严格相等 ===
比较):
let day = 3;
switch (day) {case 1:console.log('周一');break; // 跳出 switchcase 2:console.log('周二');break;default: // 所有 case 不匹配时执行console.log('其他');
}
5.2 循环语句
重复执行代码块。
5.2.1 for 循环
适合已知循环次数的场景:
// 语法:for (初始化; 条件; 迭代) { 循环体 }
for (let i = 0; i < 5; i++) {console.log(i); // 输出 0,1,2,3,4
}
5.2.2 while 循环
适合未知循环次数,条件为真时执行:
let count = 0;
while (count < 3) {console.log(count); // 输出 0,1,2count++;
}
5.2.3 do-while 循环
至少执行一次循环体,再判断条件:
let num = 5;
do {console.log(num); // 输出 5num++;
} while (num < 5); // 条件为假,循环结束
5.2.4 for...in 循环
遍历对象的可枚举属性(不推荐遍历数组):
let obj = { name: 'JS', age: 25 };
for (let key in obj) {console.log(key + ': ' + obj[key]); // 输出 name: JS, age: 25
}
5.2.5 for...of 循环(ES6+)
遍历可迭代对象(数组、字符串、Set 等)的元素:
let arr = ['a', 'b', 'c'];
for (let item of arr) {console.log(item); // 输出 a, b, c
}
六、函数
函数是可重用的代码块,用于封装逻辑。
6.1 函数声明方式
6.1.1 函数声明
function sum(a, b) { // a, b 为形参return a + b; // return 返回结果,终止函数执行
}
console.log(sum(2, 3)); // 5(2, 3 为实参)
6.1.2 函数表达式
let multiply = function(a, b) {return a * b;
};
console.log(multiply(2, 3)); // 6
6.1.3 箭头函数(ES6+)
简化函数表达式的写法,无自己的 this
:
let add = (a, b) => a + b; // 单行可省略 {} 和 return
let greet = name => `Hello, ${name}!`; // 单个参数可省略 ()
console.log(add(2, 3)); // 5
console.log(greet('JS')); // Hello, JS!
6.2 函数参数
-
默认参数:为参数设置默认值,实参未传递时使用。
function greet(name = 'Guest') {console.log(`Hello, ${name}!`); } greet(); // Hello, Guest!
-
剩余参数(...):接收多个实参为数组。
function sum(...nums) {return nums.reduce((total, num) => total + num, 0); } console.log(sum(1, 2, 3)); // 6
6.3 作用域与闭包
-
作用域:变量可访问的范围,分为全局作用域和函数作用域(ES6 后新增块级作用域)。
-
闭包:函数嵌套时,内部函数可访问外部函数的变量,即使外部函数已执行完毕。
function outer() {let count = 0;return function inner() { // 闭包函数count++;return count;}; } let counter = outer(); console.log(counter()); // 1 console.log(counter()); // 2(count 被闭包保存)
七、对象
对象是键值对的集合,用于存储复杂数据。
7.1 对象创建
-
字面量方式(推荐):
let person = {name: 'Alice', // 属性:键(字符串或标识符): 值age: 30,sayHello: function() { // 方法:函数属性console.log(`Hello, I'm ${this.name}`); // this 指向当前对象} };
-
构造函数方式:
let car = new Object(); car.brand = 'Toyota'; car.year = 2023;
7.2 对象操作
-
访问属性:通过
.
或[]
访问。console.log(person.name); // Alice console.log(person['age']); // 30
-
修改属性:直接赋值覆盖。
person.age = 31; console.log(person.age); // 31
-
删除属性:使用
delete
关键字。delete person.age; console.log(person.age); // undefined
7.3 对象遍历
通过 for...in
或 Object.keys()
遍历属性:
for (let key in person) {console.log(key + ': ' + person[key]);
}Object.keys(person).forEach(key => {console.log(key + ': ' + person[key]);
});
八、数组
数组是有序的元素集合,元素可任意类型。
8.1 数组创建
let fruits = ['apple', 'banana', 'orange']; // 字面量方式(推荐)
let numbers = new Array(1, 2, 3); // 构造函数方式
8.2 常用数组方法
方法 | 作用 | 示例 |
---|---|---|
push() | 末尾添加元素,返回新长度 | fruits.push('grape') → ['apple', 'banana', 'orange', 'grape'] |
pop() | 删除末尾元素,返回被删元素 | fruits.pop() → 'orange' |
shift() | 删除首元素,返回被删元素 | fruits.shift() → 'apple' |
unshift() | 首部添加元素,返回新长度 | fruits.unshift('lemon') → ['lemon', 'apple', 'banana'] |
slice(start, end) | 截取子数组(不修改原数组) | [1,2,3].slice(1,3) → [2,3] |
splice(start, deleteCount, ...add) | 修改数组(增删元素) | [1,2,3].splice(1,1,4) → [1,4,3] |
map() | 遍历并返回新数组(映射) | [1,2,3].map(x => x*2) → [2,4,6] |
filter() | 筛选符合条件的元素 | [1,2,3].filter(x => x>1) → [2,3] |
forEach() | 遍历数组(无返回值) | [1,2,3].forEach(x => console.log(x)) |
reduce() | 累加计算为单个值 | [1,2,3].reduce((a,b) => a+b, 0) → 6 |
8.3 数组遍历
// for 循环
for (let i = 0; i < fruits.length; i++) {console.log(fruits[i]);
}// for...of 循环
for (let fruit of fruits) {console.log(fruit);
}// forEach 方法
fruits.forEach(fruit => console.log(fruit));
九、ES6+ 新特性
9.1 模板字符串
用 ` `包裹,支持换行和变量嵌入(`
${变量}`):
let name = 'JS';
let info = `Name: ${name}
Version: 1.0`; // 支持换行
console.log(info);
9.2 解构赋值
快速提取数组或对象的元素/属性:
// 数组解构
let [a, b] = [1, 2]; // a=1, b=2
let [c, ...rest] = [3,4,5]; // c=3, rest=[4,5]// 对象解构
let { name, age } = { name: 'Alice', age: 30 }; // name='Alice', age=30
9.3 展开运算符(...)
将数组/对象展开为单个元素/属性:
// 数组展开
let arr1 = [1,2];
let arr2 = [...arr1, 3,4]; // [1,2,3,4]// 对象展开
let obj1 = { a: 1 };
let obj2 = { ...obj1, b: 2 }; // { a:1, b:2 }
9.4 Set 与 Map(ES6+)
-
Set:无重复元素的集合。
let set = new Set([1, 2, 2, 3]); console.log(set.size); // 3(自动去重) set.add(4); // 添加元素 set.delete(1); // 删除元素
-
Map:键值对集合(键可任意类型)。
let map = new Map(); map.set('name', 'JS'); // 设置键值对 map.set(1, 'number'); console.log(map.get('name')); // JS(获取值)
十、错误处理
使用 try-catch-finally
捕获和处理错误:
try {// 可能出错的代码let result = 10 / 0;if (result === Infinity) {throw new Error('除数不能为 0'); // 主动抛出错误}
} catch (error) {// 捕获错误并处理console.log('错误:', error.message); // 错误:除数不能为 0
} finally {// 无论是否出错都会执行console.log('执行结束');
}