< 每日知识点:关于Javascript 精进小妙招 ( Js技巧 ) >

logoImg


👉 前言

这几天稍微没那么忙了,得空继续更新,今天更新的是关于Javascript的小技巧,!

在前端开发中,最经常打交道的除了HTML,我相信就是Javascript了。但是在书写时,我们往往会忽略一些细节,或者是不注重性能之类的! 所以今天特此提及Javascript的小技巧,希望能有所帮助!

Tips: 关于JavaScript性能方面: 大伙可以去看看,之前写过的< 在 Js 中如何理解 ‘ 时间复杂度 ’ 和 ‘ 空间复杂度 ’ > 一文!对提升代码质量有所帮助。

JavaScript实现功能的写法有很多很多,俗话说的好: “ 条条大路通罗马 ”, 但是有些写法写出来,就总能让人眼前一亮! 借此结合自己的所学,表达一下自己的看法!

仅以抛砖引玉,大家有什么好的建议或者看法,可以在评论区留言哦!

👉 数据结构进阶

在开发过程中,我们常常会遇到一些,复杂结构取值赋值的情况。一般是先解构、后取值赋值的操作,但是我们也能通过更加简便的方法去实现解构赋值一步到位!

原理: 定义一个匿名变量, 通过给匿名变量赋值,从而取出提前定义好的同名属性的值

let infoData = {}
const _infoData = {
	name_1: '这是第一个名字',
	name_2: '这是第二个名字'
}

({ name_1: infoData.name_1, name_2: infoData.name_2 } = _infoData )

console.log(infoData) 
//{ name_1: '这是第一个名字', name_2: '这是第二个名字' }

虽然这种写法看上去简洁很多,但是也有其弊端,即可读性方面不如直接解构赋值直观。(这种写法适合装13 😏)

拓展

通过上述使用,同理可以拓展出许许多多的用法来。特定类型的数据类型,它们身上挂载许许多多属性和方法,我们可以通过上面那种赋值解构的方式获取对应数据身上的属性和值!

接下来以数组为例,我们输出其对应的属性:
在这里插入图片描述
不难看出, 一个数组中除了其对应的内容,还包含了一个属性length 以及 原型对象属性prototype,可以通过赋值解构的方式,直接将所需属性提取出来!

let arr = ['1008611', '中国移动', '广东省']

const getInfo = ({ 0: num, 1: name, length, [length - 1]: address }) => {
	console.log(num, name, address, length) 
}

getInfo(arr)
// 1008611 中国移动 3 广东省

👉 将 ‘阿拉伯数字’ 转为 ‘中文数字(汉字)’

在开发过程中,有时为了美观,我们往往会自定义一些顺序列表名称,例如: 第一XXX、第二XXX、第三XXX等诸如此类的名称,通过循环的方式渲染在页面中。

/**
 * 数字转成汉字
 * @params num === 要转换的数字
 * @return 汉字
 * */
toChinesNum(num) {
  let changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
  let unit = ['', '十', '百', '千', '万']
  num = parseInt(num)
  let getWan = (temp) => {
    let strArr = temp.toString().split('').reverse()
    let newNum = ''
    let newArr = []
    strArr.forEach((item, index) => {
      newArr.unshift(item === '0' ? changeNum[item] : changeNum[item] + unit[index])
    })
    let numArr = []
    newArr.forEach((m, n) => {
      if (m !== '零') numArr.push(n)
    })
    if (newArr.length > 1) {
      newArr.forEach((m, n) => {
        if (newArr[newArr.length - 1] === '零') {
          if (n <= numArr[numArr.length - 1]) {
            newNum += m
          }
        } else {
          newNum += m
        }
      })
    } else {
      newNum = newArr[0]
    }

    return newNum
  }
  let overWan = Math.floor(num / 10000)
  let noWan = num % 10000
  if (noWan.toString().length < 4) {
    noWan = '0' + noWan
  }
  return overWan ? getWan(overWan) + '万' + getWan(noWan) : getWan(num)
}

