lodash源码
import isFlattenable from './isFlattenable.js'
/**
* The base implementation of `flatten` with support for restricting flattening.
*
* @private
* @param {Array} array The array to flatten.
* @param {number} depth The maximum recursion depth.
* @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
* @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
* @param {Array} [result=[]] The initial result value.
* @returns {Array} Returns the new flattened array.
*/
function baseFlatten(array, depth, predicate, isStrict, result) {
predicate || (predicate = isFlattenable)
result || (result = [])
if (array == null) {
return result
}
for (const value of array) {
if (depth > 0 && predicate(value)) {
if (depth > 1) {
// Recursively flatten arrays (susceptible to call stack limits).
baseFlatten(value, depth - 1, predicate, isStrict, result)
} else {
result.push(...value)
}
} else if (!isStrict) {
result[result.length] = value
}
}
return result
}
export default baseFlatten
lodash是通过递归加数组打散来完成数组扁平化的。这种方法优点是能控制数组最多扁平化几层。
./isFlattenable.js用来检测是否是数组或类数组:
import isArguments from '../isArguments.js'
/** Built-in value reference. */
const spreadableSymbol = Symbol.isConcatSpreadable
/**
* Checks if `value` is a flattenable `arguments` object or array.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
*/
function isFlattenable(value) {
return Array.isArray(value) || isArguments(value) ||
!!(value && value[spreadableSymbol])
}
export default isFlattenable
通过代码,我们可以看到,它是通过递归完成的。其中有三个参数需要解析一下:
参数值 | 解析 |
---|---|
depth | 表示最多可扁平化多少层 |
predicate | 填入false表示用默认的函数判断是否可以对每一项数据进行扁平化,也可自己写个函数判断 |
isStrict | 表示是否在扁平化之后的数组中留下不能扁平化的数据 |
我们可以这样调用
其它扁平化方式
正则实现也是先将数组转换成字符串的表达形式,这里将数组转成字符串我们使用JSON.stringify方法,将数组转换成一个由括号包裹、元素间以逗号相隔的字符串,例如"[1, [2, [3, [4, 5]]], 6]",从转换后的字符可以发现,每一对括号包着的范围就是一个层级,数组的展平就是将内部的层级全部消除,只保留最外层,在这里,就是将括号全部替换成空字符,得到一个元素以逗号相隔字符串,最后将利用JSON.parse方法解析成数组对象。
let arr = [1, [2, [3, [4, 5]]], 6];
function flatten(arr) {
let str = JSON.stringify(arr);
str = str.replace(/(\[|\])/g, '');
// 拼接最外层,变成JSON能解析的格式
str = '[' + str + ']';
return JSON.parse(str);
}
console.log(flatten(arr)); // [1, 2, 3, 4,5]
这种方式在处理引用数据类型上有局限性,同时还要注意元素是否是JSON的合法数据类型。