js操作笔记

个人常用操作

对象数组去重

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.xxxundefined[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.slicearguments对象转换成一个数组。
箭头函数中没有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))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值