这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

前言

  • 代码的简洁、美感、可读性等等也许不影响程序的执行,但是却对人(开发者)的影响非常之大,甚至可以说是影响开发者幸福感的重要因素之一;
  • 了解一些有美感的代码,不仅可以在一定程度上提高程序员们的开发效率,有些还能提高代码的性能,可谓是一举多得;

笔者至今难以忘记最开始踏入程序员领域时接触的一段List内嵌for的Python代码:

array = [[16, 3, 7], [2, 24, 9], [4, 1, 12]]
row_min = [min(row) for row in array ]
print(row_min)

这可能就是动态语言非常优秀的一点,而JavaScript同样作为动态语言,其中包含的优秀代码片段也非常之多,比如我们通过JavaScript也可以非常轻松地实现上述的功能:

const array = [[16, 3, 7], [2, 24, 9], [4, 1, 12]]
const row_min = array.map(item => Math.min(...item))
console.log(row_min)

能写出优秀的代码一直是笔者所追求的,以下为笔者在开发阅读过程积累的一些代码片段以及收集了互联网上一些优秀代码片段,希望对你有所帮助

概述

这里,考虑到有些技巧是大家见过的或者说是已经烂熟于心的,但总归有可能有些技巧没有留意过,为了让大家更加清楚的找到自己想要查阅的内容以查漏补缺,所以这里笔者贴心地为大家提供了一张本文内容的索引表,供大家翻阅以快速定位,如下:

应用场景标题 描述 补充1 补充2
数组去重 通过内置数据解构特性进行去重[] => set => [] 通过遍历并判断是否存在进行去重[many items].forEach(item => (item <不存在于> uniqueArr) && uniqueArr.push(item))
数组的最后一个元素 获取数组中位置最后的一个元素 使用at(-1)
数组对象的相关转换 对象到数组:Object.entries() 数组到对象:Obecjt.fromEntries()
短路操作 通过短路操作避免后续表达式的执行 a或b:a真b不执行 a且b:a假b不执行
基于默认值的对象赋值 通过对象解构合并进行带有默认值的对象赋值操作 {...defaultData, ...data}
多重条件判断优化 单个值与多个值进行对比判断时,使用includes进行优化 [404,400,403].includes
交换两个值 通过对象解构操作进行简洁的双值交换 [a, b] = [b, a]
位运算 通过位运算提高性能和简洁程度
replace()的回调 通过传入回调进行更加细粒度的操作
sort()的回调 通过传入回调进行更加细粒度的操作 根据字母顺序排序 根据真假值进行排序

数组去重

这不仅是我们平常编写代码时经常会遇到的一个功能实现之一,也是许多面试官在考查JavaScript基础时喜欢考查的题目,比较常见的基本有如下两类方法:

1)通过内置数据结构自身特性进行去重

主要就是利用JavaScript内置的一些数据结构带有不包含重复值的特性,然后通过两次数据结构转换的消耗[] => set => []从而达到去重的效果,如下演示:

const arr = ['justin1go', 'justin2go', 'justin2go', 'justin3go', 'justin3go', 'justin3go'];
const uniqueArr = Array.from(new Set(arr));
// const uniqueArr = [...new Set(arr)];

2)通过遍历并判断是否存在进行去重

白话描述就是:通过遍历每一项元素加入新数组,新数组存在相同的元素则放弃加入,伪代码:[many items].forEach(item => (item <不存在于> uniqueArr) && uniqueArr.push(item))

至于上述的<不存在于>操作,可以是各种各样的方法,比如再开一个for循环判断新数组是否有相等的,或者说利用一些数组方法判断,如indexOfincludesfilterreduce等等

const arr = ['justin1go', 'justin2go', 'justin2go', 'justin3go', 'justin3go', 'justin3go'];
const uniqueArr = [];
arr.forEach(item => {
// 或者!uniqueArr.includes(item)
if(uniqueArr.indexOf(item) === -1){
uniqueArr.push(item)
}
})

结合filter(),判断正在遍历的项的index,是否是原始数组的第一个索引:

const arr = ['justin1go', 'justin2go', 'justin2go', 'justin3go', 'justin3go', 'justin3go'];
const uniqueArr = arr.filter((item, index) => {
return arr.indexOf(item, 0) === index;
})

结合reduce(),prev初始设为[],然后依次判断cur是否存在于prev数组,如果存在则加入,不存在则不动:

const arr = ['justin1go', 'justin2go', 'justin2go', 'justin3go', 'justin3go', 'justin3go'];
const uniqueArr = arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);

数组的最后一个元素

对于获取数组的最后一个元素,可能平常见得多的就是arr[arr.length - 1],我们其实可以使用at()方法进行获取

const arr = ['justin1go', 'justin2go', 'justin3go'];
console.log(arr.at(-1)) // 倒数第一个值
console.log(arr.at(-2)) // 倒数第二个值
console.log(arr.at(0)) // 正数第一个
console.log(arr.at(1)) // 正数第二个

注:node14应该是不支持的,目前笔者并不建议使用该方法,但获取数组最后一个元素是很常用的,就应该像上述语法一样简单...

数组对象的相互转换

    const entryified = [
["key1", "justin1go"],
["key2", "justin2go"],
["key3", "justin3go"]
]; const originalObject = Object.fromEntries(entryified);
console.log(originalObject);

短路操作

被合理运用的短路操作不仅非常的优雅,还能减少不必要的计算操作

1)基本介绍

主要就是||或操作、&&且操作当第一个条件(左边那个)已经能完全决定整个表达式的值的时候,编译器就会跳过该表达式后续的计算

  • 或操作a || b:该操作只要有一个条件为真值时,整个表达式就为真;即a为真时,b不执行;
  • 且操作a && b:该操作只要有一个条件为假值时,整个表达式就为假;即a为假时,b不执行;

2)实例

网络传输一直是前端的性能瓶颈,所以我们在做一些判断的时候,可以通过短路操作减少请求次数:

const nextStep = isSkip || await getSecendCondition();
if(nextStep) {
openModal();
}

还有一个经典的代码片段:

function fn(callback) {
// some logic
callback && callback()
}

基于默认值的对象赋值

  • 很多时候,我们在封装一些函数或者类时,会有一些配置参数。
  • 但这些配置参数通常来说会给出一个默认值,而这些配置参数用户是可以自定义的
  • 除此之外,还有许许多多的场景会用到的这个功能:基于默认值的对象赋值。
function fn(setupData) {
const defaultSetup = {
email: "justin3go@qq.com",
userId: "justin3go",
skill: "code",
work: "student"
}
return { ...defaultSetup, ...setupData }
} const testSetData = { skill: "sing" }
console.log(fn(testSetData))

如上{ ...defaultSetup, ...setupData }就是后续的值会覆盖前面key值相同的值。

多重条件判断优化

if(condtion === "justin1go" || condition === "justin2go" || condition === "justin3go"){
// some logic
}

如上,当我们对同一个值需要对比不同值的时候,我们完全可以使用如下的编码方式简化写法并降低耦合性:

const someConditions = ["justin1go", "justin2go", "justin3go"];
if(someConditions.includes(condition)) {
// some logic
}

交换两个值

一般来说,我们可以增加一个临时变量来达到交换值的操作,在Python中是可以直接交换值的:

a = 1
b = 2
a, b = b, a

而在JS中,也可以通过解构操作交换值;

let a = 1;
let b = 2;
[a, b] = [b, a]

简单理解一下:

  • 这里相当于使用了一个数组对象同时存储了a和b,该数组对象作为了临时变量
  • 之后再将该数组对象通过解构操作赋值给a和b变量即可

同时,还有种比较常见的操作就是交换数组中两个位置的值:

const arr = ["justin1go", "justin2go", "justin3go"];
[arr[0], arr[2]] = [arr[2], arr[0]]

位运算

关于位运算网上的讨论参差不齐,有人说位运算性能好,简洁;也有人说位运算太过晦涩难懂,不够易读,这里笔者不发表意见,仅仅想说的是尽量在使用位运算代码的时候写好注释!

