个人常用操作
对象数组去重
noRepeatObjectArr(arr, attribute) {
// 对象数组去重,attribute为去重的属性名
const map = new Map()
for (let item of arr) {
if (item[attribute] && !map.has(item[attribute])) {
map.set(item[attribute], item)
}
}
return [...map.values()]
}
多条件多值搜索
/**
* 多条件多数据筛选 来源github
* @param {array} arr 筛选的数组
* @param {object} filters 筛选的字段和值,对象属性名为字段名 属性值为搜索值
* name:['katsuki', 'xxx'],
* age:['18', '20']
*/
export function multiFilter(array: any, filters: any) {
const filterKeys = Object.keys(filters);
// filters all elements passing the criteria
return array.filter((item: any) => {
// dynamically validate all filter criteria
return filterKeys.every((key) => {
if (!filters[key].length) return true;
return filters[key].includes(item[key]) || item[key].includes(filters[key]);
});
});
}
千分位数字
/**
* 将值转换成带千分位的数字
* @param value 需要转换的值
* @returns 带千分位符号的数字
*/
thousandthProp(value) {
let innerText = ""
if (!value) {
innerText = ""
} else {
if (parseFloat(value).toLocaleString() === "NaN") {
innerText = value
} else {
innerText = parseFloat(value).toLocaleString()
}
}
return innerText
},
获取url的search内容
const getURLParameters = (url) =>
(url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
(prevRes, v) => ((prevRes[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), prevRes),
{}
)
console.log('test', getURLParameters('http://katsuki.com?name=katsuki&age=18'))
js return 返回结果是最后一个值,因此
return prevRes[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), prevRes
相当于
prevRes[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1))
return prevRes
判断值是否为数组
1.Array.isArray()
2.arr instanceof Array
3.
function isArray(value){
return Object.prototype.toString.call(value) === "[object Array]"
}
undefined null 0 空字符串 判断
if(value === undefined) {}
if(value === null) {}
if(value === '') {}
if(value === 0 || !value) {}
可选链(optional chaining)
obj?.prop
:访问不知道是否存在的obj
的静态属性
const obj = null
console.log(obj?.name) // undefined
obj?.[expr]
:访问不知道是否存在的obj
的动态属性或数组项
const obj= null
const katsuki = 'name'
console.log(obj?.[katsuki]) // undefined
const array = null
console.log(array?.[0]) // undefined
obj?.(...args)
:执行不知道是否存在的obj
的方法
const katsuki = null
console.log(katsuki?.name) // undefined
案列:undefined.xxx
、undefined[0]
会报错,需要做好判断
const objLess = {
company: 'key',
}
const objMore = {
company: 'fw',
product: { name: 'katsuki' },
msg: [{ age: 18 }, { age: 20 }],
}
function getProduct(obj) {
if (obj.product != null) {
return obj.product.name
}
return obj.product?.name
}
console.log('objLess product', getProduct(objLess))
console.log('objMore product', getProduct(objMore))
function getAge(obj) {
if (obj.ageMsg && obj.ageMsg.length > 0) {
return obj.ageMsg[0].age
}
// 等价于上面代码
return obj.ageMsg?.[0].age
}
console.log('objLess age', getAge(objLess))
console.log('objMore age', getAge(objMore))
双问号处理undefined null
const noVal = undefined
const name = 'katsuki'
console.log(noValue ?? 'wryyyyy') // wryyyyy
console.log(value ?? 'wryyyyy') // katsuki
// 左边为undefined,赋值wryyyyy
obj.product?.name ?? 'wryyyyy'
Array.from(es6)
用于遍历只取少部分返回,替代map方式
const katsukiArr = [
{ name: "katsuki", age: 18, word: 'wryyyy' },
{ name: "kasami", age: 19, word: '無駄無駄' },
]
const arr1 = Array.from(katsukiArr, ({ name }) => name)
const arr2 = Array.from(katsukiArr, ({ name, word }) => { return { name, word } })
console.log(arr1)
console.log(arr2)
---------------------手动分割---------------------
检查对象中是否存在某个属性
in
:查自身及原型链
hasOwnProperty
:查自身
Object.prototype.age = 18
const obj = {
"name" : "katsuki",
}
console.log("name" in obj); // true
console.log('age' in obj) // true
console.log(obj.hasOwnProperty("name")); // true
console.log(obj.hasOwnProperty('age')) // false
console.log(obj["name"]) // katsuki
函数缓存
已经做过的事情结果先暂时存起来,下次再做同样的事情,不用再重新去做,只要把之前的存的结果拿出来用即可
const memorize = function(fn) {
const cache = {}
return function(...args) {
const _args = JSON.stringify(args)
return cache[_args] || (cache[_args] = fn.apply(fn, args))
}
}
const add = function(a, b) {
console.log('缓存开始')
return a + b
}
const adder = memorize(add)
console.log(adder(10, 8)) // 输出结果: 开始缓存 18
console.log(adder(10, 8)) // 输出结果: 18
console.log(adder(8, 10)) // 输出结果: 开始缓存 18
不可更改对象(地址及值)
1.const
不允许改变对象或数组的引用,但可以改变其值。
2.Object.freeze()
忽略对象或数组的值更改
const constObj = Object.freeze({
NAME: 'katsuki'
})
constObj.NAME = 'unchange' // 忽略
constObj = {
NAME: 'kasami'
} // 这将抛出TypeError
Object.seal()
方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。
深冻结对象
未深冻结
let person = {
name: 'katsuki',
innerPerson: {
name: 'kasami',
},
}
Object.freeze(person)
person.innerPerson.name = '2333' // 能更改
console.log(person)
深冻结
function deepFreeze(object) {
let propNames = Object.getOwnPropertyNames(object) // array
for (let name of propNames) {
let value = object[name]
object[name] = value && typeof value === 'object' ? deepFreeze(value) : value
}
return Object.freeze(object)
}
let person = {
name: 'katsuki',
innerPerson: {
name: 'kasami',
},
}
deepFreeze(person)
person.innerPerson.name = '2333' // 不能更改
console.log(person)
数组排序
Array.sort
方法会改变原数组,若不想改变原数组进行排序,需要拷贝数组,不共用地址
const originArr = ['katsuki', 18, 996, 77, 'kasami']
const sortArr1 = originArr.slice().sort()
const sortArr2 = [...originArr].sort() // es6
Array.sort(compareFn)
,传入比较函数进行排序
数字数组排序
const arr = [77, 18, 39]
arr.sort(compare)
function compare(a, b) {
if(a > b) return 1 // 大于0 b在a前
if(b > a) return -1 // 小于0 a在b前
return 0 // 等于0 位置不变
}
字符串数组排序
String.localeCompare()
['katsuki', 'chan', 'kasami', 'wryyyyy'].sort((a, b) => a.localeCompare(b))
对象数组排序
const arr = [
{ name: 'katsuki', company: 'fw' },
{ name: 'summer pocket', company: 'key' },
{ name: 'pokemon', company: 'gf' },
{ name: 'kasami', company: 'fw' },
]
const compare = (a, b) => {
// 字符串比较统一转大写或小写
const nameA = a.name.toUpperCase()
const nameB = b.name.toUpperCase()
let compareNum = 0
if(nameA > nameB) {
compareNum = 1
} else if(nameA < nameB) {
compareNum = -1
}
return compareNum // compareNum * -1 倒序
}
arr.sort(compare)
动态排序函数
const arr = [
{ name: 'katsuki', company: 'fw', year: 18 },
{ name: 'summer pocket', company: 'key', year: 1 },
{ name: 'pokemon', company: 'gf', year: 20 },
{ name: 'kasami', company: 'fw', year: 19 },
]
const compareValues = (key, order = 'asc') => {
return function innerSort(a, b) {
console.log('a', a)
console.log('b', b)
// 检查对象中是否含义该属性名
if (!Object.prototype.hasOwnProperty.call(a, key) || !Object.prototype.hasOwnProperty.call(b, key)) return 0
// 字符串或数字的比较
const valueA = typeof a[key] === 'string' ? a[key].toUpperCase() : a[key]
const valueB = typeof b[key] === 'string' ? b[key].toUpperCase() : b[key]
let compareNum = 0
if (valueA > valueB) {
compareNum = 1
} else if (valueB > valueA) {
compareNum = -1
}
return order === 'desc' ? compareNum * -1 : compareNum
}
}
arr.sort(compareValues('year'))
使用Object.prototype.hasOwnProperty.call(a, key)
而不使用a.hasOwnProperty(key)
原因:Do not access Object.prototype method ‘hasOwnProperty’ from target object
对象及数组的深拷贝
一层拷贝
只改变最外层引用数据类型
地址
对象一层拷贝
let obj1 = { name: 'katsuki'}
let obj2 = Object.assign({}, obj1)
let obj3 = { ...obj1 }
let obj4 = jQuery.extend({}, obj1)
数组一层拷贝
let arr1 = ['無駄無駄', '貧弱貧弱', 'wryyyyy']
let arr2 = arr1.slice(0)
let arr3 = [].concat(arr1)
{ one: 'aaa', two: { inner: 'bbb' }, three: [ a, b ] }
,这种嵌套引用数据类型
的使用一层拷贝,嵌套部分仍然共用地址,数组同理
深拷贝
JSON
:正则表达式
、函数
类型等无法进行深拷贝
let obj1 = { name: 'katsuki'}
let obj2 = JSON.parse(JSON.stringify(obj1))
递归:深复制对象
及数组
function deepClone(obj) {
const newObj = obj.constructor === Array ? [] : {} // 判断复制的目标是数组还是对象
for (let keys in obj) {
// 遍历目标
if (obj.hasOwnProperty(keys)) {
if (obj[keys] && typeof obj[keys] === 'object') {
// 值是对象,递归
newObj[keys] = obj[keys].constructor === Array ? [] : {}
newObj[keys] = deepClone(obj[keys])
} else {
// 不是,就直接赋值
newObj[keys] = obj[keys]
}
}
}
return newObj
}
第三方库lodash.js
,真香
_.cloneDeep(value)
对象比较
思路同对象深复制,需要递归比较相同属性的值相同
第三方库lodash.js
,真香
_.isEqual(object, object)
Array
重复字符
let a = Array(18).join(0)
// ES6
let b = "0".repeat(18)
清空数组
const arr = ['katsuki', 'wryyyyy']
arr.length = 0
console.log(arr) // []
填充
const arr = new Array(18).fill(0) // [0, ..., 0] 18个零
类数组转化为数组
使用Array.prototype.slice
将arguments
对象转换成一个数组。
箭头函数中没有arguments对象
Array.prototype.slice.call(arrayLike)
Array.from(arrayLike) // es6
Object
Object.keys
返回一个给定对象自身可枚举属性的键数组
const obj = { name: 'katsuki', age : 18 }
let keys = Object.keys(person)// ["name", "age"]
Object.values
返回一个给定对象自身可枚举属性的值数组
const obj = { name: 'katsuki', age : 18 }
let keys = Object.keys(values)// ["katsuki", 18]
Object.entries
返回一个给定对象自身可枚举属性的键值对数组
const obj = { name: 'katsuki', age : 18 }
console.log(Object.entries(obj)) // [['name', 'katsuki'], ['age', 18]]
const arr = ['無駄無駄', '貧弱貧弱']
console.log(Object.entries(arr)) // [['0', '無駄無駄'], ['1', '貧弱貧弱']]
const arr2 = ['無駄無駄', '貧弱貧弱', { world: 'ざワールド時お止まれ!' }]
console.log(Object.entries(arr)) // [['0', '無駄無駄'], ['1', '貧弱貧弱'], ['2', { world: 'ざワールド時お止まれ!' }]]
const str = '無駄無駄'
console.dir(Object.entries(str)) // [['0', '無'], ['1', '駄'], ['2', '無'], ['3', '駄']]
关闭window.open打开页面
cloesWin = () => {
const browserName = navigator.appName
if (browserName === 'Netscape') {
window.opener = 'whocares'
window.close()
} else if (browserName === 'Microsoft Internet Explorer') {
window.open(',’_parent’,')
window.close()
}
}
Map替代Switch
const KATSUKI = 1
const KASAMI = 2
const WRYYYY = 3
const { code } = this.state
switch (code) {
case KATSUKI:
katsukiFun()
break
case KASAMI:
kasamiFun()
break
case WRYYYY:
wryyyyFun()
break
default:
break
}
// Map方式
const map = new Map([
[KATSUKI, katsukiFun],
[KASAMI, kasamiFun],
[WRYYYY, wryyyyFun],
])
const map = scopeMap.get(code)
map && map()
位运算
!!
将数字转为布尔值
console.log(!!7); // true
console.log(!!0); // false
使用~
、>>
、<<
、>>>
、|
来取整
console.log(~~6.66) // 6
console.log(6.66 >> 0) // 6
console.log(6.66 << 0) // 6
console.log(6.66 | 0) // 6
console.log(6.66 >>> 0) // 6
^
判断符号是否相同
a = -1
b = 1
(a ^ b) >= 0; // true 相同; false 不相同
^
来检查数字是否不相等
if (a ^ 666) {...};
indexOf() 不需要再比较数字
const arr = [1, 2, 3];
// 存在,等效于 > -1
if (~arr.indexOf(1)) {}
// 不存在,等效于 === -1
!~arr.indexOf(1);
string
toString(16)
取随机字符串
substring()
的第二个参数控制取多少位 (最多可取13位)
Math.random().toString(16).substring(2, 15) // 13位字符串
URLSearchParams
便捷获取url参数
var urlSearch = "name=katsuki&age=18&name=dio"
var searchParams = new URLSearchParams(urlSearch)
for (let k of searchParams) {
console.log(k)
}
console.log(searchParams.has("name")) // true
console.log(searchParams.get("name")) // katsuki
console.log(searchParams.getAll("name")) // ["katsuki", "dio"]
console.log(searchParams.get("word")) // null
searchParams.append("word", "wryyyyy")
console.log(searchParams.toString()) // name=katsuki&age=18&name=dio&word=wryyyyy
searchParams.set("age", "17")
console.log(searchParams.toString()) // "name=katsuki&age=17&name=dio&word=wryyyyy"
searchParams.delete("word")
console.log(searchParams.toString()) // "name=katsuki&age=17&name=dio"
searchParams.set("name", "kasami")
console.log(searchParams.toString()) // "name=kasami&age=17"
模糊查询
const str = 'katsuki'
const regstr = ['', ...str, ''].join('.*')
const reg = new RegExp(regstr)
const filterData = data.filter((v) => reg.test(v.name))