记录--你可能忽略的10种JavaScript快乐写法

Posted 林恒smileZAZ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录--你可能忽略的10种JavaScript快乐写法相关的知识,希望对你有一定的参考价值。

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

前言

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

笔者至今难以忘记最开始踏入程序员领域时接触的一段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

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

 

你可能忽略的json的坑!!!

json,前后端进行数据传输的一种格式,基本前后端分离的模式中已经非常的普遍了。而且,语法也很简答。他只有两个方法,parse,stringify.大家都不会陌生。那么今天我们来看一下你可能会忽略掉的json的一些坑。
1:json对于解析值为undefined的值有一些特别的处理。分为两种情况在对象中undefined将会被直接忽略掉。我们来做个测验。

 let obj = {name: undefined,age: 10}
 let result = JSON.stringify(obj)
console.log(result)
结果为 {"age":10}。
//你会看到出现在对象中的值为undefined的name被忽略掉了。

 第二个:undefined出现在数组中将会被置为null,继续测验。

 var obj = {name: [undefined,10]}
 var result = JSON.stringify(obj)
console.log(result)
结果为:{"name": [null,10]}

那么我们在前后端数据传输中就得特别注意了还有进行对象深拷贝时候就尽量规避使用json.parse(json.string(obj))。可能会导致一些其他问题。
最后再说一个json的用法。配合localStorage存储一个对象。我们知道localStorage只能存储字符串,因此我们可以利用json.stringify()转换为字符串,然后用的时候在通过parse取出来就好了。
  




以上是关于记录--你可能忽略的10种JavaScript快乐写法的主要内容,如果未能解决你的问题,请参考以下文章

一种使用 javascript 为活动源聚合和分组项目的方法

你可能忽略的json的坑!!!

每个成功的程序员,都会掌握这三种语言!

认知自由:可能是通向快乐的最短路径

程序员获取编程灵感的 10 种方式

20230417 训练记录:dp