下面为一些常见的位运算操作,参考链接

1 ) 使用&运算符判断一个数的奇偶

// 偶数 & 1 = 0
// 奇数 & 1 = 1
console.log(2 & 1) // 0
console.log(3 & 1) // 1

2 ) 使用~, >>, <<, >>>, |来取整

console.log(~~ 6.83)    // 6
console.log(6.83 >> 0) // 6
console.log(6.83 << 0) // 6
console.log(6.83 | 0) // 6
// >>>不可对负数取整
console.log(6.83 >>> 0) // 6

3 ) 使用^来完成值交换

var a = 5
var b = 8
a ^= b
b ^= a
a ^= b
console.log(a) // 8
console.log(b) // 5

4 ) 使用&, >>, |来完成rgb值和16进制颜色值之间的转换

/**
* 16进制颜色值转RGB
* @param {String} hex 16进制颜色字符串
* @return {String} RGB颜色字符串
*/
function hexToRGB(hex) {
var hexx = hex.replace('#', '0x')
var r = hexx >> 16
var g = hexx >> 8 & 0xff
var b = hexx & 0xff
return `rgb(${r}, ${g}, ${b})`
} /**
* RGB颜色转16进制颜色
* @param {String} rgb RGB进制颜色字符串
* @return {String} 16进制颜色字符串
*/
function RGBToHex(rgb) {
var rgbArr = rgb.split(/[^\d]+/)
var color = rgbArr[1]<<16 | rgbArr[2]<<8 | rgbArr[3]
return '#'+ color.toString(16)
}
// -------------------------------------------------
hexToRGB('#ffffff') // 'rgb(255,255,255)'
RGBToHex('rgb(255,255,255)') // '#ffffff'

replace()的回调函数

之前写过一篇文章介绍了它,这里就不重复介绍了,F=>传送

sort()的回调函数

sort()通过回调函数返回的正负情况来定义排序规则,由此,对于一些不同类型的数组,我们可以自定义一些排序规则以达到我们的目的:

  • 数字升序:arr.sort((a,b)=>a-b)
  • 按字母顺序对字符串数组进行排序:arr.sort((a, b) => a.localeCompare(b))
  • 根据真假值进行排序:
const users = [
{ "name": "john", "subscribed": false },
{ "name": "jane", "subscribed": true },
{ "name": "jean", "subscribed": false },
{ "name": "george", "subscribed": true },
{ "name": "jelly", "subscribed": true },
{ "name": "john", "subscribed": false }
]; const subscribedUsersFirst = users.sort((a, b) => Number(b.subscribed) - Number(a.subscribed))

本文转载于:

