JavaScript学习笔记:6.表达式和运算符

JavaScript表达式与运算符详解

JavaScript学习笔记:6.表达式和运算符

上一篇搞定了函数这个“代码复用神器”,这一篇咱们来拆解JS的“底层操作核心”——表达式和运算符。如果说变量是零散的“乐高积木”,函数是预制的“复杂组件”,那表达式就是拼好的“积木模块”,运算符就是连接它们的“卡扣”——没有它们,代码就是一堆孤立的字符,根本跑不起来。

很多新手栽在=====的区别上,被a++++a绕晕,甚至不知道&&还能当“短路开关”用,本质都是没吃透这俩核心概念。今天就用“生活化场景+踩坑实录”的方式,把这些“卡扣”的用法、坑点讲透,让你写代码时又快又稳,还能耍点“优雅技巧”~

一、先理清:表达式和运算符的“爱恨情仇”

先解决最基础的混淆——这俩不是一回事,但天生绑定,缺一不可。

1. 表达式:有“结果”的代码片段

表达式的核心是“能算出一个具体值”,就像“3块积木拼出的小房子”,不管多简单或复杂,最终都有明确产出。

  • 简单表达式:100(值为100)、"前端"(值为“前端”)、user.age(值为user对象的age属性)
  • 复杂表达式:10 + 20(值30)、fn(5)(值为函数返回值)、a && b || c(值为逻辑运算结果)
  • 隐藏表达式:{ name: "张三" }(值是这个对象)、[1,2,3](值是这个数组)

记住:只要一段代码能跟在console.log()里打印出结果,它就是表达式

2. 运算符:表达式的“操作工具”

运算符就是用来“操作数据、拼接表达式”的工具,比如“+”“===”“&&”,就像乐高的“卡扣”“连接件”,没有它们,积木拼不成模块。

JS的运算符家族很庞大,但核心常用的就几类:赋值、比较、算术、逻辑、三元、扩展。咱们重点聊这些“高频选手”,冷门的位运算符简单带过,避免信息过载。

二、赋值运算符:给变量“装内容”的正确姿势

赋值运算符的核心是“把右边的值装进左边的变量”,但不只是=这么简单,还有能偷懒的“复合赋值”和高级的“解构赋值”。

1. 基础赋值:别把“赋值”当“比较”

最容易踩的低级坑:在if条件里写=(赋值) instead of ===(比较),相当于“硬给变量改值”,逻辑直接错乱。

// 反面例子:把赋值当比较,永远返回true
let isLogin = false;
if (isLogin = true) { // 这里是赋值,isLogin变成true,条件永远成立
  console.log("登录成功"); // 错误执行!
}

// 正面例子:用===做比较
if (isLogin === true) {
  console.log("登录成功"); // 正确判断
}

2. 复合赋值:偷懒的“快捷键”

当需要“修改变量后再存回去”时,复合赋值能少写重复代码,比如a = a + 3可以写成a += 3,清爽又高效。
常用复合赋值对照表:

运算符等价写法场景示例
x += yx = x + y数字累加、字符串拼接
x -= yx = x - y数字递减
x *= yx = x * y倍数计算
x /= yx = x / y除法运算
x ??= yx ?? (x = y)空值兜底(ES6+)

坑点提醒:x += y对字符串是拼接,对数字是累加,别混着用:

let str = "奶茶";
str += "加珍珠"; // "奶茶加珍珠"(字符串拼接)
let num = 5;
num += 3; // 8(数字累加)

3. 解构赋值:批量“拆包”的高级操作

这是ES6的“神技”,能从数组或对象里快速提取数据,不用一个个索引/属性访问,代码瞬间简洁。

// 数组解构:提取数组元素
const [a, b, c] = [10, 20, 30];
console.log(a); // 10,b=20,c=30

// 对象解构:提取对象属性
const user = { name: "张三", age: 25 };
const { name, age } = user;
console.log(name); // "张三"

// 实战场景:函数参数解构(超常用)
function printUser({ name, age }) {
  console.log(`${name}今年${age}`);
}
printUser(user); // "张三今年25岁"

避坑指南:解构时如果变量名和属性名不一致,要指定别名,否则会undefined:

const { name: userName } = user; // 别名userName,对应user.name
console.log(userName); // "张三"