方法转载自: js中把数字转换成汉字输出 一文,原文有更加大单位的转换方法,有需要可以跳转去看看哦

👉 通过css检测系统的主题色从而全局修改样式

通过 prefers-color-scheme 实现浏览器主题切换, prefers-color-scheme 是CSS 媒体特性【@media】用于检测用户是否有将操作系统的主题色设置为亮色【light】或者暗色【dark】

详细说明: 点击跳转

@media (prefers-color-scheme: dark) { 
	//... 
} 
@media (prefers-color-scheme: light) {
	//...
}

Tips: 这种使用媒体检测的方法,在使用前端框架后,显得有点鸡肋。
以Vue框架为例,可以直接通过v:bind 绑定 class,通过编写表达式控制主题切换。
例如: :class="theme ? 'light' : 'dark' "

👉 数组随机打乱顺序

在开发中,通常情况下会通过Math.random() 函数去获取一个随机数值,进行数组顺序打乱。当然这时在正常情况下,但是如果要对一个数据量庞大的数组进行打乱时,往往随机的数据量越大,随机的数组内容就显得越不够随机。这时就需要通过二次随机的方式去取值,使得取出来的数值更加符合随机性。

第一种方法

通过 0.5-Math.random() 得到一个随机数,再通过两次sort排序打乱的更彻底

shuffle(arr) {
	return arr.sort(() => 0.5 - Math.random()).sort(() => 0.5 - Math.random());
},

第二种方法

通过for循环的方式,获取下标并以其作为随机基数,获取二次随机后的随机值进行打乱

function shuffle(arr) {
  for (let i = arr.length - 1; i > 0; i--) {
    const randomIndex = Math.floor(Math.random() * (i + 1));
    [arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]]
  }
  return arr
}

拓展

随机获取一个Boolean值: 和上个原理相同,通过随机数获取,**Math.random()**的区间是0-0.99,用0.5在中间百分之五十的概率

function randomBool() {
    return 0.5 - Math.random()
}

👉 数组函数妙用

① 把数组最后一项移到第一项

let arr = [1, 2, 3]
const changeArr_EtS = (arr) => {
  return arr.unshift(arr.pop());
}
changeArr_EtS(arr) // 返回数组长度
console.log(arr) // [3, 1, 2]

② 把数组第一项放到最后一项

let arr = [1, 2, 3]
const changeArr_StE = (arr) => {
  return arr.push(arr.shift());
}
changeArr_StE(arr) // 返回数组长度
console.log(arr) // [2, 3, 1]

③ 利用set对数组进行条件筛选(ES6新特性)

在ES6中,推出了 “ Set ”类,它是一种类似数组的变量类型, 但是它有个特性,就是它的成员都必须是唯一值,不允许重复。利用这个特性,可以对数组进行去重、求交集等操作,示例如下:

//1 数组去重
let a = [1,2,3,4,5,6,7,1,2,3];
let b = [...new Set([...a])];

// 2 求交集 并集  差集
let a = new Set[1,2,3];
let b = new Set[3,4,5];
	
//交集
let c = new Set([...a,...b]);

//并集
let d = new Set([...a].filter(x => b.has[x]));

//差集
let d = new Set([...a].filter(x=> !b.has[x]));

👉 借助Element.scrollIntoView 实现节点平滑滚动

Element非彼element,此Element 是一个通用性非常强的基类,所有 Document 对象下的对象都继承自它。这个接口描述了所有相同种类的元素所普遍具有的方法和属性。一些接口继承自 Element 并且增加了一些额外功能的接口描述了具体的行为。

本知识点是运用了其中的scrollIntoView方法,scrollIntoView() 方法会滚动元素的父容器,使被调用 scrollIntoView() 的元素对用户可见。

> 语法规则

