js开发代码片段与小技巧

简介: js开发代码片段与小技巧

1、+ 号的隐式类型转换使用
+[3] //3
+[1,2,3].slice(-1) //将 [3] 转换为了3
2、日期的转换
const addDaysToDate = (date, n) => {
const d = new Date(date);
d.setDate(d.getDate() + n);
return d.toISOString().split('T')[0];
};
addDaysToDate('2020-10-15', 10); // '2020-10-25'
平时做日期的计算可能更多的使用时间戳,秒数去加减,其实有对应的 setDate,getDate等方法去做(月份也一样)
toISOString 可以将日期对象转换为 YYYY-MM-DDTHH:mm:ss.sssZ 格式,分割掉 T 字符,即可以得到日期形式
3、对象的合并
Object.assign
// 在像某对象添加多个属性时,可以直接采取合并方式
const addStyles = (el, styles) => Object.assign(el.style, styles)
addStyles(document.getElementById('my-element'), {
background: 'red',
color: '#ffff00',
fontSize: '3rem'
})
4、Array.from
/
对于这个api知道更多的只是将类数组转化为真正的数组
(arrayLike,mapFn) 准确的说应该是类数组或者 可迭代对象({length: 5})
mapFn 接收一个回调,返回的数组每个元素会执行该回调
/
let a = Array.from({length: 10},(_,i) => i)
a // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5、关于工具函数封装tips
在封装工具类函数时,可以往闭包的角度靠(内部再返回一个函数)
有时候可以具有更好的拓展性
// 栗子:获取某些数中的最大值
const ary = (fn,n) => (...arg) => fn(...arg.slice(0,n))
const firstTwoMax = ary(Math.max, 2)
firstTwoMax(1,2,3,4)

// ary的函数将传入的函数,作为返回函数的返回值调用,类似于将传入的函数缓存下来,再一次调用时,传入比较值
// 这样有个好处是,其实我们可以更改比较条件,比如 取最小值等等
// 这样工具函数更具有灵活性
6、 按条件分割数组
const bifurcateBy = (arr, fn) =>
arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [
[],
[],
])
bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b');
// [ ['beep', 'boop', 'bar'], ['foo'] ]

/
利用 reduce 将结果汇总,同时把分割条件作为一个 返回布尔值的函数传入
内部通过布尔值的判断,添加到对应的数组中
/
7、二分搜索算法,来查找已排序数组中某元素的位置
尽管现在有api可以直接实现位置查找,不过这个算法思想还是可以的
const binarySearch = (arr,item) => {
// 获取首位下标
let l = 0,
r = arr.length - 1;
while(l <= r) {
// 找到中间下标
const middle = Math.floor( (l + r) / 2)
const guess = arr[middle]
// 中间值与目标值比较
if(guess == item) return middle
// 中间值 > 目标值 ? 说明目标值在左侧,则取左边中间值再比较,反之亦然
guess > item ? r = middle - 1 : l = middle + 1
}
return -1
}
binarySearch([1,2,3,4],4) // 3
二分搜索算法,采取折中的方式,将中间值与目标做比较,然后不断修改中间值,进而找到目标值
8、冒泡排序
const bubbleSort = arr => {
let swapped = false;
const a = [...arr];
for (let i = 1; i < a.length; i++) {
swapped = false;
for (let j = 0; j < a.length - i; j++) {
if (a[j + 1] < a[j]) {
// es6 变量交换
[a[j], a[j + 1]] = [a[j + 1], a[j]];
swapped = true;
}
}
if (!swapped) return a;
}
return a;
};
核心思想是将当前值a 与 下一位置值b比较,如果 a > b,就把 a和b交互位置
同时,一轮排序其实就可以实现最大值排最后了,所以循环次数越往后会越少,这也是 i < a.length ,j < a.length - i 的原因
es6 的变量交换位置,更加方便了,其实也可以用于多个变量的赋值改变类似: [count, i] = [count + 1, r + 1]…
9、将字符串首字母转换为大写
// 有意思的是 这里只是通过解构的方式,就把字符串的首字符与剩余字符分开了
// 在此之前你说否还想着截取首字母再来转换?
const capitalize = ([first, ...rest], lowerRest = false) =>
first.toUpperCase() +
(lowerRest ? rest.join('').toLowerCase() : rest.join(''));