三、比较运算符:判断“对不对”的坑王

比较运算符用来判断两个值的关系(相等、大小等),返回truefalse,但==的“自动类型转换”坑了无数人,堪称“JS坑王”。

1. 核心区别:==(模糊比较)vs ===(严格比较)

这是面试必问,也是日常开发最容易出错的点,记住一句话:非特殊场景,一律用===

  • ==:会先自动转换两个值的类型,再比较“转换后的值”
  • ===:不转换类型,直接比较“值+类型”,完全相等才返回true

看看==的离谱转换:

console.log("10" == 10); // true(字符串转数字)
console.log(0 == false); // true(0和false都转成false)
console.log("" == false); // true(空字符串转false)
console.log(null == undefined); // true(特殊规则,互认亲戚)
console.log(NaN == NaN); // false(NaN:我连自己都不认)

===的判断才是“靠谱的”:

console.log("10" === 10); // false(类型不同:字符串vs数字)
console.log(0 === false); // false(类型不同:数字vs布尔)
console.log(null === undefined); // false(类型不同)

2. 其他比较运算符:注意类型一致性

> < >= <=也会触发类型转换,尤其是字符串比较,会按Unicode编码排序,不是按数字大小:

// 坑点:字符串比较
console.log("2" > "10"); // true("2"的Unicode编码比"1"大)
console.log(Number("2") > Number("10")); // false(转数字后正确比较)

// 正确姿势:先统一类型,再比较
const num1 = "15";
const num2 = 20;
console.log(Number(num1) < num2); // true

四、算术运算符:做计算的“小心机”

算术运算符就是加减乘除(+ - * /),但+有双重身份,++/--有前后置区别,还有NaNInfinity这两个“捣蛋鬼”。

1. +的双重身份:加法或拼接

+是唯一能同时处理数字和字符串的运算符,规则很简单:只要有一边是字符串,就变成拼接

console.log(10 + 20); // 30(数字加法)
console.log("10" + 20); // "1020"(字符串拼接)
console.log(10 + "20"); // "1020"(字符串拼接)
console.log(10 + true); // 11(true转成1,数字加法)

实战技巧:用+变量快速转数字(比Number()简洁):

const strNum = "25";
console.log(+strNum); // 25(字符串转数字)
console.log(+"3.14"); // 3.14(字符串转浮点数)
console.log(+true); // 1(布尔转数字)

2. ++/--:先算账还是先给钱?

自增(++)和自减(--)是“变量自增1/减1”的简写,但前后置的返回值完全不同,像“先给钱再算账”和“先算账再给钱”:

  • 后置(a++):先返回a的原值,再让a加1(先给钱,再记账)
  • 前置(++a):先让a加1,再返回新值(先记账,再给钱)

代码实测:

let a = 5;
console.log(a++); // 5(先返回5,a变成6)
console.log(a); // 6

let b = 5;
console.log(++b); // 6(先变成6,再返回6)
console.log(b); // 6

// 坑点:复杂表达式中混用
let c = 1;
let d = c++ + ++c; // 拆解:c++返回1(c变2),++c变3返回3 → 1+3=4
console.log(d); // 4

避坑指南:尽量别在表达式里混用++/--,拆成单独语句更易读:

let c = 1;
c++; // 先自增
let d = c + ++c; // 2 + 3 = 5,逻辑清晰

3. 捣蛋鬼:NaNInfinity

算术运算无法得到有效结果时,就会冒出这俩:

console.log(0 / 0); // NaN(无意义运算)
console.log(10 / 0); // Infinity(正数除以0)
console.log(-10 / 0); // -Infinity(负数除以0)
console.log(NaN + 5); // NaN(NaN和任何数运算都是NaN)

避坑技巧:用Number.isNaN()判断NaN(别用isNaN(),会误判非数字类型):

console.log(Number.isNaN(NaN)); // true(正确)
console.log(Number.isNaN("10")); // false(正确)
console.log(isNaN("10")); // false(还好)
console.log(isNaN("abc")); // true(误判!"abc"是字符串不是NaN)

五、逻辑运算符:不止“与或非”,还能当“开关”

逻辑运算符(&& 与、|| 或、! 非)不仅能做逻辑判断,还能利用“短路特性”简化代码,是JS开发者的“隐藏技巧”。