element.scrollIntoView(); // 等同于 element.scrollIntoView(true)
element.scrollIntoView(alignToTop); // Boolean 型参数
element.scrollIntoView(scrollIntoViewOptions); // Object 型参数

> 参数选项

alignToTop (布尔值) - 可选

  • true,元素的顶端将和其所在滚动区的可视区域的顶端对齐。等价于: scrollIntoViewOptions: {block: "start", inline: "nearest"}。
  • false,元素的底端将和其所在滚动区的可视区域的底端对齐。等价于:scrollIntoViewOptions: {block: "end", inline: "nearest"}

scrollIntoViewOptions(对象) - 可选

一个包含下列属性的对象:

  • behavior 可选

    定义动画过渡效果, "auto"或 “smooth” 之一。默认为 “auto”。

  • block 可选

    定义垂直方向的对齐, “start”, “center”, “end”, 或 "nearest"之一。默认为 “start”。

  • inline 可选

    定义水平方向的对齐, “start”, “center”, “end”, 或 "nearest"之一。默认为 “nearest”。

> 使用案例

// 获取需要使用锚点滚动的元素
let element = document.getElementById("box");

// 元素的顶端将和其所在滚动区的可视区域的顶端对齐
element.scrollIntoView();

// 元素的底端将和其所在滚动区的可视区域的底端对齐
element.scrollIntoView(false);

// 滚动至底端
element.scrollIntoView({block: "end"});

// 平滑滚动至顶部
element.scrollIntoView({ behavior: "smooth", block: "start" }) 

// 平滑滚动至底部
element.scrollIntoView({ behavior: "smooth", block: "end" }) 

👉 获取一个随机颜色

// 通过获取一个16进制的随机数
function getRandomColor(){
    return `#${Math.floor(Math.random() * 0xffffff).toString(16)}`;
}

👉 克隆数组

在js中,有许多函数或语法按照指定操作是可以返回数组本身的,虽然写法不同,但是返回值均为数组,比如以下这些示例:

const clone = (arr) => arr.slice(0);
const clone = (arr) => [...arr];
const clone = (arr) => Array.from(arr);
const clone = (arr) => arr.map((x) => x);
const clone = (arr) => JSON.parse(JSON.stringify(arr));
const clone = (arr) => arr.concat([]);
const clone = (arr) => structuredClone(arr);

👉 一步从时间中提取年月日时分秒

function extract(date){
	// 由于toISOString会丢失时区,导致时间差八小时,所以在格式化之前我们加上八个小时时间即可。
	const d = new Date(new Date(date).getTime() + 8*3600*1000);
	return new Date(d).toISOString().split(/[^0-9]/).slice(0, -1);
}
console.log(extract(new Date()))
// ['2022', '10', '24', '12', '45', '40', '49']

👉 利用 split + 正则 实现 提取URL字符串中的参数

网页路径经常是:www.baidu.com?search=js&xxx=kkk这种形式的,我们是经常需要取参数的,可以使用第三方的qs包实现,如果你只是要实现取参数,这一句代码就可以实现,不必再引入qs了。

const getParameters = URL => JSON.parse(`{"${decodeURI(URL.split("?")[1]).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"')}"}`
)

getParameters("https://www.google.com.hk/search?q=js+md&newwindow=1");
// {q: 'js+md', newwindow: '1'}

👉 实现反转字符串

通过使用split + reverse + join 方法轻松实现。

const reverseStr = str => str.split('').reverse().join('');
reverseStr('this is reverse');
// esrever si siht

👉 检查当前网页是否在后台运作(选项卡式)

浏览器使用选项卡式浏览,任何网页都有可能在后台,此时对用户来说是没有在浏览的, 知道怎么快速检测到,你的网页对用户是隐藏还是可见吗?

可以通过 document.hidden属性来获得。如果网页隐藏,则为 true,反之为 false

const isTabActive = () => !document.hidden; 

