【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制


在这里插入图片描述

博客主页: [小ᶻZ࿆]
本文专栏: 前端

文章目录

  • 💯前言
  • 💯案例背景
  • 💯逻辑运算符的优先级与短路求值
    • 运算符优先级的概念
    • 短路求值的概念
  • 💯分析案例代码的执行过程
    • 第一步:执行 `&&` 运算
    • 第二步:执行 `||` 运算
  • 💯运算示例
    • 示例 1:`arguments[0]` 为数组
    • 示例 2:`arguments[0]` 不是数组
    • 示例 3:未传入参数
  • 💯按顺序计算运算符的重要性
  • 💯逻辑运算符的最佳实践
    • 1. 使用逻辑运算符进行安全的参数检查
    • 2. 简化代码逻辑
    • 3. 确保逻辑表达式易于理解
    • 4. 结合空值合并运算符 `??`
  • 💯JavaScript 运算符优先级表
  • 💯 拓展:短路求值的应用场景
    • 1. 条件赋值
    • 2. 条件执行函数
    • 3. 防止空引用
    • 4. 与默认参数结合
  • 💯小结


在这里插入图片描述


💯前言

  • 在编写JavaScript程序时,逻辑运算符&&(逻辑与)和||(逻辑或)是常用的构造工具,能够简洁地实现逻辑判断和条件分支。然而,在处理复杂逻辑时,这些运算符的优先级短路求值特性可能导致混淆和误解。对于开发者而言,深入理解这些运算符的工作机制不仅有助于编写高效、健壮的代码,还可以减少调试中遇到的意外情况。本文旨在深入探讨JavaScript中逻辑运算符的优先级、短路求值,以及它们在编写高效、健壮代码中的应用。
    JavaScript
    在这里插入图片描述

💯案例背景

  • 我有一次在JavaScript中写了一个函数实现类似数组的push功能,在判断arguments的第 0 项是否为数组的这一行采用了逻辑运算符,发现自己对于逻辑运算符理解并不是很清晰确切,所以本文就是通过这段逻辑运算符代码来引入这一讨论。
    在这里插入图片描述

    var arr = [1, 2, 3];
    function push() {var arr = Array.isArray(arguments[0]) && arguments[0] || [];console.log(arr);var argLen = arguments.length;for (var i = 1; i < argLen; i++) {var len = arr.length;arr[len] = arguments[i];}return arr;
    }console.log(push([1, 2, 3], 4, 5, 6, 7));
    

该代码结合使用了 &&|| 两个逻辑运算符,如下所示:

var arr = Array.isArray(arguments[0]) && arguments[0] || [];

尽管这段代码看起来很简洁,但对于缺乏深入理解逻辑运算符优先级的程序员而言,容易产生混淆。特别是当 &&|| 结合在一起时,其执行顺序并不直观。为了全面理解这段代码的逻辑,我们需要首先明确 JavaScript 中运算符的优先级及逻辑运算符的短路求值机制。


💯逻辑运算符的优先级与短路求值

在这里插入图片描述


运算符优先级的概念

在这里插入图片描述

运算符优先级决定了当一个表达式包含多个运算符时,哪些运算符优先执行。在 JavaScript 中,不同运算符具有不同的优先级,这意味着在复杂表达式中,优先级高的运算符将首先被计算。例如,对于表达式 1 + 2 * 3,乘法运算符 * 的优先级高于加法运算符 +,因此乘法首先执行,最终结果为 1 + 6 = 7

在逻辑运算符中,&& 的优先级高于 ||,这意味着在包含这两个运算符的表达式中,&& 会先执行,然后才是 ||


短路求值的概念

在这里插入图片描述

