介绍
JS数组对象字符串的一些处理方法
# JS常用特性
# 通过二元判断对象中是否存在的数据
- 可以通过二元表达式 判断对象中是否存在该数据 进行一些特殊判断操作
假设如果 succ对象中 存在confirm数据 则进行一些操作
?.
就算原数据没有 也不回报错 会返回undefined
而不是直接报错
if(succ?.confirm){
// 如果 succ对象中存在confirm数据 则进行一些操作
}
# 声明方法通过解构传参
- 疑问: 有时候我们会封装一些通用方法 通用方法如果需要传参过多 会导致非常难管理 有些参数我不想传 想用默认值 我们可不可以指定传参呢
- 解答: 我们可以给方法传入对象
Object
然后再声明的方法中解构对象 这样就可以实现我们 按需传值 而非传统的有序传参
// 声明一个通用方法
/**
* @example this.$addNull(array,name,id)
* @author 刘凯利
* @function 添加空的可选值 id为0
* @param {Object} obj 参数合集
* @param {Array} obj.array 要添加的数组
* @param {String} obj.id 渲染id
* @param {String} obj.name 名称
*/
export default function addNull (obj) {
// 解构传参的对象
const { array, id, name } = obj
... 方法干的事情
}
// 外部使用该方法
addNull({
// 传递array 参数
array: [2333,3333],
// 不想传id 直接传name
name: '不传id'
})
- 通过方法内 解构参数对象 实现按需传参的需求
# JS处理数组常用方法
- 记录常用的数组Array (opens new window)方法 通常我会把数组方法应用在数组对象就是常说的
JSON
对象 - Array (opens new window) 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。
# 查询数组对象中符合条件对象的索引
- 数组对象就是常说的
JSON
对象 在前端显示为[{},{},{},....]
- 我们可以通过findIndex() (opens new window) 循环查找符合条件的对象 findIndex() (opens new window)可以对自身进行遍历 遍历每个对象 查到符合条件的终端 并返回其索引值
findIndex()
找到匹配对象后就返回结果,不会继续遍历findIndex()
只适合删除单条JSON数据 或 进行快速查询索引 如果想实现批量过滤JSON数据 需要使用filter() (opens new window) 进行过滤
查询数组对象中 符合条件的对象 返回其索引
- 一个数组对象 获取 id 为 3 的索引
- 多个筛选条件可以使用二元逻辑运算符 (opens new window)
&&
等
const arry = [
{ id: '1', name: '张三' },
{ id: '2', name: '李四' },
{ id: '3', name: '王五' },
{ id: '4', name: '赵六' }
]
// 查找id为3的对象索引
const index = arry.findIndex((item) => item.id == '3');
console.info(index); // 返回值2
# 根据索引删除数组对象中的内容
- 使用splice() (opens new window) 根据指定索引删除数组对象的内容
- splice() (opens new window) 这个方法会修改原数组 他的返回值是被删掉的内容
arrayObject.splice(index,howmany,item1,.....,itemX)
参数 | 描述 |
---|---|
index | 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置(0 - 3)。 |
howmany | 必需。要删除的项目数量。如果设置为 0,则不会删除项目。 |
item1, ..., itemX | 可选。向数组添加的新项目。 |
删除数组对象中指定索引的对象
- 删除索引为1的对象
const arry = [
{ id: '1', name: '张三' },
{ id: '2', name: '李四' },
{ id: '3', name: '王五' },
{ id: '4', name: '赵六' }
]
const change = arry.splice(1,1); // 截取三个内容
// 删除后的原数组
console.log(arry) // (3) [{id: '1', name: '张三'}, {id: '3', name: '王五'}, {id: '4', name: '赵六'}]
// 删除掉的内容
console.log(change) // [{id: '2', name: '李四'}]
# 根据条件筛选过滤数组对象
- 通过filter() (opens new window) 过滤掉符合条件的数组对象(JSON) 并且返回一个新数组
- filter() (opens new window)不会修改原数组 会返回一个新数组
在数组对象中 筛选出num不为0的数据
- 多个筛选条件可以使用二元逻辑运算符 (opens new window)
&&
等
let arr = [
{
productId: 1,
productName: '电视机',
num: 20
}, {
productId: 2,
productName: '洗衣机',
num: 0
}, {
productId: 3,
productName: '冰箱',
num: 50
}, {
productId: 4,
productName: '空调',
num: 0
},
]
// 进行筛选
arr = arr.filter(item => {
return item.num !== 0 // num不等0的数据筛选出来
})
// 也可以进行简写
arr = arr.filter(item => item.num !== 0)
// 进行筛选 多条数据进行筛选
arr = arr.filter(item => {
return item.num !== 0 && item.productId !== 1 // num不为0的数据筛选和productId不为1的数据
})
console.log(arr)
// [{productId: 1, productName: '电视机', num: 20},{productId: 3, productName: '冰箱', num: 50}]
filter()
可以帮我们做很多事情 过滤相比splice()
删除 可以再循环中进行splice()
在循环中删除循环数组不可靠 因为他会修改原数组 循环的时候 会造成索引不对问题- 进行一些批量删除数据操作的时候
filter()
可以通过forEach
实现多条数据的删除 但是建议是通过唯一标识进行遍历删除 如该条数据的id
- 进行一些批量删除数据操作的时候
# json数据中去除对象特定字段并生成新数组
- 如果后端返回的数组对象(json数据)中的数据你想单独拎出来放到一个数组中 就需要通过map() (opens new window)遍历全部数据后 把该字段拿出来
- map() (opens new window)不会修改原数组 会返回一个新数组
// 假设这个是你要处理的该数组对象
const ret = res.data.data
// 把数组对象用map那出来
const rtx = ret.map(e => {
return e.real_img_src
})
// 这里就是你想要的数组内容
console.log(rtx)
- 取出后的数据
# 过滤掉数组的falsey假值
- falsey可以直译为假值,包含
false
,''
,""
,null
,undefined
与NAN
这几种数据类型。 - 通过filter() (opens new window) 进行过滤 把数组中每一项的值转换为
Boolean
用其判断是否为true
- Boolean (opens new window) 作为一种数据类型 同时也是构造函数 可以对非假值进行为
true
的转换
- Boolean (opens new window) 作为一种数据类型 同时也是构造函数 可以对非假值进行为
let arr = [12, null, 0, 'xyz', null, -25, NaN, '', undefined, 0.5, false];
// 通过转换Boolean的方式 进行假值的筛选
let filterArray = arr.filter(Boolean);
// filterArray = [12, "xyz", -25, 0.5]
# JS处理对象常用方法
- Object (opens new window) 是 JavaScript 的一种 数据类型 (opens new window) 。它用于存储各种键值集合和更复杂的实体。Objects 可以通过
Object()
构造函数或者使用 对象字面量 (opens new window) 的方式创建
# 清空对象里的内容
- 把对象中的所有数据 变为空值
''
通过Object.keys() (opens new window) 会返回一个表示给定对象的所有可枚举属性的字符串数组- 枚举是我们自己定义的一个集合, 当我们定义了一个枚举类型的时候,我们声明它里面有几个元素,在我们使用这个枚举的时候,我们只能够使用它有的元素,没有的元素我们是无法使用,系统就会报错!
- 通常我们可以把JS的对象理解为一个枚举、集合
- Object.keys() (opens new window) 方法会修改源原对象 需要用
let
声明变量
let obj= {
name: '刘凯利',
old: 21
}
// 清空obj对象
Object.keys(obj).forEach(key => {
obj[key] = ''
})
// Object.keys会修改原对象哦
console.log(obj) // {name: '', old: ''}
# Object.keys()
快速复制 不存在的key不复制 (深拷贝)
- 通过Object.keys() (opens new window) 方法我们可以实现 两个对象的赋值 并且不存在的key不复制 它属于(深拷贝)的概念 当原对象的值修改后 拷贝的值也会变
- Object.keys() (opens new window) 方法会修改源原对象 需要用
let
声明变量
// 要拷贝的对象
let addDeptModel = {
editType: '5号',
id: '123',
pid: '',
parentName: '',
manager: '',
}
// 拷贝到的对象
// 这个时候只拷贝存在的key 其他的key不拷贝
let DeptModel = {
editType: '',
id: '',
pid: '',
}
// 声明一个拷贝方法
const objCoppy = (obj1, obj2) => {
Object.keys(obj2).forEach(key => {
obj2[key] = obj1[key]
})
}
// 进行拷贝
objCoppy(addDeptModel, DeptModel)
console.log(DeptModel); // {editType: '5号', id: '123', pid: ''}
# object.assign()
合并对象中的属性(浅拷贝)
Object.assign() 方法可以把可枚举和自有的对象 合并到目标对象 返回合并后的目标对象
不会修改合并储存对象里面的原数据 只是继续添加数据
object.assign()
有n个参数 但是参数1是 指定储存合并的对象- 参数1是 指定储存合并的对象( 自己可以拥有原数据 并不会覆盖原数据 )
- 参数2 需要合并的对象
- 参数3 需要合并的对象
.....
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
// 合并储存的对象
const target = {
a: 1
};
// 需要合并的对象1
const source1 = {
b: 2
};
// 需要合并的对象2
const source2 = {
c: 3
}
// 进行对象合并
Object.assign(target, source1, source2)
console.log(target) // {a: 1, b: 2, c: 3}
# object.hasOwnProperty()
对象中判断指定键(属性名)是否存在
- 我们想判断一个字段是是否在对象中存在 需要用到hasOwnProperty() (opens new window)方法检测是否有指定的键
<span v-if="data.hasOwnProperty('children')" />
- 这样就可以判断
data
对象中 是否包含children
键(属性名)
其他例子
const object1 = {};
object1.property1 = 42;
console.log(object1.hasOwnProperty('property1'));
// expected output: true
console.log(object1.hasOwnProperty('toString'));
// expected output: false
# 进阶
- 如果你开启了eslint 直接使用hasOwnProperty() (opens new window) 会提示报错
- 这个错误的解释是
- 对象可以具有属性,这些属性可以将
Object.prototype
的内建函数隐藏,可能导致意外行为或拒绝服务安全漏洞。例如,web 服务器解析来自客户机的 JSON 输入并直接在结果对象上调用hasOwnProperty
是不安全的,因为恶意客户机可能发送一个JSON值,如{"hasOwnProperty": 1}
,并导致服务器崩溃。
- 对象可以具有属性,这些属性可以将
- 解决方案
- 使用
Object.prototype
调用这些方法
- 使用
// 报错写法
childNodes[j].hasOwnProperty('children')
// 正确规范写法
Object.prototype.hasOwnProperty.call(childNodes[j], 'children')
# 数组对象中获取指定键(属性名) 并组成新数组
- 如果后端返回的数组对象中的数据你想单独拎出来放到一个数组中 就需要通过map (opens new window)来把该字段拿出来
- map (opens new window) 方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。如果没有特殊情况 会全部遍历后结束
// 假设这个是你要处理的该数组对象
const ret = res.data.data
// 把数组对象用map那出来
const rtx = ret.map(e => {
return e.real_img_src
})
// 这里就是你想要的数组内容
console.log(rtx)
- 取出后的数据
# 判断两组对象是否一致
- 在JS中
Object
对象是一种复杂数据类型 和普通数据类型不同的是Object
就算里面的key: value
值一样 那么用==
和===
比对也不一样 因为Object
类型实际上比对的是堆 而非值对象里的值
# key位置不变的对比
- 只比对两组
Object
的key: value
不比较顺序 如果key
的顺序变了 将会视为Object
被改变- 第一种: 把对象转换成
JSON
字符串 进行比对 - 第二种:
ES6
提供的的对象方法Object.entries() (opens new window) 可以把一个对象 转换成数组{key: value,{},...} 转换 [['key', 'value'],[],...]
然后再通过toString() (opens new window)转换成字符串 最后实现比对对象 (实际上转了半天变成了 比对字符串)
- 第一种: 把对象转换成
// 方式1 把两组对象转换成JSON进行比对
JSON.stringify(object1) === JSON.stringify(object2)
// 方式2 把两组对象转换成
Object.entries(object1).toString() === Object.entries(object2).toString()
# key位置会变的比对
- 以上的方法只适合
key
的位置不变 非常依赖key
的顺序 因为本质上都是通过各种手段 把对象转换成各种字符串 (JSON
和JS
字符串) 一旦key
的位置变了 那么转换后的字符串肯定也会发生变化 - 通过递归方法 可以实现不受
key
的顺序 只比较value
的值 而且支持嵌套对象
// 判断数据类型
const getDataType = data => {
const temp = Object.prototype.toString.call(data);
const type = temp.match(/\b\w+\b/g);
return (type.length < 2) ? 'Undefined' : type[1];
}
/**
*
* @param {*} source 传入对象比较A
* @param {*} comparison 传入对象比较B
* @returns false为一致 true为不一致
*/
export default function isObjectChanged (source, comparison) {
// 由于'Object','Array'都属于可遍历的数据类型,所以我们提前定义好判断方法,方便调用
const iterable = (data) => ['Object', 'Array'].includes(getDataType(data));
// 如果源数据不是可遍历数据,直接抛错,主要用于判断首次传入的值是否符合判断判断标准。
if (!iterable(source)) {
throw new Error(`source should be a Object or Array , but got ${getDataType(source)}`);
}
// 如果数据类型不一致,说明数据已经发生变化,可以直接return结果
if (getDataType(source) !== getDataType(comparison)) {
return true;
}
// 提取源数据的所有属性名
const sourceKeys = Object.keys(source);
// 将对比数据合并到源数据,并提取所有属性名。
// 在这里进行对象合并,首先是要保证 对比数据>=源数据,好处一:后边遍历的遍历过程就不用做缺省判断了。
const comparisonKeys = Object.keys({ ...source, ...comparison });
// 好处二:如果属性数量不一致说明数据必然发生了变化,可以直接return结果
if (sourceKeys.length !== comparisonKeys.length) {
return true;
}
// 这里遍历使用some,some的特性一旦找到符合条件的值,则会立即return,不会进行无意义的遍历。完美符合我们当前的需求
return comparisonKeys.some(key => {
// 如果源数据属于可遍历数据类型,则递归调用
if (iterable(source[key])) {
return isObjectChanged(source[key], comparison[key]);
} else {
return source[key] !== comparison[key];
}
})
}
- 封装后 我们导入使用
import isObjectChanged from './isObjectChanged.js'
// 对象1
let obj = {
name: '小刘',
hobby: ['敲代码'],
old: 12,
talk: {
first: 'hello'
}
}
// 对象2
let obj2 = {
name: '小刘',
hobby: ['敲代码'],
old: 12,
talk: {
first: 'hello'
}
}
console.log(isObjectChanged(obj, obj2)) // false为一致 true为不一致
# 通过解构 删除对象中的key
- 之前删除对象的key都是使用delete](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/delete) 操作符 进行删除的 通过解构也可实现删除操作 (解构实际上是进行了浅拷贝 对原对象不进行修改)
let obj = { x: 45, y: 72, z: 68, p: 98 };
// delete 操作符进行删除
delete obj.x;
delete obj.p;
console.log(obj); // {y: 72, z: 68}
// 解构方式进行删除
// 把x p 解构出来(解构出来也可以单独调用)
// 那么剩下的就是y z 进行了一次浅拷贝 不会影响到原来的对象
let { x, p, ...newObj } = obj;
console.log(newObj); // {y: 72, z: 68}
# JS处理字串符常用方法
- String (opens new window) 全局对象是一个用于字符串或一个字符序列的构造函数。
# 替换对象的key
- 如果后端返回的数据 不是你需要的key 这个时候你就可以替换key 用你想用key
- replace() (opens new window) 只支持替换字符串 数组或其他类型的会报错 但是你可以把他转换成JSON字符串JSON.stringify() (opens new window) 使用的时候再通过JSON.parse() (opens new window) 解析JSON 字符串 即可完成替换操作
举例使用
- 这个时候 你想把
id
替换成valueregion_name
替换成text 需要用到replace
这个方法 通过正则来替换key 替换成自己想要的
// 接收数据
const ret = res.data.data
// 处理数据b
const changeObject = JSON.parse(JSON.stringify(ret).replace(/region_name/g, "text").replace(/id/g, "value"));
- 这样数据就处理好啦
封装成一个方法
/**
* 用户替换键名的方法
* @param {Object} obj 全部数据
* @param {Array} obj.data 需要修改的数据集合
* @param {*} obj.oldKeyRules 修改替换的正则表达式
* @param {String} obj.newKdy 需要替换的key名
* @returns
*/
export default function replaceKey (obj) {
const { data, oldKeyRules, newKdy } = obj
const changeData = JSON.parse(JSON.stringify(data).replace(oldKeyRules, newKdy));
return changeData
}
# 最佳实现方法
- 利用
replace()
实现key的替换简单方便 但是很尴尬的是 只要符合替换条件 不管是不是属性名 他都会进行替换 所以我们要用更准确的方法 利用递归实现属性名的替换
/**
* 用户替换键名的方法
* @param {Array} obj 要替换的数据
* @param {Array} typeArr 替换的规则
* @returns
*/
let copyTrans = function (obj, typeArr) {
let result;
let toString = Object.prototype.toString;
if (toString.call(obj) === '[object Array]') {
result = [];
for (let i = 0; i < obj.length; i++) {
result[i] = copyTrans(obj[i], arguments[1])
}
} else if (toString.call(obj) === '[object Object]') {
result = {};
for (let _key in obj) {
if (obj.hasOwnProperty(_key)) {
let flag = 0, _value = null;
for (let j = 0; j < arguments[1].length; j++) {
if (arguments[1][j].key === _key) {
flag = 1;
_value = arguments[1][j].value
}
}
if (flag)
result[_value] = copyTrans(obj[_key], arguments[1])
else
result[_key] = copyTrans(obj[_key], arguments[1])
}
}
} else {
return obj
}
return result
}
export default copyTrans
- 使用该替换属性名的递归方法
import copyTrans from './uits/copyTrans'
// 需要替换的数据
const data = [
{
Name: "test1Name",
type: "test",
other: '321'
},
{
Name: "test2",
type: "model2"
}
]
// 修改属性名 key是原属性名 value是替换后的属性名 data是需要替换操作的数据
// copyTrans(需要替换的数据Array, 替换的规则Array)
const ret = copyTrans(data, [{ key: "Name", value: "title" }, { key: "type", value: "demo" }])
console.log(ret)
//[{title: 'test1Name', demo: 'test', other: '321'},{title: 'test2', demo: 'model2'}]
# 一些功能性的常用方法
- 记录一些功能性 可扩展性 具有举一反三的常用方法
# 过滤数组中非图片后缀的内容
- 我们在渲染一些图片集合中 会碰到一些非图片的字段 我们筛选掉这些非图片后缀的内容 让渲染
<img>
的时候 不出现裂开的图片- 之前记录了 json数据中去除对象特定字段并生成新数组 通过
map
配合图片的正则表达式 可以筛选出图片 但是map
如果不return
会自动插入undefined
所以最后用filter
筛选掉map生成的数组中undefined
的内容
- 之前记录了 json数据中去除对象特定字段并生成新数组 通过
// 一个简单的图片集合 里面包含了图片的内容
const attachmentList = [
{
id: 1,
name: '第一张',
path: 'https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/202207312128781.jpg'
},
{
id: 2,
name: '第二张',
path: 'https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/202207312128781.jpg'
},
{
id: 3,
name: '第三张',
path: 'https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/demo.pdf'
}
]
// 筛选图片的正则内容规则
const suffix = `(bmp|jpg|png|tif|gif|pcx|tga|exif|fpx|svg|psd|cdr|pcd|dxf|ufo|eps|ai|raw|WMF|webp|jpeg)`
// 筛选图片正则
const regular = new RegExp(`.*\.${suffix}`)
// map筛选 让json格式的图片集合变成数组的格式
let imageData = attachmentList.map(e => {
// 判断是否存在非图片的内容不return
if (regular.test(e.path)) {
return e.path
}
})
// 如果不return map会自动插入undefined 用filter筛选掉undefined的内容 把筛选后的图片集合进行赋值
imageData = imageData.filter(item => {
// 筛选掉undefined 和 null的数据
return item !== undefined && item !== null
})
- 最后 筛选完毕的数据是这样子的