前置
本篇隨筆包含 _.compact 和 _.concat 及其依賴的工具函式,
你可能需要一些 JavaScript 基礎知識才能看懂一些沒有注釋的細節,
compact
_.compact(array)
創建一個新陣列,包含原陣列中所有的非假值元素,例如 false, null, 0, "", undefined, 和 NaN 都是被認為是“假值”,
/**
* Creates an array with all falsey values removed. The values `false`, `null`,
* `0`, `""`, `undefined`, and `NaN` are falsey.
*
* @since 0.1.0
* @category Array
* @param {Array} array The array to compact.
* @returns {Array} Returns the new array of filtered values.
* @example
*
* compact([0, 1, false, 2, '', 3])
* // => [1, 2, 3]
*/
function compact(array) {
let resIndex = 0
const result = []
if (array == null) {
return result
}
// for of 回圈 array
// resIndex 自增賦值符合條件的陣列
for (const value of array) {
if (value) {
result[resIndex++] = value
}
}
return result
}
export default compact
arrayPush
/**
* Appends the elements of `values` to `array`.
*
* @private
* @param {Array} array The array to modify.
* @param {Array} values The values to append.
* @returns {Array} Returns `array`.
*/
function arrayPush(array, values) {
var index = -1,
length = values.length,
offset = array.length;
// 回圈往array結尾追加values的元素
while (++index < length) {
array[offset + index] = values[index];
}
return array;
}
module.exports = arrayPush;
對比 v8 的 push 實作:
// Appends the arguments to the end of the array and returns the new
// length of the array. See ECMA-262, section 15.4.4.7.
function ArrayPush() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push");
var array = TO_OBJECT(this);
var n = TO_LENGTH(array.length); // 被push的array的length
var m = arguments.length;
// Subtract n from kMaxSafeInteger rather than testing m + n >
// kMaxSafeInteger. n may already be kMaxSafeInteger. In that case adding
// e.g., 1 would not be safe.
if (m > kMaxSafeInteger - n) throw %make_type_error(kPushPastSafeLength, m, n);
for (var i = 0; i < m; i++) {
array[i+n] = arguments[i]; // 復制元素
}
var new_length = n + m; // 修正length屬性的值
array.length = new_length;
return new_length;
}
isObjectLike
檢查 value 是否是類物件,如果一個值不是 null,并且 typeof 結果為 object,則該值為類物件,
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* isObjectLike({})
* // => true
*
* isObjectLike([1, 2, 3])
* // => true
*
* isObjectLike(Function)
* // => false
*
* isObjectLike(null)
* // => false
*/
function isObjectLike(value) {
return typeof value =https://www.cnblogs.com/guangzan/p/=='object' && value !== null
}
export default isObjectLike
isArguments
import getTag from './.internal/getTag.js' // 在上一篇文章中解釋了這個方法
import isObjectLike from './isObjectLike.js'
/**
* Checks if `value` is likely an `arguments` object.
*
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an `arguments` object, else `false`.
* @example
*
* isArguments(function() { return arguments }())
* // => true
*
* isArguments([1, 2, 3])
* // => false
*/
function isArguments(value) {
// 已經解釋過 toStringTag
return isObjectLike(value) && getTag(value) == '[object Arguments]'
}
export default isArguments
isFlattenable
檢查 value 是否為可扁平化的 arguments 物件或陣列,
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) {
// Symbol.isConcatSpreadable 用于配置某物件作為 Array.prototype.concat() 方法的引數時是否展開其陣列元素,
// 參考 https://segmentfault.com/q/1010000021953491 的采納答案
return Array.isArray(value) || isArguments(value) ||
!!(value && value[spreadableSymbol])
}
export default isFlattenable
baseFlatten
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. // 只限于通過 "predicate"檢查的數值,
* @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
copyArray
/**
* Copies the values of `source` to `array`.
*
* @private
* @param {Array} source The array to copy values from.
* @param {Array} [array=[]] The array to copy values to.
* @returns {Array} Returns `array`.
*/
function copyArray(source, array) {
let index = -1
const length = source.length
array || (array = new Array(length))
while (++index < length) {
array[index] = source[index]
}
return array
}
export default copyArray
isArray
/**
* Checks if `value` is classified as an `Array` object.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an array, else `false`.
* @example
*
* _.isArray([1, 2, 3]);
* // => true
*
* _.isArray(document.body.children);
* // => false
*
* _.isArray('abc');
* // => false
*
* _.isArray(_.noop);
* // => false
*/
var isArray = Array.isArray;
module.exports = isArray;
concat
_.concat(array, [values])
創建一個新陣列,將 array 與任何陣列或值連接在一起,
var arrayPush = require('./_arrayPush'),
baseFlatten = require('./_baseFlatten'), // 扁平化陣列
copyArray = require('./_copyArray'),
isArray = require('./isArray');
/**
* Creates a new array concatenating `array` with any additional arrays
* and/or values.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to concatenate.
* @param {...*} [values] The values to concatenate.
* @returns {Array} Returns the new concatenated array.
* @example
*
* var array = [1];
* var other = _.concat(array, 2, [3], [[4]]);
*
* console.log(other);
* // => [1, 2, 3, [4]]
*
* console.log(array);
* // => [1]
*/
function concat() {
var length = arguments.length; // 引數數量
if (!length) {
return [];
}
var args = Array(length - 1), // [empty]
array = arguments[0], // 原陣列
index = length;
// args 加入除原陣列以外的引數其他引數的陣列或值
while (index--) {
args[index - 1] = arguments[index];
}
// 若原陣列是 Array 型別,拷貝一遍陣列回傳,反之創建一個陣列
// 將 args 扁平化并 push 到原陣列
return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
}
module.exports = concat;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/47813.html
標籤:JavaScript
下一篇:表單元素