https://juejin.cn/post/7203243879255277623

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--你可能忽略的10种JavaScript快乐写法的更多相关文章

  1. 10种JavaScript特效实例让你的网站更吸引人

    我们有三种主要的方法(从难到易):自己动手写脚本;使用类似于jQuery和mooTools的JavaScript框架(可以让编写代码变得更容易些);使用能工作于现有的JavaScript框架下的提前预 ...

  2. 10种JavaScript开发者必备的VS Code插件

    摘要: 好的代码插件可以让工作效率翻倍,心情也更加舒畅! 原文:10 Must-have VS Code Extensions for JavaScript Developers 作者:Michael ...

  3. 30个深度学习库:按Python、C++、Java、JavaScript、R等10种语言分类

    30个深度学习库:按Python.C++.Java.JavaScript.R等10种语言分类 包括 Python.C++.Java.JavaScript.R.Haskell等在内的一系列编程语言的深度 ...

  4. 10 种最常见的 Javascript 错误(频率最高)

    本文是小编给大家收藏的JavaScript 中频度最高的 10 种错误,我们会告诉你什么原因导致了这些错误,以及如何防止这些错误发生.写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学 ...

  5. 从零开始学习前端JAVASCRIPT — 10、JavaScript基础ES6(ECMAScript6.0)

    ECMAScript 6.0(简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了.它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发 ...

  6. 45种Javascript技巧大全(转)

      6.小心使用typeof.instanceof和constructor typeof:不要忘了typeof null返回object,而大多数对象,typeof(Array, Date, and ...

  7. 七个开法者经常忽略或误用的JavaScript基本知识

    七个开法者经常忽略或误用的JavaScript基本知识 翻译自 http://tech.pro/tutorial/1453/7-javascript-basics-many-developers-ar ...

  8. 记录下项目中常用到的JavaScript/JQuery代码二(大量实例)

    记录下项目中常用到的JavaScript/JQuery代码一(大量实例) 1.input输入框监听变化 <input type="text" style="widt ...

  9. 2018年值得关注的10大JavaScript动画库

    2018年值得关注的10大JavaScript动画库 旭日云中竹 前端早读课 1周前 前言 平时大家开发动画是采用什么方式呢?虽然18年过半,可这十个动画库是真的没听过几个,有点尴尬.今日早读文章由@ ...

  10. 在Microsoft Power BI中创建地图的10种方法

    今天,我们来简单聊一聊“地图”. 在我们日常生活中,地图地位已经提升的越来越高,出门聚餐.驾驶.坐车.旅行......应运而生的就是各种Map APP. 作为数据分析师,我们今天不讲生活地图,要跟大家 ...

随机推荐

  1. 看似简单的input框输入竟然异常卡顿,记一个日常性能问题的排查思路

    壹 ❀ 引 我们公司产品主要提供企业项目管理服务,那么自然有配套的desk工单管理系统,用于搜集客户bug以及相关问题反馈.有一天我在测试功能时碰巧发现了一个bug,所以就想着提一个工单记录下方便日后 ...

  2. Java设计模式-外观模式Facade

    介绍 外观模式(Facade),也叫"过程模式:外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用 外观模式通过定义一个一致的接口, ...

  3. js根据输入字符长度自动调整textarea高度

    1.编写html <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  4. 骨牌铺方格 SDUT

    状态转移方程:dp[i] = dp[i - 1] + dp[i - 2]. 当前行,可能是由上一行转移过来的,那么当前行就只能横着铺,所以方案数是dp[i - 1]. 当前行,可能是由i-2行转移过来 ...

  5. Linux驱动开发笔记(四):设备驱动介绍、熟悉杂项设备驱动和ubuntu开发杂项设备Demo

    前言   驱动的开发需要先熟悉基本概念类型,本篇讲解linux杂项设备基础,还是基于虚拟机ubuntu去制作驱动,只需要虚拟机就可以尝试编写注册杂项设备的基本流程.   linux三大设备驱动 字符设 ...

  6. 国内如何快速访问GitHub

    1.国内如何快速访问gibhub -FQ的方法无非就是用软件,这种就不介绍了 -本次介绍的是修改本地系统主机hosts文件,绕过国内dns解析,达到快速访问github 打开https://tool. ...

  7. 基于javaweb的个人音乐网站

    一 .需求 ① 前台用户: 用户注册和登录以及完善个人资料: 添加好友功能(用户之间可通过发送好友申请添加好友,被添加人可以同意或拒绝好友申请): 下载歌曲功能(当用户点击下载按钮时,就能下载相对应的 ...

  8. 【LeetCode回溯算法#02】组合总和III

    组合总和III 力扣题目链接(opens new window) 找出所有相加之和为 n 的 k 个数的组合.组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字. 说明: 所有数字 ...

  9. 前端面试题(四)—— 事件委托(Event Delegation)

    一.什么是事件委托 事件委托(Event Delegation)是一种常用的技术. 它利用事件冒泡的特性,在父元素上监听事件,而不是在子元素上直接添加事件监听器. 通过在父元素上捕获事件,然后根据事件 ...

  10. 手把手教你蜂鸟e203协处理器的扩展

    NICE协处理器 赛题要求:   对蜂鸟E203 RISC-V内核进行运算算子(譬如加解密算法.浮点运算.矢量运算等)的扩展,可通过NICE协处理器接口进行添加,也可直接实现RISC-V指令子集(譬如 ...