isTabActive()
// true|false

👉 检测元素是否处于焦点

document.activeElement 属性返回文档中当前获得焦点的元素。

const elementIsInFocus = (el) => (el === document.activeElement);

elementIsInFocus(anyElement)
// 元素处于焦点返回true,反之返回false

👉 检查设备为何种类型

使用 navigator.userAgent获取设备名称,通过正则判断是移动设备还是电脑设备:

// 获取设备名称,通过正则判断类型
const judgeDeviceType = () => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|OperaMini/i.test(navigator.userAgent) ? 'Mobile' : 'PC';

judgeDeviceType()  // PC | Mobile

👉 将指定内容复制到剪贴板

Clipboard API 它的所有操作都是异步的,返回 Promise 对象,不会造成页面卡顿。而且,它可以将任意内容(比如图片)放入剪贴板。

// 详细使用可以查询 Clipboard 使用说明
const copyText = async (text) => await navigator.clipboard.writeText(text)
copyText('小温的学习之旅')

navigator.clipboard 使用说明 [点击跳转]

👉 获取用户在浏览器中选定的文本

使用window内置的 getSelection 获取用户选择的文本。

const getSelectedText = () => window.getSelection().toString();

getSelectedText();
// 返回选中的内容

👉 判断某天是否为工作日

在开发一些与工作相关,比如 ‘ 报工 ’这种,需要判断用户是否在工作日报工的情况,这时就需要用到判断当日是否属于工作日了(周一至周五为工作日)。 判断如下:

// 知识点:  
// getDay() 方法可返回表示星期的某一天的数字。
// 语法 :dateObject.getDay()
// 返回值是 0(周日) 到 6(周六) 之间的一个整数。利用 0 和 6 余数皆是 0的原理。
const isWeekday = (date) => date.getDay() % 6 !== 0;

isWeekday(new Date(2022, 03, 11))
// true

👉 计算两个日期之间相差天数

日常开发中,偶尔会遇到需要显示距离某天剩余的天数, 一般我们就需要计算两日期之间的相差天数了。比如: 计算距离高考的日期、距离某版本项目部署日期剩余天数等等。

const dayDiff = (date1, date2) => Math.ceil(Math.abs(date1.getTime() - date2.getTime()) / 86400000);

dayDiff(new Date("2021-10-21"), new Date("2022-02-12"))
// Result: 114

👉 将数组转换成对象,重构成需要的结构

合理利用好arr.reduce()函数,能合理的提高代码效率。具体使用可点开查看详情!

> reduce详情 <


let arr = [1,2,2,3]

// 比如计算数组中某数字出现的次数
const findTimes = (arr, target) => {
	let objTimes = arr.reduce((target, item, index) => {
        target[item] = target[item] ? (target[item] + 1) : 1
        return target;
    }, {})
	console.log(objTimes) // {1: 1, 2: 2, 3: 1}
	return objTimes[target] || 0
}

// 比如计算数组中数值总和
const findSum = (arr) => {
	return arr.reduce((target, item, index) => target + item, 0)
}

findTimes(arr, 2) // 2

findSum(arr) // 8


今天的卷王之旅到此结束,希望对你有所帮助! 最后求求点个赞支持一下吧!

更新时间: 2023年2月11日,后续有新的亮眼的小技巧再做补充啦~


📃 参考文献

往期内容 💨

🔥 < 今日份知识点: 浅述对函数式编程的理解 及其 优缺点 >

🔥 < element组件封装: element表格(element-table)实现表格列筛选功能组件 >

🔥 < 今日份知识点:谈谈内存泄漏 及 在 Javascript 中 针对内存泄漏的垃圾回收机制 >

🔥 < 今日份知识点:浅述对 “ Vue 插槽 (slot) ” 的理解 以及 插槽的应用场景 >

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术宅小温

你小小的鼓励,是我搬砖的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值