20个提升效率的JS简写技巧,告别屎山!

JavaScript 中有很多简写技巧,可以缩短代码长度、减少冗余,并且提高代码的可读性和可维护性。本文将介绍 20 个提升效率的 JS 简写技巧,助你告别屎山,轻松编写优雅的代码!

移除数组假值

可以使用 filter() 结合 Boolean 来简化移除数组假值操作。假值指的是在条件判断中被视为 false 的值,例如 nullundefined、空字符串(""'')、0、NaNfalse

传统写法:

let arr = [12, null, 0, 'xyz', null, -25, NaN, '', undefined, 0.5, false];let filterArray = arr.filter(value => {if(value) {return value};}); // [12, 'xyz', -25, 0.5]

简化写法:

let arr = [12, null, 0, 'xyz', null, -25, NaN, '', undefined, 0.5, false];let filterArray = arr.filter(value => Boolean(value)); // [12, 'xyz', -25, 0.5]

更简化写法:

let arr = [12, null, 0, 'xyz', null, -25, NaN, '', undefined, 0.5, false];let filterArray = arr.filter(Boolean); // [12, 'xyz', -25, 0.5]

Boolean 是 JavaScript 的内置构造函数,通过传递一个值给它,可以将该值转换为布尔值。在这种情况下,Boolean 构造函数作为回调函数传递给 filter() 方法,因此会将每个数组元素转换为布尔值。只有转换结果为真值的元素才会保留在新数组中。

注意:这种方式会将 0 也过滤掉,如果不需要过滤 0,需要进行额外的判断。

数组查找

当对数组进行查找时,indexOf()用于获取查找项的位置。如果未找到该项,则返回值为-1。在JavaScript中,0被视为false,而大于或小于0的数字被视为true。因此,需要这样来写:

传统写法:

if(arr.indexOf(item) > -1) { }if(arr.indexOf(item) === -1) {}

简化写法:

if(~arr.indexOf(item)) {}if(!~arr.indexOf(item)) {}

位非()运算符对除了-1之外的任何值都返回一个"真"值。对其进行取反就是简单地使用`!即可。另外,也可以使用includes()`函数:

if(arr.includes(item)) {}

空值合并运算符

空值合并运算符(??)用于为 nullundefined 的变量提供默认值。

传统写法:

const fetchUserData = () => {return '前端充电宝';};const data = fetchUserData();const username = data !== null && data !== undefined ? data : 'Guest';

简化写法:

const fetchUserData = () => {return '前端充电宝';};const data = fetchUserData();const username = data ?? 'CUGGZ';

除此之外,还有一个空位合并赋值运算符(??=),用于在变量为空(nullundefined)时进行赋值操作。

传统写法:

let variable1 = null;let variable2 = "前端充电宝";if (variable1 === null || variable1 === undefined) {variable1 = variable2;}

简化写法:

let variable1 = null;let variable2 = "前端充电宝";variable1 ??= variable2;

??= 的写法更加简洁和易读。它首先检查变量 variable1 是否为 nullundefined,如果是,则将它赋值为 variable2 的值。如果 variable1 已经有一个非空的值,那么赋值操作就不会发生。

逻辑或赋值运算符

逻辑或赋值运算符(||=)用于为变量分配默认值。

传统写法:

let count;if (!count) {count = 0;}

简化写法:

let count;count ||= 0;

count 为假值(例如 undefined、null、false、0、NaN 或空字符串)时,逻辑或赋值运算符将 count 赋值为 0。否则,它会保留 count 的原始值。

多值匹配

对于多个值的匹配,可以将所有的值放入一个数组中,然后使用 indexOf() 方法进行检查。indexOf() 方法是 JavaScript 数组的一个内置方法,它用于返回指定元素在数组中第一次出现的位置索引。如果数组中不存在该元素,则返回 -1。

传统写法:

if (value === 1 || value === 'one' || value === 2 || value === 'two') {// ...}

简化写法:

if ([1, 'one', 2, 'two'].indexOf(value) >= 0) {// ...}

更简化写法:

if ([1, 'one', 2, 'two'].includes(value)) { // ...}

三元表达式

使用三元表达式表示可以简化if...else

传统写法:

let isAdmin;if (user.role === 'admin') {isAdmin = true;} else {isAdmin = false;}

简化写法:

const isAdmin = user.role === 'admin' ? true : false;

更简化写法:

const isAdmin = user.role === 'admin';

短路求值

当将一个变量的值赋给另一个变量时,可能希望确保源变量不为 null、undefined 或空。可以编写一个包含多个条件的长 if 语句,或者使用短路求值来简化。

if (variable1 !== null || variable1 !== undefined || variable1 !== '') {let variable2 = variable1;}

使用短路求值简化后的代码如下:

const variable2 = variable1 || 'new';

对于逻辑或(||)操作符,以下值被视为假:

  • false

  • 0

  • 空字符串("" 或 '')

  • null

  • undefined

  • NaN

所以,如果本身的值可能就是这些中的一个,就不适合使用短路求值。

短路求值还能在函数调用中避免不必要的函数执行。

传统写法:

function fetchData() {if (shouldFetchData) {return fetchDataFromAPI();} else {return null;}}

简化写法:

function fetchData() {return shouldFetchData && fetchDataFromAPI();}

shouldFetchData 为真值时,短路求值会继续执行 fetchDataFromAPI() 函数并返回其结果。如果 shouldFetchData 为假值,短路求值会直接返回假值(null),避免了不必要的函数调用。

科学计数法

可以使用科学技术法来表示数字,以省略尾部的零。例如,1e7 实际上表示 1 后面跟着 7 个零。它表示一个十进制,相当于 10,000,000。

传统写法:

for (let i = 0; i < 10000; i++) {}

简化写法:

for (let i = 0; i < 1e7; i++) {}// 下面的所有比较都将返回 true1e0 === 1;1e1 === 10;1e2 === 100;1e3 === 1000;1e4 === 10000;1e5 === 100000;

位运算符

双位非运算符有一个非常实用的用途,可以用它来替代Math.floor()函数,它在执行相同的操作时速度更快。

传统写法:

Math.floor(4.9) === 4  //true

简化写法:

~~4.9 === 4  //true

指数幂运算

指数幂运算可以使用 ** 来简化。

传统写法:

Math.pow(2,3); // 8Math.pow(2,2); // 4Math.pow(4,3); // 64

简化写法:

2**3 // 82**4 // 44**3 // 64

从 ES7(ECMAScript 2016)开始,JavaScript 引入了指数幂运算符 **,使指数幂运算更加简洁。

双非未运算符

在 JavaScript 中,双非位运算符 ~~ 可以用于将数字向下取整,类似于 Math.floor() 方法的功能。

传统写法:

const floor = Math.floor(6.8); // 6

简化写法:

const floor = ~~6.8; // 6

注意:双非位运算符只适用于 32 位整数,即范围为 -(2^31) 到 (2^31)-1,即 -2147483648 到 2147483647。对于大于 2147483647 或小于 0 的数字,双非位运算符(~~)会给出错误的结果,因此建议在这种情况下使用 Math.floor() 方法。

对象属性

ES6 提供了一种更简洁的方式来给对象赋值属性。如果变量名与对象的键名相同,可以利用简写符号来进行赋值。

传统写法:

const name = '微信公众号:前端充电宝';const age = 18;const person = {name: name,age: age};

简化写法:

const name = '微信公众号:前端充电宝';const age = 30;const person = {name,age};

箭头函数

箭头函数可以简化经典函数的写法。

传统写法:

function sayHello(name) {console.log('Hello', name);}setTimeout(function() {console.log('Loaded')}, 2000);list.forEach(function(item) {console.log(item);});

简化写法:

sayHello = name => console.log('Hello', name);setTimeout(() => console.log('Loaded'), 2000);list.forEach(item => console.log(item));

如果箭头函数只有一条语句,它会隐式地返回其求值的结果,这时可以省略 return 关键字:

传统写法:

function calcCircumference(diameter) {return Math.PI * diameter}

简化写法:

calcCircumference = diameter => (Math.PI * diameter;)

参数解构

如果正在使用一些流行的 Web 框架,比如 React、Vue,可能会使用数组或对象字面量形式的数据来在组件之间传递信息。在组件中要想使用数据对象,就需要对其进行解构。

传统写法:

const observable = require('mobx/observable');const action = require('mobx/action');const runInAction = require('mobx/runInAction');const store = this.props.store;const form = this.props.form;const loading = this.props.loading;const errors = this.props.errors;const entity = this.props.entity;

简化写法:

import { observable, action, runInAction } from 'mobx';const { store, form, loading, errors, entity } = this.props;

还可以为变量赋予新的变量名:

const { store, form, loading, errors, entity:contact } = this.props;

扩展运算符

在ES6中引入的扩展运算符可以简化数组和对象的一些操作。

传统写法:

// 合并数组const odd = [1, 3, 5];const nums = [2, 4, 6].concat(odd);// 克隆数组const arr = [1, 2, 3, 4];const arr2 = arr.slice();

简化写法:

// 合并数组const odd = [1, 3, 5];const nums = [2, 4, 6, ...odd];console.log(nums); // [ 2, 4, 6, 1, 3, 5 ]// 克隆数组const arr = [1, 2, 3, 4];const arr2 = [...arr];

concat() 函数不同,可以使用扩展运算符在另一个数组的任意位置插入一个数组。

const odd = [1, 3, 5];const nums = [2, ...odd, 4, 6];

还可以将扩展运算符与ES6的解构语法结合使用:

const { a, b, ...z } = { a: 1, b: 2, c: 3, d: 4 };console.log(a) // 1console.log(b) // 2console.log(z) // { c: 3, d: 4 }

扩展运算符还能用于合并对象:

传统写法:

let fname = { firstName : '前端' };let lname = { lastName : '充电宝'}let full_names = Object.assign(fname, lname);

简化写法:

let full_names = {...fname, ...lname};

强制参数

在传统的 JavaScript 写法中,为了确保函数参数被传入一个有效值,我们需要使用条件语句来抛出一个错误。可以通过使用强制参数简写的写法实现相同的逻辑。

传统写法:

function foo(bar) {if(bar === undefined) {throw new Error('Missing parameter!');}return bar;}

简化写法:

mandatory = () => {throw new Error('Missing parameter!');}foo = (bar = mandatory()) => {return bar;}

这里定义了一个名为 mandatory 的函数,用于抛出一个错误,表示函数参数未被传入。然后,在函数 foo 的参数列表中,使用赋默认值的方式来将 bar 参数设置为 mandatory() 的调用结果,如果 bar 参数未被传入或者传入了假值,就会触发 mandatory() 函数的执行。

转为布尔值

可以使用双重逻辑非操作符将任何值转换为布尔值。

!!23 // TRUE!!"" // FALSE!!0 // FALSE!!{} // TRUE

单一的逻辑非操作符已经可以将值转换为布尔类型并对其进行取反,所以第二个逻辑非操作符会再次对其进行取反,从而将其恢复为原始含义,并保持为布尔类型。

变量交换

可以使用数组解构来轻松实现变量交换。

传统写法(使用临时变量完成两个变量的交换):

let a = 5;let b = 10;const temp = a;a = b;b = temp;

简化写法(使用数组解构赋值完成两个变量交换):

let a = 5;let b = 10;[a, b] = [b, a];

这里创建了一个包含两个元素的数组 [b, a],然后使用数组解构赋值将其中的值分别赋给变量 ab。由于左侧的数组和右侧的数组结构相同,所以两个值会进行交换。

变量声明

当需要同时声明多个变量时,可以使用变量声明的简写方法来节省时间和空间。

传统写法:

let x;let y;let z = 3;

简化写法:

let x, y, z = 3;

不过,这个优化有些争议,很多人认为这么写会影响代码的可读性,因为许多变量写到了一行,不如一个变量一行更清晰明了,所以可以选择性采用。

如果有多个变量需要赋相同的值,则可以使用连等来实现。

传统写法:

let a = 100;let b = 100;let c = 100;

简化写法:

let a = b = c = 100;

For 循环

JavaScript 中传统的 for 循环语法使用数组的长度作为迭代器来遍历数组。还有很多 for 循环的快捷方式提供了在数组中迭代对象的不同方法,例如:

  • for...of:用于遍历内置字符串、数组、类数组对象、NodeList。

  • for...in:用于访问数组的索引和对对象字面量进行遍历,并记录属性名称和值的字符串。

  • Array.forEach:使用回调函数对数组元素及其索引执行操作。

传统写法:

for (let i = 0; i < arr.length; i++) {console.log("item: ", arr[i]);}}

简化写法:

for (let str of arr) {console.log("item: ", str);}arr.forEach((str) => {console.log("item: ", str);});for (let index in arr) {console.log(index, arr[index]);}

对于对象字面量,也可以使用 for...in 来遍历:

const obj = { a: 1, b: 3, c: 5 };for (let key in obj) {console.log(key, obj[key]);}

往期推荐

VS Code 中使用Git实践,学会了效率翻倍!

微软最热门的10款前端开源项目!

JavaScript 终于原生支持数组分组了!

Next.js 13.5 正式发布,速度大幅提升!

多图预警,前端应该掌握的浏览器调试技巧大揭秘!

竟然可以在一个项目中混用 Vue 和 React?

图解 60 个 CSS 选择器,一网打尽!

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

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

相关文章

智能机器学习:人工智能的下一个巨大飞跃

文章目录 第1节&#xff1a;智能机器学习的背景1.1 传统机器学习1.2 人工智能 第2节&#xff1a;智能机器学习的定义2.1 智能机器学习的原理2.1.1 自主学习2.1.2 强化学习2.1.3 自适应性 2.2 智能机器学习的关键技术2.2.1 深度学习2.2.2 强化学习算法2.2.3 自然语言处理&#x…

Stable Diffusion 参数介绍及用法

大模型 CheckPoint 介绍 作用&#xff1a;定调了作图风格&#xff0c;可以理解为指挥者 安装路径&#xff1a;models/Stable-diffusion 推荐&#xff1a; AnythingV5Ink_v32Ink.safetensors cuteyukimixAdorable_midchapter2.safetensors manmaruMix_v10.safetensors counterf…

线性约束最小方差准则(LCMV)波束形成算法仿真

常规波束形成仅能使得主波束对准目标方向&#xff0c;从而在噪声环境下检测到目标&#xff0c;但无法对复杂多变的干扰做出响应&#xff0c;所以不能称之为真正意义上的自适应滤波。自适应阵列处理指的是采用自适应算法对空间阵列接收的混合信号进行处理&#xff0c;又可称为自…

晨控CK-FR08系列读写器与LS可编程逻辑控制器MODBUSRTU连接手册

晨控CK-FR08系列读写器与LS可编程逻辑控制器MODBUSRTU连接手册 晨控CK-FR08是一款基于射频识别技术的高频RFID标签读卡器&#xff0c;读卡器工作频率为13.56MHZ&#xff0c;支持对I-CODE 2、I-CODE SLI等符合ISO15693国际标准协议格式标签的读取。读卡器内部集成了射频部分通信…

【Linux】生产者和消费者模型

生产者和消费者概念基于BlockingQueue的生产者消费者模型全部代码 生产者和消费者概念 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。 生产者和消费者彼此之间不直接通讯&#xff0c;而通过这个容器来通讯&#xff0c;所以生产者生产完数据之后不用等待…

微信小程序 工具使用(HBuilderX)

微信小程序 工具使用:HBuilderX 一 HBuilderX 的下载二 工具的配置2.1 工具 --> 设置 --> 运行配置2.1.1 微信开发者工具路径2.1.2 node 运行配置 2.2 插件 工具 --> 插件安装2.2.1 下载插件 三 微信小程序端四 同步运行五 BUG5.1 nodemon在终端无法识别 一 HBuilderX…

AnV-X6使用及总结

目录 1 简介2 安装3 基础概念3.1 画布Graph3.2 基类Cell3.3 节点Node3.4 边Edge 4 使用4.1 创建节点4.2 节点连线4.3 事件系统 5 总结 1 简介 AntV是一个数据可视化&#xff08;https://x6.antv.antgroup.com/&#xff09;的工具&#xff08;https://antv.vision/zh/ &#xf…

【深度学习实验】卷积神经网络(四):自定义二维汇聚层:最大汇聚(max pooling)和平均汇聚(average pooling)

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. Conv2D&#xff08;二维卷积层&#xff09; 2. Pool2D&#xff08;二维汇聚层&#xff09; 理论知识 a. 初始化 b. 前向传播(最大汇聚层) c. 前向传播(平均汇聚…

智能的障碍:符号化

基于事实与价值叠加的算计与基于事实的计算有着明显的区别。 基于事实的计算是指根据已有的客观事实和数据进行计算和推理。在这种计算中&#xff0c;只考虑和利用与事实相关的信息和数据&#xff0c;目的是得出合理的、基于客观事实的结论。例如&#xff0c;使用数学公式和逻辑…

CentOS密码重置

背景&#xff1a; 我有一个CentOS虚拟机&#xff0c;但是密码忘记了&#xff0c;偶尔记起可以重置密码&#xff0c;于是今天尝试记录一下&#xff0c;又因为我最近记性比较差&#xff0c;所以必须要记录一下。 过程&#xff1a; 1、在引导菜单界面&#xff08;grub&#xff…

【word密码】为什么word设置只读模式之后,还能编辑?

Word文档设置了只读模式&#xff0c;是可以编辑的&#xff0c;但是当我们进行保存的时候就会发现&#xff0c;word提示需要重命名并选择新路径才能够保存。 这种操作&#xff0c;即使可以编辑文字&#xff0c;但是原文件是不会受到影响的&#xff0c;编辑之后的word文件会保存到…

Android.bp常用语法和预定义属性

介绍 Android.bp是Android构建系统中用于定义模块和构建规则的配置文件&#xff0c;它使用一种简单的声明式语法。以下是Android.bp的一些常见语法规则和约定&#xff1a; 注释&#xff1a; 单行注释使用//符号。 多行注释使用/和/包围。 和go语言相同 // 这是单行注释 /* 这是…

Ubuntu 安装Kafka

在本指南中&#xff0c;我们将逐步演示如何在 Ubuntu 22.04 上安装 Apache Kafka。 在大数据中&#xff0c;数以百万计的数据源生成了大量的数据记录流&#xff0c;这些数据源包括社交媒体平台、企业系统、移动应用程序和物联网设备等。如此庞大的数据带来的主要挑战有两个方面…

性能压力测试的定义及步骤是什么

在今天的数字化时代&#xff0c;软件系统的性能和稳定性对于企业的成功至关重要。为了确保软件在高负载和压力情况下的正常运行&#xff0c;性能压力测试成为了不可或缺的环节。本文将介绍性能压力测试的定义、步骤。 一、性能压力测试的定义和目标 性能压力测试是通过模拟实际…

FragmentManager is already executing transactions

本文解决问题&#xff1a; java.lang.IllegalStateException: FragmentManager is already executing transactions 问题背景描述&#xff1a; 在Fragment中 用tablayoutviewpagerfragment&#xff0c;即Fragment嵌套Fragment场景、或者ViewPager2嵌套ViewPager2时。 执行生命…

vue中同一个页面参数不同动态改变数据与标题

背景 要求做一个页面&#xff0c;可以在菜单配置参数后直接跳转显示不同的报表&#xff1b; 具体步骤 步骤1&#xff1a;接收参数 参数配置与路由拦截这里不详细说&#xff0c;可以参考vue配置参数跳转 说明&#xff1a;这里参考的是saber框架中的特殊情况&#xff0c;如果…

SQLyog 连接 MySQL8.0+ 报错2058

问题如下&#xff1a; 解决方案&#xff1a; 1.首先用命令窗口进入user表 2.使用有mysql.user表权限的用户连接mysql并执行如下命令&#xff1a; ALTER USER sqlyoglocalhost IDENTIFIED WITH mysql_native_password BY root23456; 注&#xff1a;使用mysql_native_password…

DBRichEdit关联ClientDataSet不能保存的Bug

ClientDataSet的最大好处&#xff0c;就是建立能内存表&#xff0c;特别DataSnap三层运用中&#xff0c;主要使用ClientDataSet与运程的服务器中的数据表&#xff0c;建立读取存贮关系。 在软件的使用中&#xff0c;总有客户反映&#xff0c;一些数据不能保存。 发现都是使用DB…

如何使用docker快速部署MinDoc文档系统

MinDoc是非常优秀的知识分享系统&#xff0c;但是很多刚接触的人会一脸懵逼&#xff0c;而且官方文档写的也并不清晰&#xff0c;所以和大家分享一下快速部署MinDoc的方法。 首先docker环境先自行安装好&#xff0c;这里不再赘述。 拉取docker镜像&#xff1a; docker pull …

RS232,485,422的定义及区别

计算机与计算机或计算机与终端之间的数据传送可以采用串行通讯和并行通讯二种方式。 由于串行通讯方式具有使用线路少、成本低&#xff0c;特别是在远程传输时&#xff0c;避免了多条线路特性的不一致而被广泛采用。串口按电气标准及协议来划分&#xff0c;包括RS232、RS422、R…