2.2 javascript开发技巧
2.2.1 数组操作
1、使用 includes 简化 if 判断
Bad Code
if(ticketCode === '01' || ticketCode === '02' || ticketCode === '03') { }
Good Code
if(['01', '02', '03'].includes(ticketCode)) { } // 下面这种也可以 if('01,02,03'.includes(ticketCode)) { }
2、使用every判断是否所有项都满足条件
Bad Code
let arr = [{checked: true}, {checked: false}, {checked: true}, {checked: false}] let isAllchecked = true // 是否全部选中 arr.forEach(item => { if(!item.checked) { isAllchecked = false } })
Good Code
数组的every方法只要有一项不满足条件就会返回false,不会再继续遍历
let arr = [{checked: true}, {checked: false}, {checked: true}, {checked: false}] let isAllchecked = arr.every(item => { console.log('item', item) return !!item.checked })
3、使用some判断是否有一项满足条件
Bad Code
let arr = [{checked: false}, {checked: true}, {checked: false}, {checked: true}] let isHaveChecked = false // 是否有选中的 arr.forEach(item => { if(item.checked) { isHaveChecked = true } })
Good Code
数组的some方法只要有一项满足条件就会返回true,不会再继续遍历
let arr = [{checked: false}, {checked: true}, {checked: false}, {checked: true}] let isHaveChecked = arr.some(item => { console.log('item', item) return !!item.checked })
4、使用reduce遍历数组处理求和等复杂逻辑
reduce() 方法对数组中的每个元素按序执行一个由您提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值 。
第一次执行回调函数时,不存在“上一次的计算结果”。如果需要回调函数从数组索引为 0 的元素开始执行,则需要传递初始值。否则,数组索引为 0 的元素将被作为初始值 initialValue,迭代器将从第二个元素开始执行(索引为 1 而不是 0)。
语法
reduce(callbackFn) reduce(callbackFn, initialValue)
参数
- callbackFn
一个“reducer”函数,包含四个参数:
previousValue:上一次调用 callbackFn 时的返回值。在第一次调用时,若指定了初始值 initialValue,其值则为 initialValue,否则为数组索引为 0 的元素 array[0]。
currentValue:数组中正在处理的元素。在第一次调用时,若指定了初始值 initialValue,其值则为数组索引为 0 的元素 array[0],否则为 array[1]。currentIndex:数组中正在处理的元素的索引。若指定了初始值 initialValue,则起始索引号为 0,否则从索引 1 起始。array:用于遍历的数组。
- initialValue 可选
作为第一次调用 callback 函数时参数 previousValue 的值。若指定了初始值 initialValue,则 currentValue 则将使用数组第一个元素;否则 previousValue 将使用数组第一个元素,而 currentValue 将使用数组第二个元素。
返回值
使用“reducer”回调函数遍历整个数组后的结果。
示例
(1)计算数组中每个元素出现的次数
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'] let nameNum = names.reduce((pre,cur)=>{ if(cur in pre) { pre[cur]++ } else { pre[cur] = 1 } return pre }, {}) console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}
(2)数组去重
let arr = [1,2,3,4,4,1] let newArr = arr.reduce((pre,cur)=>{ if(!pre.includes(cur)){ return pre.concat(cur) }else{ return pre } },[]) console.log(newArr);// [1, 2, 3, 4] // 简便写法 let newArr = [...new Set(arr)] let newArr = Array.from(new Set(arr))
(3)将二维数组转化为一维
let arr = [[0, 1], [2, 3], [4, 5]] let newArr = arr.reduce((pre,cur) => { return pre.concat(cur) }, []) console.log(newArr); // [0, 1, 2, 3, 4, 5] // 简便写法 let newArr = arr.flat() // 拉平二维数组
(4)将多维数组转化为一维
let arr = [[0, 1], [2, 3], [4,[5,6,7]]] const newArr = function(arr){ return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[]) } console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]
2.2.2 对象操作
1、向对象有条件的添加属性
使用场景:
表单提交时针对个性化开关控制的必填参数可以通过该方式来添加到固定参数集合中。
const condition = true; const person = { id: 1, name: 'John Doe', ...(condition && { age: 16 }), }; // 如果 condition 为 false,JavaScript 会做这样的事情: const person = { id: 1, name: '前端小智', ...(false), }; // 展开 `false` 对对象没有影响 console.log(person); // { id: 1, name: 'John Doe' }
2、检查属性是否存在对象中
const example = {}; example.prop = 'exists'; // hasOwn 只会对直接属性返回 true:: Object.hasOwn(example, 'prop'); // returns true Object.hasOwn(example, 'toString'); // returns false Object.hasOwn(example, 'hasOwnProperty'); // returns false // in 会对直接或继承的属性返回 true: 'prop' in example; // returns true 'toString' in example; // returns true 'hasOwnProperty' in example; // returns true
3、使用Object.entries() 返回一个给定对象自身可枚举属性的键值对数组
const object1 = { a: 'somestring', b: 42 }; const arr = Object.entries(object1) //arr:[['a','somestring'],['b','42']] for (const [key, value] of arr) { console.log(`${key}: ${value}`); } // Expected output: // "a: somestring" // "b: 42"
4 、使用Object.fromEntries( ) 方法把键值对列表转换为一个对象
const entries = new Map([ ['foo', 'bar'], ['baz', 42] ]); const obj = Object.fromEntries(entries); console.log(obj); // Expected output: Object { foo: "bar", baz: 42 }
5、使用Object.freeze冻结对象(可在vue data定义非响应式变量使用)
const obj = { prop: 42 }; Object.freeze(obj); obj.prop = 33; // Throws an error in strict mode console.log(obj.prop); // Expected output: 42
2.2.3 字符串操作
1、字符串不满两位补零
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。
padStart()和padEnd()一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。
'x'.padStart(5, 'ab') // 'ababx' 'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' 'x'.padEnd(4, 'ab') // 'xaba'
如果原字符串的长度,等于或大于最大长度,则字符串补全不生效,返回原字符串。
'xxx'.padStart(2, 'ab') // 'xxx' 'xxx'.padEnd(2, 'ab') // 'xxx'
如果用来补全的字符串与原字符串,两者的长度之和超过了最大长度,则会截去超出位数的补全字符串。
'abc'.padStart(10, '0123456789') // '0123456abc'
如果省略第二个参数,默认使用空格补全长度。
'x'.padStart(4) // ' x' 'x'.padEnd(4) // 'x '
常用场景:
// 获取当前月份小于10前补0 let month = new Date().getMonth() +1 // 常规写法利用三木运算符处理 month = month < 10 ? '0' + month : month // 也可以利用pdaStart填充实现 month = String(month).padStart(2, '0') // 还可以按照以下方式实现 month = ('0' + month).slice(-2) console.log(month); // expected output: "01" // 银行卡号只显示后4位 const fullNumber = '2034399002125581'; const last4Digits = fullNumber.slice(-4); const maskedNumber = last4Digits.padStart(fullNumber.length, '*'); console.log(maskedNumber); // expected output: "************5581"
2、判断字符串前缀、后缀
判断字符串前缀、后缀不要一言不合就使用正则表达式:
const url = "https://bili98.cn"; const isHTTPS = /^https:\/\//.test(url); // true const fileName = "main.py"; const isPythonCode = /\.py$/.test(fileName); // true
推荐使用 String.prototype.startsWith 和 String.prototype.endsWith,语义性更好:
const url = "https://bili98.cn"; const isHTTPS = url.startsWith("https://") // true const fileName = "main.py"; const isPythonCode = fileName.endsWith(".py"); // true
3、使用replaceAll 方法替换所有匹配到的字符
ES2021新特性-替换一个字符串中的所有指定字符 replaceAll()方法的使用
在 ES2021 之前,要替换掉一个字符串中的所有指定字符,我们可以这么做:
const str = '2-4-6-8-10' const newStr = str.replace(/\-/g, '+') console.log(newStr) // 2+4+6+8+10
ES2021 则提出了 replaceAll 方法,并将其挂载在 String 的原型上,可以这么用:现在可以用String.prototype.replaceAll()替换全部字符串而不需要使用正则。
const str = '2-4-6-8-10' const newStr = str.replaceAll('-', '+') console.log(newStr) // 2+4+6+8+10