【总结系列】原生JS常用技巧,国内前端开发看什么

26 阅读3分钟

(二)数组相关


一、数组去重

数组去重是一个很常见的需求了,在网上也有很多去重的方法,在此介绍两个简洁的去重方法。

unique(arr){

if(!Array.isArray(arr))

throw new Error("arr is not a array")

return [...new Set(arr)] //或者 Array.from(new Set(arr))

}

上面就是利用了 Set 元素的唯一性。

但是,如果数组中存在内容相同的引用类型,那么这个方法就没有效果了。

比如:

let arr = [

{name:"jonas",age:18},

{name:"jonas",age:18},

{name:"jonas",age:18}

]

你会发现无论使用上面的方法还是网络上介绍的数组去重方法,都实现不了这种去重。所以,这时候自己写了一个方法用于解决这个问题(见下面)。

二、数组深度去重

对于基本数据类型的去重很简单,就是上面的一行代码就解决了,然而复杂的是引用类型。此处的引用类型主要是指对象和数组,所以,问题就变成两个:①去重内容相同的对象②去重内容相同的数组。

因为数组和对象的特征不同,存储数据的方式也不同,所以第一件事就是将数组和对象区分开来。

/**

  • 获取一个值的类型

  • @param target

  • @returns {string} 返回这个值的类型。如果是数组,则返回 "Array";是对象返回 "Object"

*/

function getType(target) {

return Object.prototype.toString.call(target).slice(8,-1)

}

接下来的问题就是判断两个对象中的内容是否完全一致了。

/**

  • 判断两个对象的内容是否完全一致,返回布尔值

  • @param a

  • @param b

  • @returns {boolean}

*/

function objUnique(a,b) {

//限制两个参数都是对象

if(getType(a) !== 'Object' && getType(b) !== 'Object')

return false

//获取其中一个对象的属性

let keyList = Object.keys(a)

for(let i = 0;i < keyList.length;i++){

//获取键名

let propName = keyList[i]

//处理嵌套

if(getType(a[propName]) === 'Object' && getType(b[propName]) === 'Object'){

objUnique(a[propName],b[propName])

}else if(getType(a[propName]) === 'Array' && getType(b[propName]) === 'Array'){

arrUnique(a[propName],b[propName])

}else if(a[propName] !== b[propName]){

//存在一对键值对不同,则表示两个对象不同

return false

}

}

return true

}

/**

  • 判断两个数组的内容是否完全一致,返回布尔值

  • @param a

  • @param b

  • @returns {boolean}

*/

function arrUnique(a, b) {

//限制两个参数都是数组

if(getType(a) !== 'Array' && getType(b) !== 'Array')

return false

//如果长度不等,则两个数组不可能相同

if(a.length !== b.length)

return false

//处理嵌套

for(let i = 0;i < a.length;i++){

if(getType(a[i]) === 'Object' && getType(b[i]) === 'Object'){

objUnique(a[i],b[i])

}else if(getType(a[i]) === 'Array' && getType(b[i]) === 'Array'){

arrUnique(a[i],b[i])

}else if(a[i] !== b[i]){

//存在一个元素不同,则表示两个数组不同

return false

}

}

return true

}

整合:

/**

  • 数组深度去重

  • @param arr

  • @returns {null|*[]}

*/

function unique(arr) {

//处理异常参数

if(getType(arr) !== 'Array')

throw new Error("arr is not a Array.")

//基本数据类型容器

let commonList = []

//对象收纳容器

let objList = []

//数组收纳容器

let arrList = []

//数据分类

arr.forEach(item => {

if(getType(item) === 'Object'){

objList.push(item)

}else if(getType(item) === 'Array'){

arrList.push(item)

}else{

commonList.push(item)

}

})

//基本数据类型去重

commonList = Array.from(new Set(commonList))

//对象收纳容器去重

for(let i = 0;i < objList.length;i++){

for(let j = i + 1;j < objList.length;j++){

if(objUnique(objList[i],objList[j])){

objList.splice(j,1)

j--

}

}

}

//数组收纳容器去重

for(let i = 0;i < arrList.length;i++){

for(let j = i + 1;j < arrList.length;j++){

if(arrUnique(arrList[i],arrList[j])){

arrList.splice(j,1)

j--

}

}

}

//合并收纳容器

return [...commonList,...objList,...arrList]

}

三、数组的并集,交集,差集

公共代码:

let arr1 = [1, 2, 3]

let arr2 = [4, 3, 2]

①并集

let arr = [...new Set([...arr1,...arr2])]

②交集

let arr = arr1.filter(x => arr2.includes(x))

③差集

let arr = arr1.filter(x => !arr2.includes(x))

四、取数组中的最大值与最小值

/**

  • 取数组中的最大值与最小值,忽略非数值元素和NaN

  • @param arr

  • @return {{min: *, max: *}|null}

*/

function minAndMax(arr) {

//规范类型

function getType(obj) {

return Object.prototype.toString.call(obj).slice(8,-1)

}

if(getType(arr) !== "Array")

throw new Error("arr is not array")

let min

let max

let flag = 0

for(let i = 0;i < arr.length;i++){

let current = arr[i]

//剔除非法数据

if(getType(current) !== "Number" || Number.isNaN(current)){

continue

}

if(!flag){

min = current

max = current

flag++

}

if(current > max)

max = current

if(current < min)

min = current

}

return {min,max}

}

五、数组的扁平化

扁平化,就是将多维数组转换为一维数组。

ES6 中有提供了一个方法用于扁平化:

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

let result = arr.flat(Infinity) //参数代表扁平层数,默认为1

(三)对象相关


一、对象或数组的深拷贝

JSON.parse(JSON.stringify(obj))

(四)数据类型相关


一、准确检测数据类型

无论是 typeof 还是 instanceof ,都无法很好的准确的检测一个未知对象的数据类型。所以还是手写了一个方法:

/**

  • 检测数据类型

  • @param obj 待检测对象

  • @returns {string} 返回具体的类型(首字母大写)

*/

function checkType(obj) {

return Object.prototype.toString.call(obj).slice(8,-1)

}

  • 如果是对象,则返回 Object;

ajax

1)ajax请求的原理/ 手写一个ajax请求? 2)readyState? 3)ajax异步与同步的区别? 4)ajax传递中文用什么方法?

ajax.PNG

前12.PNG

开源分享:docs.qq.com/doc/DSmRnRG…