JavaScript基础语法之运算符和控制流
JavaScript基础语法之运算符和控制流
- 一、运算符
- 1.1 算术运算符:数值计算的基石
- 1.1.1 字符串拼接陷阱
- 1.2 比较运算符:条件判断的起点
- 1.2.1 严格比较(`===`)vs 松散比较(`==`)
- 1.2.2 其他比较运算符
- 1.3 逻辑运算符:复杂条件的组合
- 1.3.1 短路逻辑(重要特性)
- 1.3.2 实战:表单验证
- 1.4 赋值运算符:数据存储的桥梁
- 1.4.1 基础赋值(`=`)
- 1.4.2 解构赋值(ES6新增)
- 1.5 三元运算符:简洁的条件赋值
- 二、控制流
- 2.1 条件语句:路径选择的分叉口
- 2.1.1 if-else语句
- 2.1.2 switch语句(等值判断优化)
- 2.1.3 穿透行为(不推荐)
- 2.2 循环语句:重复执行的引擎
- 2.2.1 for循环(最常用)
- 2.2.2 while循环(条件优先)
- 2.2.3 do-while循环(至少执行一次)
- 2.2.4 现代遍历方式(ES6+)
- 2.3 跳转语句:流程控制的调节器
- 2.3.1 break(终止循环/switch)
- 2.3.2 continue(跳过当前迭代)
- 三、运算符优先级与代码可读性
- 3.1 优先级记忆口诀
- 3.1.1 括号提升优先级
- 3.2 代码风格最佳实践
- 四、常见问题解析
- 4.1 运算符相关
- 4.2 控制流相关
一、运算符
1.1 算术运算符:数值计算的基石
运算符 | 说明 | 案例 |
---|---|---|
+ | 加法/字符串拼接 | 1 + 2 → 3,"a" + "b" → “ab” |
- | 减法 | 5 - 3 → 2 |
* | 乘法 | 4 * 3 → 12 |
/ | 除法 | 10 / 2 → 5 |
% | 取模(余数) | 10 % 3 → 1 |
++ | 自增(前置/后置) | let a=1; a++ → 1(先返回再增) |
-- | 自减(前置/后置) | let b=2; --b → 1(先减再返回) |
1.1.1 字符串拼接陷阱
console.log(1 + 2 + "px"); // "3px"(先算术后拼接)
console.log("px" + 1 + 2); // "px12"(先拼接后算术)
1.2 比较运算符:条件判断的起点
1.2.1 严格比较(===
)vs 松散比较(==
)
===
:类型和值都相同才返回true
1 === "1" → false(类型不同) null === undefined → false(类型不同)
==
:自动类型转换后比较值1 == "1" → true(转为数值比较) null == undefined → true(特殊值相等)
1.2.2 其他比较运算符
3 > 2 → true
"apple" < "banana" → true(按Unicode码点比较)
[1,2] == [1,2] → false(引用类型比较地址)
1.3 逻辑运算符:复杂条件的组合
1.3.1 短路逻辑(重要特性)
&&
(逻辑与):左侧为false
时直接返回左侧值,否则返回右侧值false && console.log("不会执行"); // 返回false true && "hello"; // 返回"hello"
||
(逻辑或):左侧为true
时直接返回左侧值,否则返回右侧值true || console.log("不会执行"); // 返回true false || "world"; // 返回"world"
!
(逻辑非):将值转为布尔并取反!0 → true,!"" → true,!{} → false(对象为truthy)
1.3.2 实战:表单验证
const username = "admin";
const password = "123";
if (username && password) {console.log("登录信息完整");
}
1.4 赋值运算符:数据存储的桥梁
1.4.1 基础赋值(=
)
let a = 10;
a += 5; // 等价于a = a + 5 → 15
a *= 2; // 等价于a = a * 2 → 30
1.4.2 解构赋值(ES6新增)
// 数组解构
const [x, y] = [1, 2]; // x=1, y=2// 对象解构
const { name, age } = { name: "张三", age: 25 }; // name="张三", age=25
1.5 三元运算符:简洁的条件赋值
const score = 85;
const result = score >= 60 ? "及格" : "不及格"; // "及格"// 嵌套使用(多条件判断)
const level = score >= 90 ? "A" : score >= 80 ? "B" : "C";
二、控制流
2.1 条件语句:路径选择的分叉口
2.1.1 if-else语句
const age = 18;
if (age >= 18) {console.log("成年人");
} else if (age >= 12) {console.log("青少年");
} else {console.log("儿童");
}
2.1.2 switch语句(等值判断优化)
const day = 3;
switch (day) {case 1:console.log("星期一");break; // 防止穿透case 2:console.log("星期二");break;default:console.log("其他");
}
2.1.3 穿透行为(不推荐)
// 不写break会继续执行下一个case
const num = 2;
switch (num) {case 1:case 2:case 3:console.log("1-3之间"); // 无论num是1/2/3都会执行break;
}
2.2 循环语句:重复执行的引擎
2.2.1 for循环(最常用)
// 普通for循环
for (let i = 0; i < 5; i++) {console.log(i); // 0,1,2,3,4
}// 遍历数组
const fruits = ["苹果", "香蕉", "橙子"];
for (let i = 0; i < fruits.length; i++) {console.log(fruits[i]);
}
2.2.2 while循环(条件优先)
let count = 3;
while (count > 0) {console.log(count); // 3,2,1count--;
}
2.2.3 do-while循环(至少执行一次)
let num = 0;
do {console.log(num); // 0num++;
} while (num < 0);
2.2.4 现代遍历方式(ES6+)
// for-of遍历数组元素
for (const fruit of fruits) {console.log(fruit);
}// for-in遍历对象属性(注意顺序和原型链)
for (const key in { a: 1, b: 2 }) {console.log(key); // "a", "b"
}
2.3 跳转语句:流程控制的调节器
2.3.1 break(终止循环/switch)
// 跳出指定循环(标签语法)
outer:
for (let i = 0; i < 3; i++) {for (let j = 0; j < 3; j++) {if (i === 1 && j === 1) break outer; // 跳出外层循环console.log(i, j);}
}
2.3.2 continue(跳过当前迭代)
// 打印1-5中的奇数
for (let i = 1; i <= 5; i++) {if (i % 2 === 0) continue;console.log(i); // 1,3,5
}
三、运算符优先级与代码可读性
3.1 优先级记忆口诀
- 括号与函数调用:
()
,[]
, 成员访问.
- 一元运算符:
++
,--
,!
- 算术运算符:
*
,/
,%
高于+
,-
- 比较运算符:
>
,<
,>=
,<=
高于==
,===
- 逻辑运算符:
&&
高于||
- 赋值运算符:
=
优先级最低
3.1.1 括号提升优先级
// 正确逻辑:先判断a和b,再与c或d
if ((a && b) || (c && d)) { ... }// 错误写法(依赖优先级,可读性差)
if (a && b || c && d) { ... }
3.2 代码风格最佳实践
- 避免复杂表达式:拆分过长的条件判断
// 不好:一行复杂逻辑 if (user && user.age >= 18 && (user.role === "admin" || user.role === "manager")) { ... }// 好:分步判断 const isAdult = user.age >= 18; const isAdmin = user.role === "admin"; const isManager = user.role === "manager"; if (isAdult && (isAdmin || isManager)) { ... }
- 优先使用
===
:避免类型转换带来的意外结果 - 合理使用标签:复杂循环嵌套时提高break/continue的精准性
四、常见问题解析
4.1 运算符相关
==
的隐式转换陷阱null == undefined → true(合法特殊值) "" == false → true(都转为数值0) // 严格比较更安全:"" === false → false
- 自增运算符的上下文影响
let x = 1; let y = x++; // y=1,x=2(后置自增先返回原值) let z = ++x; // z=3,x=3(前置自增先增值再返回)
4.2 控制流相关
- 循环中的变量作用域
// ES5中var导致的闭包问题 var btnList = document.querySelectorAll("button"); for (var i = 0; i < btnList.length; i++) {btnList[i].onclick = function() {console.log(i); // 点击时输出btnList.length(闭包共享i)}; }// ES6中let解决块级作用域 for (let i = 0; i < btnList.length; i++) {btnList[i].onclick = function() {console.log(i); // 正确输出当前索引}; }
- switch的类型匹配
// 严格匹配类型,以下返回default switch (1) {case "1": // 类型不同,不匹配console.log("字符串1");break;default:console.log("数字1"); // 执行此处 }
总结
核心知识图谱运算符 ├─ 算术(+/-/*/%/++/--) ├─ 比较(===/==/>/<) ├─ 逻辑(&&/||/!) ├─ 赋值(=/-=/+=) └─ 三元(条件表达式)控制流 ├─ 条件(if-else/switch) ├─ 循环(for/while/for-of) └─ 跳转(break/continue)
学习建议
- 刻意练习:通过LeetCode简单题练习条件判断(如判断奇偶数)和循环遍历(如数组求和)
- 调试技巧:使用
console.log
打印中间值,观察运算符执行顺序- 代码审查:检查是否有不必要的类型转换,是否滥用
==
导致的逻辑漏洞
若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