短路求值是一种逻辑运算符的计算特性。在 &&|| 运算的过程中,JavaScript 会依据操作数的值来决定是否继续计算下一个操作数,或者直接返回最终结果。

  • 逻辑与 (&&) 的短路求值 :如果第一个操作数为 false,则整个表达式的结果必然为 false,此时不再计算第二个操作数。例如,false && anything 的结果一定是 false,因为无论 anything 的值是什么,只要第一个操作数为 false,结果就是 false

  • 逻辑或 (||) 的短路求值 :如果第一个操作数为 true,整个表达式的结果就是 true,无需再计算第二个操作数。例如,true || anything 的结果总是 true,因为只要有一个操作数为 true,整个表达式的值就是 true

理解这些特性后,我们便能够更深入地分析复杂的逻辑表达式。


💯分析案例代码的执行过程

在这里插入图片描述

回到我们的示例代码:

var arr = Array.isArray(arguments[0]) && arguments[0] || [];

理解这段代码的执行过程需要按照逻辑运算符的优先级和短路求值规则进行逐步分析。


第一步:执行 && 运算

在这里插入图片描述

首先执行的是 Array.isArray(arguments[0]) && arguments[0],因为 && 的优先级高于 ||

  • Array.isArray(arguments[0]) :这部分代码用于检查 arguments[0] 是否是一个数组。
  • 如果 arguments[0] 是一个数组,则表达式的值为 arguments[0]
  • 如果 arguments[0] 不是数组或未定义,则表达式的值为 false

第二步:执行 || 运算

在这里插入图片描述

接下来执行 && 运算后的结果与 || [] 进行逻辑或运算。

  • 如果 && 部分的结果是一个数组(即 arguments[0] 是数组),则 || 运算符左边的值为 true,直接返回该数组。
  • 如果 && 部分的结果是 false,则 || 会返回右侧的值 [],即空数组。

💯运算示例

在这里插入图片描述

以下示例演示了不同输入下该段代码的执行过程。


示例 1:arguments[0] 为数组

在这里插入图片描述

function test() {var arr = Array.isArray(arguments[0]) && arguments[0] || [];console.log(arr);
}test([1, 2, 3]);  // 输出:[1, 2, 3]
  • 在此示例中,arguments[0][1, 2, 3],即数组。
  • Array.isArray(arguments[0]) 返回 true,因此 && 的右侧 arguments[0] 被返回,即 [1, 2, 3]
  • 因为 && 部分结果为数组,|| 操作符不会再执行右侧的 [],最终结果为 [1, 2, 3]

示例 2:arguments[0] 不是数组

在这里插入图片描述

test("not an array");  // 输出:[]
  • 在此示例中,arguments[0]"not an array",不是数组。
  • Array.isArray(arguments[0]) 返回 false,因此 && 部分的结果为 false
  • || 操作符执行右侧的 [],最终结果为空数组 []

示例 3:未传入参数

在这里插入图片描述

test();  // 输出:[]
  • 在这种情况下,arguments[0]undefined
  • Array.isArray(arguments[0]) 返回 false,因此 && 部分的结果为 false
  • || 操作符执行右侧的 [],最终结果为空数组 []

💯按顺序计算运算符的重要性

  • 在这里插入图片描述
    在逻辑运算中,不能直接将 || [] 看作一个整体,而必须依据运算符优先级和计算顺序来进行判断。&&|| 都是从左到右逐步执行的。
    在这里插入图片描述
  1. 首先计算 && 部分 :由于 && 的优先级更高,必须首先计算 Array.isArray(arguments[0]) && arguments[0]
  2. 然后计算 || 部分 :根据 && 的计算结果,执行 || []。若前者结果为 false,则返回空数组 []

💯逻辑运算符的最佳实践

在这里插入图片描述

了解了这些基础知识之后,我们可以总结出一些逻辑运算符的最佳实践,以便在实际开发中编写出更易于维护和理解的代码。


1. 使用逻辑运算符进行安全的参数检查

在这里插入图片描述

在 JavaScript 中,逻辑运算符常用于进行参数检查,以确保参数的类型和有效性。例如:

function safePush(arr, value) {var array = Array.isArray(arr) && arr || [];array.push(value);return array;
}

safePush 函数利用 &&|| 运算符来确保输入的 arr 是一个数组。如果 arr 不是数组,则使用空数组作为默认值,从而避免传入无效参数导致程序崩溃的风险。


