Web前端入门第 58 问:JavaScript 运算符 == 和 === 有什么区别?
运算符
JavaScript 运算符是真的多,尤其是 ES6 之后还在不停的加运算符,其他编程语言看 JS 就像怪物一样,各种骚操作不断~~
运算符分类
1、算术运算符
算术运算符的作用就是用来基础计算,跟小学课本一样,包含:加 +
,减 -
,乘 *
,除 /
,取余(也叫做取模) %
,指数 **
,自增 ++
,自减 --
。
只是需注意:乘号不再是 x
,除号也不再是 ÷
!
与我们学过的运算法则一样,乘法与除法优先级比加减法高,如果要改变优先级,需要使用括号 ()
,只是一个算式中有多个括号还是使用小括号,不用中括号
而已。
// 加法
console.log(3 + 5); // 8
console.log(3 + '5'); // '35'(字符串拼接)
// 减法、乘法、除法
console.log(10 - 3); // 7
console.log(2 * 4); // 8
console.log(10 / 2); // 5
// 取余、指数
console.log(10 % 3); // 1(余数)
console.log(2 ** 3); // 8(2的3次方)
// 自增/自减(注意前置与后置)
let a = 5;
console.log(a++); // 5(先返回原值,再自增)
console.log(++a); // 7(先自增,再返回新值)
// 使用括号改变优先级
console.log((2 + 3) * 4); // 5 * 4 = 20
console.log(((2 + 3) - (5 -3)) * 4); // (5 - 2) * 4 = 12
2、比较运算符
一般用于逻辑比较,比如比较两个值是否相等,比较两个数的大小等等。包含:等于 ==
,严格等于(全等于) ===
,不等于 !=
,严格不等于(不全等) !==
,大于 >
,小于 <
,大于等于 >=
,小于等于 <=
需特别注意:==
与 !=
会存在类型转换,所以 JS 建议使用 ===
与 !==
。
// 松散比较(类型转换)
console.log(5 == '5'); // true(值相等)
console.log(0 == false); // true(0和false在松散比较中等价)
console.log(5 != '5'); // false(值相等)
// 严格比较(值和类型)
console.log(5 === '5'); // false(类型不同)
console.log(0 === false); // false(类型不同)
console.log(5 !== '5'); // true(类型不同)
// 其他比较
console.log(3 > 2); // true
console.log('apple' > 'banana'); // false(按字母顺序比较)
console.log(2 >= 2); // true
console.log(2 <= 2); // true
如果要比较值类型不同,建议显示转换类型再用 ===
比较。比如:
const a = 5;
const b = '5';
if (a + '' === '5') {} // 将 a 转换为字符串再比较
if (b - 0 === 5) {} // 将 b 转换为数字再比较
3、逻辑运算符
用于逻辑判断,包含:逻辑与 &&
,逻辑或 ||
,逻辑非 !
。
需注意他们的短路特性。
// 逻辑与(&&):短路特性
console.log(true && 'Hello'); // 'Hello'(返回最后一个真值)
console.log(false && 'Hello'); // false(遇到假值直接返回)
// 逻辑或(||):短路特性
console.log(0 || 'default'); // 'default'(返回第一个真值)
console.log('A' || 'B'); // 'A'
// 逻辑非(!)
console.log(!true); // false
console.log(!!'非空字符串'); // true(强制转布尔值)
// 应用场景
// 默认值设置
function greet(name) {
name = name || 'Guest'; // 若 name 为假值,返回 'Guest'
console.log(`Hello, ${name}!`);
}
greet(); // 'Hello, Guest!'
// 条件执行函数
true && console.log('执行了!'); // 输出 '执行了!'
false || console.log('执行了!'); // 输出 '执行了!'
4、赋值运算符
用于给变量赋值,包含:赋值(等于) =
,加等于(累加) +=
,减等于(累减) -=
,乘等于(累乘) *=
,除等于(累除) /=
,模等于(累模) %=
,幂等于(累幂) **=
。
let x = 10;
x += 5; // x = x + 5 → 15
x *= 2; // x = 15 * 2 → 30
x **= 2; // x = 30^2 → 900
console.log(x); // 900
5、位运算符
二进制的位运算符,据说是最快的运算符,当然一般编程用不上,如果您用 JS 进行大量的计算操作时,比如:图形图像算法、加密算法等相关操作,这时候就必须需掌握位运算了!包含:按位与 &
,按位或 |
,按位异或 ^
,按位非 ~
,左移 <<
,右移 >>
,无符号右移 >>>
。
这部分运算符涉及到底层的二进制运算,如果有兴趣可以查找相关资料学习。
// 按位与(&)
console.log(5 & 3); // 1(二进制 101 & 011 → 001)
// 按位或(|)
console.log(5 | 3); // 7(101 | 011 → 111)
// 无符号右移(>>>)
console.log(-1 >>> 0); // 4294967295(将负数转为无符号整数)
6、三元运算符
又称为三目运算符(吐槽下:乱七八糟的名字特多),一般用于简化 if else
语句,但不建议过多嵌套,要不然代码阅读起来费劲。
语法:condition ? expr1 : expr2
。
const age = 20;
const canVote = age >= 18 ? 'Yes' : 'No';
console.log(canVote); // 'Yes'
// 等价于
if (age >= 18) {
console.log('Yes');
} else {
console.log('No');
}
// 三元运算符的多次嵌套
const a = age > 80 ? '高龄老人' : (age > 60 ? '老年人' : (age > 40 ? '中年人' : '年轻人'))
可以看看多次嵌套的代码是否是难以阅读,为了项目的可维护性,真心不建议把三元运算符用于多次嵌套。
7、特殊运算符
JS 内置的关键字,包含:typeof
, instanceof
, delete
, void
, in
, new
。
// typeof 返回变量的类型字符串
console.log(typeof 42); // 'number'
console.log(typeof null); // 'object'(历史遗留问题)
// instanceof 检查对象是否是某个构造函数的实例(基于原型链)
class Person {}
const p = new Person();
console.log(p instanceof Person); // true
// delete 删除对象的属性或数组元素(对变量无效)
const obj = { a: 1 };
delete obj.a; // 删除属性
console.log(obj.a); // undefined
// void 执行表达式并返回 undefined
console.log(void (1 + 1)); // undefined
// in 检查对象或其原型链中是否包含指定属性
console.log('toString' in obj); // true(继承自Object.prototype)
// new 创建构造函数实例(调用构造函数,绑定 this)
function Car(brand) {
this.brand = brand;
}
const myCar = new Car('Tesla');
console.log(myCar.brand); // 'Tesla'
/* 等价于以下过程:
1. 创建一个空对象 {}
2. 将空对象的原型指向 Car.prototype
3. 执行 Car 函数,this 指向该空对象
4. 返回新对象 */
8、ES6+ 运算符
ES6 之后新增的一些运算符,骚操作从这里开始。包含:展开运算符 ...
, 可选链 ?.
, 空值合并 ??
// 展开运算符(...)
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5, 6];
console.log(...arr1); // 1 2 3
console.log(arr2); // [1, 2, 3, 4, 5, 6]
// 可选链(?.)
const user = { address: { city: 'Paris' } };
console.log(user?.address?.city); // 'Paris'
console.log(user?.phone?.number); // undefined(不会报错)
// 空值合并(??)
const input = null;
const value = input ?? 'default'; // 'default'(仅针对 null/undefined)
类型转换规则
当操作数类型不同时,JS 会按内部规则尝试进行类型转换:
const obj = { toString: () => '100' };
// 调用 valueOf() → toString(),若结果为原始值则继续比较
console.log(obj > 50); // true('100' → 100 > 50)
// true → 1,false → 0
console.log(true > -1); // true(1 > -1)
console.log(false < 1); // true(0 < 1)
// null → 0
console.log(null > -1); // true(0 > -1)
// undefined → NaN
console.log(undefined > 0); // false(NaN 与任何值比较均为 false)
// 若字符串为合法数字 → 转换为数字,否则 → NaN
console.log('123' > 50); // true(123 > 50)
console.log('abc' > 0); // false('abc' → NaN)
// 对象与非对象比较
const arr = [10];
console.log(arr > 5); // true([10].toString() → '10' → 10 > 5)
// 十六进制字符串
console.log('0x1f' > 30); // true('0x1f' → 31 > 30)
// 空字符串与 0
console.log('' > -1); // true('' → 0 > -1)
console.log(0 == ''); // true(0 == 0)
// 布尔值的陷阱
console.log(true == '1'); // true(1 == 1)
console.log(false == '0'); // true(0 == 0)
console.log([1] > 0); // true([1].toString() → '1' → 1 > 0)
console.log([] > -1); // true([].toString() → '' → 0 > -1)
console.log([] == 0); // true(0 == 0)
console.log([] == false); // true(0 == 0)
常见问题
1、== 和 === 的区别是什么?
答:== 会进行类型转换后比较,=== 严格比较值和类型。
2、逻辑运算符 && 和 || 的返回值是什么?
答:返回第一个决定表达式结果的子表达式值(短路求值)。
3、1 + '1' 和 '1' + 1 的结果是什么?
答:均为 '11'(字符串拼接)。
4、0 == false 和 '' == false 的结果是什么?为什么?
答:均为 true,因 == 会进行隐式转换。
5、typeof null 返回什么?为什么?
答:'object'(历史遗留问题)。
6、可选链 ?. 和空值合并 ?? 的作用是什么?
答:obj?.prop 避免访问 null/undefined,a ?? b 仅在 a 为 null/undefined 时返回 b。
7、以下代码的输出是什么?
console.log(1 < 2 < 3); // true(等价于 (1 < 2) < 3 → true < 3 → 1 < 3 → true)
console.log(3 > 2 > 1); // false(等价于 (3 > 2) > 1 → true > 1 → 1 > 1 → false)
8、console.log(!!' ')
的输出是什么?
答:true(非空字符串转布尔值为 true)。
9、如何用短路求值简化代码?
const value = input || defaultValue;
10、如何安全访问嵌套对象属性?
答:使用可选链 obj?.a?.b ?? 'default'。
写在最后
优先使用 ===
和 !==
避免 JS 的隐式转换带来的不确定性。
隐式转换机制需特别注意,特别是在处理用户输入、API 接口响应数据时,稍不注意就掉坑了!!
如果您有大量计算工作量,那么必须啃书二进制的位运算符,否则使用十进制运算会拖慢程序运行速度。
Web前端入门第 58 问:JavaScript 运算符 == 和 === 有什么区别?的更多相关文章
- web前端入坑第五篇:秒懂Vuejs、Angular、React原理和前端发展历史
秒懂Vuejs.Angular.React原理和前端发展历史 2017-04-07 小北哥哥 前端你别闹 今天来说说 "前端发展历史和框架" 「前端程序发展的历史」 「 不学自知, ...
- Android零基础入门第58节:数值选择器NumberPicker
原文:Android零基础入门第58节:数值选择器NumberPicker 上一期学习了日期选择器DatePicker和时间选择器TimePicker,是不是感觉非常简单,本期继续来学习数值选择器Nu ...
- web前端入坑第二篇:web前端到底怎么学?干货资料! 【转】
http://blog.csdn.net/xllily_11/article/details/52145172 版权声明:本文为博主[小北]原创文章,如要转载请评论回复.个人前端公众号:前端你别闹,J ...
- web前端(13)—— 了解JavaScript,JavaScript的引入方式
从本篇博文开始,将进入web前端方便最关键最重要的部分——javascript,学到后面你就知道它真的太重要了 什么是JavaScript JavaScript一种直译式的脚本语言,是一种动态类型.弱 ...
- WEB前端工程师整理的原生JavaScript经典百例
一.原生JavaScript实现字符串长度截取 二.原生JavaScript获取域名主机 三.原生JavaScript转义html标签 四.原生JavaScript时间日期格式替换 Date.prot ...
- Web前端基础怎么学? JavaScript、html、css知识架构图
以前开发者只要掌握 HTML.CSS.JavaScript 三驾马车就能胜任一份前端的工作了.而现在除了普通的编码以外,还要考虑如何性能优化,如何跨端.跨平台实现功能,尤其是 AI.5G 技术的来临, ...
- web前端学习之HTML CSS/javascript之一
前端编码之路之坎坷,web前端应该一直是个战场吧,各种浏览器的不兼容,各种小细节的修改,要往一个好的产品经理方向走,实在是难,昨天听了一位十年经验的产品经理讲座,最重要的恐怕就是协调资源的能力,而协调 ...
- Web前端开发规范【HTML/JavaScript/CSS】
前言 这是一份旨在增强团队的开发协作,提高代码质量和打造开发基石的编码风格规范,其中包含了 HTML, JavaScript 和 CSS/SCSS 这几个部分.我们知道,当一个团队开始指定并实行编码规 ...
- web前端——实例中学习css,javascript
最近闲暇时候在研究前端的样式和js,以前都是从w3school上看看那些选择器和DOM操作方法很少去实际做demo来研究,做的过程当中才真切感觉到纸上得来终觉浅,看得懂跟能做出东西完全两码事,尤其在定 ...
- 文成小盆友python-num14 - web 前端基础 html ,css, JavaScript
本部分主要内容 html - 基础 css - 基础 一.html 标签 html 文档标签树如下: head 部分 Meta(metadata information) 提供有关页面的元信息,例:页 ...
随机推荐
- 读论文-顺序推荐系统_挑战、进展和前景(Sequential recommender systems_ challenges, progress and prospects)
前言 今天读的论文为一篇于2019年发表的论文,是关于顺序推荐系统(Sequential Recommender Systems,SRSs)的研究,作者对SRSs的挑战.进展和前景进行了系统综述. 要 ...
- 分享一个裁剪图片Chrome 扩展 —— Crop Image
1. 前言 在日常工作和设计过程中,我们常常需要对图片进行裁剪,以适配不同的使用场景.无论是社交媒体头像.网站图片优化,还是艺术设计,精确的图片裁剪都是必不可少的.然而,许多在线工具使用复杂,或者功能 ...
- 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
目录 什么是 Selenium 环境搭建与配置 安装 Selenium 下载浏览器驱动 基础操作 启动浏览器并访问网页 定位网页元素 通过 ID 定位 通过 CSS 选择器定位 通过 XPath 定位 ...
- nuxtjs 自定义服务端错误页面 Server error page
原文链接:https://blog.jijian.link/2020-12-03/nuxtjs-server-error-page/ 当 nuxt 项目在生产环境运行时,如果服务端运行出错,比如 as ...
- css 保留后端 textarea 中的换行与空格字符
原文链接:https://blog.jijian.link/2020-10-22/css-pre/ 如果后台使用 textarea 输入内容,在前段显示需要保留换行符与空白字符,该如何做? 常规方法 ...
- windows goland go exec "gcc": executable file not found in %PATH%
问题 windows 本地缺少 gcc 编译器 解决方案 下载安装使用 MinGW-w64 第一种 https://winlibs.com/#download-release 下载后解压到磁盘中,然后 ...
- 容器引擎-Docker
Docker是一个开源的应用容器引擎,可以轻松的为任何应用创建一个轻量级.可移植的.自给自足的容器.Docker类似于集装箱,各式各样的货物,经过集装箱的标准化进行托管,而集装箱和集装箱之间没有影响. ...
- 利用Windows自带性能计数器分析软件产品的性能瓶颈(转)
利用Windows性能计数器分析软件产品的性能瓶颈转自:http://blog.163.com/jack_test/blog/static/166620663201061594459936/ [摘要] ...
- 【Python】Python使用Tk实现动态爱心效果
[Python]Python使用Tk实现动态爱心效果 深夜种下希望,梦中便能发芽 相对于之前的版本(晚上星月争辉,美梦陪你入睡),解决了看起来很卡.爱心跳动死板和外围光环不怎么灵动的问题,添加了文字功 ...
- 远程连接到轻量应用服务器PG数据库
不建议这样做,但是开发时方便需要.进入正题. PG是不支持远程连接的,需要连接直接该参数. 在其data目录里,有二个配置文件: pg_hba.conf:配置数据库的访问权限 postgresql.c ...