capitalize('fooBar', true); // 'Foobar'
10、链式控制异步流程
const chainAsync = fns => {
let curr = 0;
const last = fns[fns.length - 1];
// 内部实现一个函数,用于逐次从数组中提取执行函数
const next = () => {
const fn = fns[curr++];
// 提取函数与最后一个做对比,是否为最后一个函数
// 同时将这个内部函数,作为回调,传入下一个 异步函数中
fn === last ? fn() : fn(next);
};
next();
};

chainAsync([
next => {
console.log('0 seconds');
// 函数执行后,再执行传入的回调next
setTimeout(next, 1000);
},
next => {
console.log('1 second');
setTimeout(next, 1000);
},
() => {
console.log('2 second');
}
]);
异步的实现,其实还是回调的使用,只不过封装后,看似同步
好比 Promise的resolve,获取结果后,通过resolve回调出去
Promise + async ,运用迭代器,使得可以控制函数的暂停和恢复,更加具有同步风范
11、js 实现一个剪切板
const copyToClipboard = str => {
const el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
const selected =
document.getSelection().rangeCount > 0
? document.getSelection().getRangeAt(0)
: false;
el.select();
document.execCommand('copy');
document.body.removeChild(el);
if (selected) {
document.getSelection().removeAllRanges();
document.getSelection().addRange(selected);
}
}

copyToClipboard('Lorem ipsum')
12、根据给定函数或者属性,统计符合条件的数组元素的个数
const countBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => {
acc[val] = (acc[val] || 0) + 1;
return acc;
}, {});

countBy([6.1, 4.2, 6.3], Math.floor); // {4: 1, 6: 2}
countBy(['one', 'two', 'three'], 'length'); // {3: 2, 5: 1}
countBy([{ count: 5 }, { count: 10 }, { count: 5 }], x => x.count)
13、实现一个发布订阅模式
const createEventHub = () => ({
hub: Object.create(null),
emit(event, data) {
(this.hub[event] || []).forEach(handler => handler(data));
},
on(event, handler) {
if (!this.hub[event]) this.hub[event] = [];
this.hub[event].push(handler);
},
off(event, handler) {
const i = (this.hub[event] || []).findIndex(h => h === handler);
if (i > -1) this.hub[event].splice(i, 1);
if (this.hub[event].length === 0) delete this.hub[event];
}
});
//代码效果参考:http://www.zidongmutanji.com/zsjx/306135.html

const handler = data => console.log(data);
const hub = createEventHub();
let increment = 0;

// Subscribe:
hub.on('message', handler);
hub.on('message', () => console.log('Message event fired'));
hub.on('increment', () => increment++);

// Publish
hub.emit('message', 'hello world');
hub.emit('message', { hello: 'world' });
hub.emit('increment');

// Unsubscribe
hub.off('message', handler);
14、补充一点关于函数length属性
/*

  • js 函数的length是表示参数的个数,需要注意的是
  • 该个数指的是 函数必须接收参数的个数,且是有效参数(应当是默认值前的参数个数)
  • */
    function a( a,b = 10,c) {} //a.lenght = 1
      a(10,'',30)        // a = 10 b = '' c = 30
      a(10,null,30)      // a = 10 b = null c = 30
      a(10,undefiend,30) // a =10 b = 10 c = 30
    
    // 对于包含默认值的参数,只有传递 undefiend 时(或者不传)才是取默认值,其他情况均为传啥就是啥