2. 简化代码逻辑

在这里插入图片描述

逻辑运算符可以用于简化代码逻辑,使其更加简洁明了。例如:

var isValid = condition1 && condition2 || defaultValue;

这种写法可以减少 if...else 语句的使用,使代码更为精练。但在使用这种简化写法时,必须理解运算符的优先级和短路求值规则,以避免逻辑错误。


3. 确保逻辑表达式易于理解

在这里插入图片描述

尽管逻辑运算符可以简化代码,但过度使用复合逻辑运算符可能导致代码的可读性降低。因此,推荐对复杂逻辑进行注释说明,或者将逻辑拆分为多个步骤以提高可读性。

例如,将原代码拆分为易于理解的步骤:

var isArray = Array.isArray(arguments[0]);
var arr = isArray ? arguments[0] : [];

这种写法虽然稍显冗长,但逻辑清晰,易于维护。


4. 结合空值合并运算符 ??

在这里插入图片描述

JavaScript 中的新特性空值合并运算符 ?? 可以与逻辑运算符结合使用,进一步提高代码的可读性。例如:

var arr = Array.isArray(arguments[0]) ? arguments[0] : []; 
var finalArr = arr ?? [];

空值合并运算符使得当 arrnullundefined 时,可以自动提供一个默认值,从而使代码更加健壮。


💯JavaScript 运算符优先级表

在这里插入图片描述

为了更好地理解逻辑运算符的优先级,以下列出了 JavaScript 中部分常用运算符的优先级(从高到低):