1. 基础逻辑:真与假的规则

JS中“假值”只有6个:false、0、""、null、undefined、NaN,其他全是“真值”。逻辑运算的核心就是判断这些:

  • &&:两边都为真,才返回真(一假则假)
  • ||:只要有一边为真,就返回真(一真则真)
  • !:取反(真变假,假变真)

2. 核心技巧:短路特性的实用场景

逻辑运算符会“偷懒”——一旦能确定结果,就停止执行后面的代码,这就是“短路”,用好了能少写很多if:

// 1. ||:空值兜底(左边是假值,就用右边的值)
const name = user.name || "匿名用户"; // user.name为空时,用"匿名用户"
// 进阶:用??替代||(只对null/undefined兜底,不误伤0、"")
const age = 0;
console.log(age || 18); // 18(坑:0被当成假值)
console.log(age ?? 18); // 0(正确:只认null/undefined为“空”)

// 2. &&:条件执行(左边是真值,才执行右边的函数)
user && user.login(); // 避免user为null时调用login()报错
// 等价于:if (user) { user.login(); }

// 3. !:快速转布尔值(双重!更稳妥)
const isEmpty = !arr.length; // arr为空时,arr.length是0(假),!0为true
const isTrue = !!arr.length; // 双重!转成标准布尔值,更易读

六、其他常用运算符:实用但容易忽略

除了上面的“高频选手”,还有几个运算符日常用得也多,简单讲清用法和场景:

1. 三元运算符:简化if-else的“快捷键”

唯一需要三个操作数的运算符,语法:条件 ? 真分支 : 假分支,适合“二选一”的简单场景。

// 普通if-else
let statusText;
if (age >= 18) {
  statusText = "成年";
} else {
  statusText = "未成年";
}

// 三元运算符简化
const statusText = age >= 18 ? "成年" : "未成年";

坑点:别嵌套超过两层!否则代码会变成“天书”:

// 反面例子:嵌套三层,难以理解
const level = score > 90 ? "优秀" : score > 70 ? "良好" : "及格";
// 正面例子:复杂判断用if-else
let level;
if (score > 90) level = "优秀";
else if (score > 70) level = "良好";
else level = "及格";

2. 关系运算符:ininstanceof

  • in:判断对象/数组是否有某个属性/索引
    const user = { name: "张三" };
    console.log("name" in user); // true(user有name属性)
    const arr = [1,2,3];
    console.log(0 in arr); // true(arr有索引0)
    
  • instanceof:判断对象是否是某个类型的实例
    const date = new Date();
    console.log(date instanceof Date); // true(date是Date实例)
    console.log([] instanceof Array); // true(数组是Array实例)
    

3. 位运算符:简要带过

位运算符(& | ^ ~ << >>)是操作二进制的,日常开发用得少(除非做底层优化、位掩码),知道它们的存在即可,不用深钻,避免精力浪费。

七、表达式进阶:常见类型大盘点

除了上面的运算符组合,JS还有很多常用表达式,核心都是“有返回值”:

  • 对象初始化表达式:{ name: "张三", age: 25 }(返回对象)
  • 数组初始化表达式:[1,2,3](返回数组)
  • 函数调用表达式:fn(10)(返回函数返回值)
  • 成员访问表达式:obj.namearr[0](返回属性/元素值)
  • 分组表达式:(10 + 20) * 3(改变运算符优先级,返回90)

八、核心避坑总结:3个原则少踩90%的坑

  1. 比较用===:除了null == undefined(判断空值),其他场景一律用严格比较,拒绝自动类型转换的坑。
  2. 不确定优先级就加括号:运算符优先级复杂(比如算术>比较>逻辑>赋值),记不住就用()强制改变顺序,代码更清晰。
  3. 主动控制类型转换:别依赖JS自动转换,用Number()String()Boolean()手动转,或用+变量快速转数字。

九、结尾:表达式和运算符的“本质”

表达式和运算符是JS的“语法基石”,所有复杂逻辑最终都会拆解成“表达式+运算符”的组合。新手和高手的区别,不在于记住多少运算符,而在于能否避开坑点,用简洁的表达式写出高效逻辑。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿蒙Armon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值