相关文章
|
4天前
|
JavaScript 前端开发 API
深入浅出Node.js后端开发
【9月更文挑战第23天】在这篇文章中,我们将探索Node.js的世界,了解它如何改变后端开发的面貌。通过实际案例和代码示例,我们不仅学习Node.js的核心概念,还会深入探讨它的高级特性,如异步编程、事件驱动模型以及微服务架构的应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和实用技能,帮助你构建更高效、可扩展的后端系统。
35 19
|
2天前
|
JavaScript 开发者
深入理解Node.js事件循环及其在后端开发中的应用
【8月更文挑战第57天】本文将带你走进Node.js的事件循环机制,通过浅显易懂的语言和实例代码,揭示其背后的工作原理。我们将一起探索如何高效利用事件循环进行异步编程,提升后端应用的性能和响应速度。无论你是Node.js新手还是有一定经验的开发者,这篇文章都能给你带来新的启发和思考。
|
1天前
|
Web App开发 缓存 JavaScript
深入浅出Node.js后端开发
【9月更文挑战第26天】本文将引导你了解Node.js的基本原理,并通过实际案例展示如何在后端开发中应用它。我们将从Node.js的核心概念讲起,逐步深入到构建一个完整的后端服务,最后探讨如何优化你的Node.js应用。准备好让你的开发技能更上一层楼了吗?让我们一起潜入Node.js的世界!
|
2天前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端开发
【9月更文挑战第25天】本文将带你了解Node.js的基本概念和核心优势,同时提供一些实际的代码示例来加深理解。无论你是初学者还是有一定经验的开发者,都能通过本文获得有价值的信息和技巧。让我们一起探索Node.js的世界吧!
|
12天前
|
Web App开发 存储 JavaScript
深入浅出Node.js后端开发
【9月更文挑战第15天】在数字化浪潮中,Node.js作为一颗耀眼的星辰,为后端开发领域注入了活力与创新。本文将带你领略Node.js的魅力所在,探索其架构设计、性能优化及实战应用,让你在轻松愉快的氛围中掌握Node.js后端开发的精髓。
|
16天前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端开发
【9月更文挑战第11天】本文将带你走进Node.js的世界,了解其背后的运行机制和实际应用。我们将从基础概念出发,逐步深入到实战应用,最后通过代码示例巩固学习成果。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的视角和思考。
|
14天前
|
JavaScript 前端开发 API
深入浅出Node.js后端开发
【9月更文挑战第13天】本文将带你进入Node.js的世界,从基础概念到实际案例,深入浅出地探讨如何利用Node.js进行后端开发。通过本文的学习,你将了解Node.js的工作原理、核心模块、以及如何构建一个简单的Web应用。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
16天前
|
Web App开发 JavaScript NoSQL
深入浅出Node.js后端开发
在数字化时代的浪潮中,后端开发作为技术支柱之一,承载着数据处理和业务逻辑实现的重要任务。本文将通过浅显易懂的方式,带你走进Node.js的世界,从基础概念到实战应用,逐步揭开后端开发的神秘面纱。无论你是编程新手还是希望扩展技术栈的开发者,这篇文章都将为你提供有价值的指导和启示。让我们一起探索如何在不断变化的技术环境中,保持初心,寻找属于自己的方向,并成为希望在世界上看到的改变。
28 1
|
16天前
|
缓存 JavaScript 前端开发
深入浅出Node.js后端开发
【9月更文挑战第11天】本文将带你进入Node.js的世界,探索其背后的哲学、核心概念以及如何利用它来构建高效、可扩展的后端服务。无论你是前端开发者寻求全栈技能,还是后端开发者希望拓宽技术栈,这篇文章都将为你提供价值。我们将从基础讲起,逐步深入到实战应用,让你对Node.js有一个全面而深刻的理解。
26 2
|
21天前
|
存储 JavaScript 安全
深入浅出Node.js后端开发
【9月更文挑战第6天】在数字化浪潮中,后端开发作为技术架构的支柱,承载着数据存储、业务逻辑处理和用户交互等核心功能。Node.js,作为一个轻量级、高效的JavaScript运行环境,已经成为许多开发者的首选工具。本文将深入探讨Node.js的基础知识、实战应用以及面临的挑战,旨在为初学者和经验丰富的开发者提供一份全面的指南。从搭建开发环境到部署应用程序,我们将一步步揭示Node.js的魅力所在,同时也会触及性能优化和安全防护等高级话题。无论你是初涉后端开发的新手,还是希望深化对Node.js的理解,这篇文章都将是你的宝贵资源。