优先级等级描述示例符号
1成员访问、数组下标、函数调用., [], ()
2一元运算符!, typeof, 等
3乘除、加减*, /, +, -
4比较运算符<, <=, >, >=
5相等运算符==, ===, !=, !==
6逻辑与&&
7逻辑或`
8空值合并??

通过掌握这些运算符的优先级,可以更好地理解复杂表达式的计算顺序,从而编写出更为健壮的代码。


💯 拓展:短路求值的应用场景

在这里插入图片描述


1. 条件赋值

在这里插入图片描述

短路求值常用于条件赋值。例如:

var name = user && user.name || 'Guest';

此段代码用于从 user 对象中获取 name 属性,如果 useruser.namenullundefined,则返回默认值 'Guest'。这种写法简洁明了。


2. 条件执行函数

在这里插入图片描述

短路求值还可以用于根据条件执行函数,例如:

isLoggedIn && showDashboard();

当且仅当 isLoggedIntrue 时,showDashboard() 函数才会被调用。如果 isLoggedInfalse,则不会执行任何操作。这种方式可以有效减少冗余的 if 判断。


3. 防止空引用

在这里插入图片描述

在操作嵌套对象的属性时,短路求值可以防止出现空引用错误。例如:

var street = user && user.address && user.address.street;

这种写法确保了只有在 useruser.address 都存在的情况下,才会访问 user.address.street,否则返回 undefined。这种方式可以有效避免嵌套对象引用时的潜在错误。


4. 与默认参数结合

在这里插入图片描述

短路求值还可以用于结合函数的默认参数使用。例如:

function getConfig(config) {var finalConfig = config || { theme: 'dark', layout: 'grid' };return finalConfig;
}

如果未提供 config 参数,或者参数值为 nullundefined,则使用默认配置对象。这种方式能够确保函数的行为一致性,并且提高代码的可维护性。


💯小结

  • 在这里插入图片描述
    在 JavaScript 中,逻辑运算符 &&|| 的组合使用具有极大的灵活性和表达力。理解它们的优先级与短路求值机制是编写高质量代码的关键。在本文中,我们通过示例代码详细分析了逻辑运算符的执行过程,并讨论了它们的最佳实践。

  • 逻辑与 (&&) 的优先级高于逻辑或 (||) ,因此在复杂表达式中需要特别注意运算符的执行顺序。

  • 短路求值特性 可以帮助简化代码逻辑,但在使用时必须小心,避免逻辑上的误解。

  • 在实际编写代码时,利用逻辑运算符简化参数检查和条件赋值操作时,应始终确保代码的可读性和可维护性。

  • 结合空值合并运算符 以及其他新特性可以进一步提升代码的健壮性和灵活性。


在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/476555.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年11月21日Github流行趋势

项目名称&#xff1a;twenty 项目维护者&#xff1a;charlesBochet, lucasbordeau, Weiko, FelixMalfait, bosiraphael项目介绍&#xff1a;正在构建一个由社区支持的现代化Salesforce替代品。项目star数&#xff1a;21,798项目fork数&#xff1a;2,347 项目名称&#xff1a;p…

【算法】计算程序执行时间(C/C++)

引言 我们在写算法时要考虑到算法的执行效率&#xff0c;有的题目规定了时间限制&#xff0c;我们需要在这个时间之内去解决问题。如果我们需要比对算法的好坏&#xff0c;就需要输出这个程序运行了多长时间。 在C或C中计算程序执行时间&#xff0c;可以使用多种方法&#xf…

【题解】—— LeetCode一周小结46

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 【题解】—— 每日一道题目栏 上接&#xff1a;【题解】—— LeetCode一周小结45 11.切棍子的最小成本 题目链接&#xff1a;1547. 切棍子的最…

PH热榜 | 2024-11-22

DevNow 是一个精简的开源技术博客项目模版&#xff0c;支持 Vercel 一键部署&#xff0c;支持评论、搜索等功能&#xff0c;欢迎大家体验。 在线预览 1. Lovable 标语&#xff1a;全球首位全栈人工智能工程师 介绍&#xff1a;GPT工程师已在140多个国家拥有超过5万用户&#…

时序论文23|ICML24谷歌开源零样本时序大模型TimesFM

论文标题&#xff1a;A DECODER - ONLY FOUNDATION MODEL FOR TIME - SERIES FORECASTING 论文链接&#xff1a;https://arxiv.org/abs/2310.10688 论文链接&#xff1a;https://github.com/google-research/timesfm 前言 谷歌这篇时间序列大模型很早之前就在关注&#xff…

【UCIE协议系列-1】

UCIE协议系列-1 1 UCIE背景1.1 UCIE产生背景1.2 UCIE主要特性 2 UCIE分层协议2.1 Protocol 层2.1.1 Mode VS protocal2.1.2 PCIe 6.02.1.2.1 Raw Mode for PCIe 6.02.1.2.2 Flit Mode: Standard 256B Flit for PCIe 6.0 2.1.3 CXL3.0 256B Flit Mode2.1.3.1 Raw Mode for CXL 2…

智能安全配电装置在高校实验室中的应用

​ 摘要&#xff1a;高校实验室是科研人员进行科学研究和实验的场所&#xff0c;通常会涉及到大量的仪器设备和电气设备。电气设备的使用不当或者维护不周可能会引发火灾事故。本文将以一起实验室电气火灾事故为例&#xff0c;对事故原因、危害程度以及防范措施进行分析和总结…

ESP8266 STA模式TCP客户端 电脑手机网络调试助手

1.STA模式TCP客户端和电脑网络调试助手 2.STA模式TCP客户端和手机网络调试助手

高中-信息技术科目考试-编程题

&#xff08;24上&#xff09;1.为了响应国家低碳的倡议&#xff0c;学校请你设计一个饮料瓶回收系统&#xff0c;根据投的饮料瓶类型和数量进行奖励。具体如下图&#xff1a;假设学生投瓶10个&#xff0c;投瓶类型定义为t&#xff08;0表示塑料瓶&#xff0c;1表示易拉罐&…

如何将文件Copy到Docker镜像中

如何将文件Copy到Docker镜像中 一、使用Dockerfile的COPY指令二、使用Docker CP命令三、使用Docker Volume四、综合应用Docker作为一种轻量级的容器化技术,在软件开发和部署中得到了广泛应用。在使用Docker时,经常需要将本地文件或目录复制到Docker镜像中,以便在容器内部使用…

Figma入门-文字、样式、链接、动作

Figma入门-文字、样式、链接、动作 前言 在之前的工作中&#xff0c;大家的原型图都是使用 Axure 制作的&#xff0c;印象中 Figma 一直是个专业设计软件。 最近&#xff0c;很多产品朋友告诉我&#xff0c;很多原型图都开始用Figma制作了&#xff0c;并且很多组件都是内置的…

shell编程(8) until循环以及函数基本创建调用

声明!!! 学习视频来自B站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章 视频链接&#xff1a;泷羽sec 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 # until循环 脚本代码&#xff1a; i0 until [ ! $i -lt 1…

NVR管理平台EasyNVR多品牌NVR管理工具的流媒体视频融合与汇聚管理方案

随着信息技术的飞速发展&#xff0c;视频监控已经成为现代社会安全管理和业务运营不可或缺的一部分。无论是智慧城市、智能交通、还是大型企业、校园安防&#xff0c;视频监控系统的应用都日益广泛。NVR管理平台EasyNVR&#xff0c;作为功能强大的流媒体服务器软件&#xff0c;…

fastadmin实现站内通知功能

实现效果如下 application/admin/view/common/header.html <style>#notificationMenu {display: none;position: absolute;top: 40px;right: 0;background: #fff;border-radius: 6px;padding: 10px 0;width: 300px;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);z-inde…

大语言模型---LoRA中损失值的计算

文章目录 概要损失计算流程小结 概要 Llama-7B模型的LoRA微调训练中&#xff0c;通过使用Cross-Entropy Loss来度量模型输出的预测分布和真实标签分布之间的距离&#xff0c;来衡量模型的准确性。 本文主要介绍LoRA中损失值的计算流程。 Cross-Entropy Loss作用&#xff1a;是…

【Vue】指令扩充(指令修饰符、样式绑定)

目录 指令修饰符 按键修饰符 事件修饰符 双向绑定指令修饰符 输入框 表单域 下拉框 单选按钮 复选框 样式绑定 分类 绑定class 绑定style tab页切换示例 指令修饰符 作用 借助指令修饰符&#xff0c;可以让指令的功能更强大 分类 按键修饰符&#xff1a;用来…

集成金蝶云星空数据至MySQL的完整案例解析

金蝶云星空数据集成到MySQL的技术案例分享 在企业信息化系统中&#xff0c;数据的高效流动和准确同步是确保业务连续性和决策支持的重要环节。本文将聚焦于一个具体的系统对接集成案例——金蝶云星空的数据集成到MySQL&#xff0c;方案名称为“2金蝶物料同步到商城中间表”。 …

为什么transformer的时间复杂度是N的平方,具体是里面的哪一个计算流程最占用时间

Transformer的时间复杂度为 O(N2)&#xff0c;其中 NN 是输入序列的长度。这一复杂度主要来源于自注意力机制&#xff08;self-attention mechanism&#xff09;的计算过程。 在Transformer模型中&#xff0c;自注意力机制的核心步骤是计算查询&#xff08;Query&#xff09;、…

如何在Linux上安装Canal同步工具

1. 下载安装包 所用到的安装包 canal.admin-1.1.4.tar.gz 链接&#xff1a;https://pan.baidu.com/s/1B1LxZUZsKVaHvoSx6VV3sA 提取码&#xff1a;v7ta canal.deployer-1.1.4.tar.gz 链接&#xff1a;https://pan.baidu.com/s/13RSqPinzgaaYQUyo9D8ZCQ 提取码&#xff1a;…

操作系统大会2024 | 麒麟信安根植openEuler社区,持续技术创新 共拓新应用 探索新机遇

[中国&#xff0c;北京&#xff0c;2024年11月15日] 以“以智能&#xff0c;致世界”为主题的操作系统大会2024在北京中关村国际创新中心召开&#xff0c;本次大会由openEuler社区和全球计算联盟主办&#xff0c;旨在汇聚全球产业界力量&#xff0c;推动基础软件根技术持续创新…