isEqual 仅比较实值的相等
js 中简单类型的比较是对具体值的比较;
而对于引用类型的比较,其比较的是引用值是否相等。
这里提供一种扩展方法,使得:
equal(1,1); equal(‘a’,’a’); 自然都返回为 true
equal({a:1},{a:1}) ; 也能返回为 true ; equal({a:1},{a:2}) 返回 false
// 获取复杂对象的类型
function getObjType(obj) {
return Object.prototype.toString.call(obj)
.slice(8, -1).toLowerCase();
}
// 对象是否为某一个类型
function isType(obj, type) {
return getObjType(obj) === type;
}
/**
* 仅比较值是否相等,不计较其内存地址是否同一个
* equal({a:1},{a:1}) 返回 true
* 这里不考虑函数的比较,直接执行默认的比较
*/
function isEqual(a, b) {
var typeOfA = typeof a;
var typeOfB = typeof b;
if (typeOfA !== typeOfB) {
return false;
}
if (typeOfA !== 'object') {
return a === b;
}
if (typeOfA === 'object') {
// 如果对象的具体类型不一致,直接返回
var objTypeA = getObjType(a);
if (objTypeA !== getObjType(a)) {
return false;
}
// 如果是数组类型
if (objTypeA === 'array') {
if (a.length !== b.length) {
return false
}
else {
for (var i = 0, len = a.length; i < len; i++) {
if (!isEqual(a[i], b[i])) {
return false;
}
}
return true;
}
}
// 如果是object类型
else if (objTypeA === 'object') {
for (var attr in a) {
if (!b.hasOwnProperty(attr)) {
return false
}
if (!isEqual(a[attr], b[attr])) {
return false;
}
}
}
// 如果是正则类型
else if (objTypeA === 'regexp') {
return a + '' === b + '';
}
// 如果是日期类型
else if (objTypeA === 'date') {
return +a == +b;
}
}
return true;
}
// 测试使用
console.log(isEqual({ a: { c: /a/, d: 1 } }, { a: { c: /a/, d: 1 } })) // true
console.log(isEqual([1, 2, 3], [1, 2, 3])) // true
console.log(isEqual('1', 1)) // false
console.log(isEqual(/a/, /a/)) // true
console.log(isEqual(new Date(), new Date())) // true
var fn = function () { }
console.log(isEqual(fn, fn)) // true
平行结构和树状结构互转
- 原数据
var originData = [
{ title: '标题1', id: '1', pid: '0' },
{ title: '标题1-1', id: '1-1', pid: '1' },
{ title: '标题1-2', id: '1-2', pid: '1' },
{ title: '标题2', id: '2', pid: '0' },
{ title: '标题2-1', id: '2-1', pid: '2' },
{ title: '标题2-2', id: '2-2', pid: '2' },
{ title: '标题2-1-1', id: '2-1-1', pid: '2-1' },
{ title: '标题2-2-1', id: '2-2-1', pid: '2-2' },
{ title: '标题2-2-2', id: '2-2-2', pid: '2-2' },
{ title: '标题2-2-2-1', id: '2-2-2-1', pid: '2-2-2' },
{ title: '标题2-2-2-2', id: '2-2-2-2', pid: '2-2-2' },
];
- 转换成树的结构的方法
默认用
children
连接子级,可通过传递第三个参数linkkey
的值改变
function toTree(arr, pid,linkKey='children') {
var treeArr = [];
var allTreeLeaf = arr.filter(item => item.pid === pid);
allTreeLeaf.forEach(tree => {
let _children = toTree(arr, tree.id)
if (_children.length) {
tree[linkKey] = _children;
}
treeArr.push(tree);
})
return treeArr;
}
// 使用
var formatTree = toTree(originData, '0');
console.log(formatTree)
- 再将树形的结构展平
注意,此处的参数
treeData
为引用关系,在展平的过程中,用到了delete
,所以会影响到原数据,如果不想影响到原数据,需先拷贝要展平的数据,然后传入拷贝的数据。
function flattenTree(treeData, linkKey) {
var result = [];
treeData.forEach(thrunk => {
if (thrunk[linkKey] && thrunk[linkKey].length) {
result = result.concat(flattenTree(thrunk.children, linkKey))
}
delete thrunk[linkKey]
result = result.concat(thrunk);
})
return result;
}
// 使用,先使用转变为树,又展平回去。
flattenTree(toTree(originData, '0'),'children');
展平多维数组
var arr = [1,[2,[3,[4,[5]]]]];
function flatten(arr, result = []) {
for (var i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
flatten(arr[i], result);
}
else {
result.push(arr[i])
}
}
return result;
}
console.log(flatten(arr)); // [1,2,3,4,5]
深拷贝
TODO