/**
* 这个方法类似indexOf,除了它是在已经排序的数组array上执行二进制检索
* This method is like `indexOf` except that it performs a binary search on a sorted `array`
* @param {Array} array The array to inspect
* @param {*} value The value to search for
* @returns {number} Returns the index of the matched value, else `-1`
* @example
* sortedIndexOf([4, 5, 5, 5, 6], 5)
* // => 1
*/
import baseSortedIndex from "./baseSortedIndex"
// 比较两个值以确定他们是否相等
function eq(value, other) {
return value === other || (value !== value && other !== other)
}
function sortedIndexOf(array, value) {
var length = array == null ? 0 : array.length
if (length) {
var index = baseSortedIndex(array, value)
if (index < length && eq(array[index], value)) {
return index
}
}
return -1
}
export default sortedIndexOf
/**
* The base implementation of `sortedIndex` and `sortedLastIndex` which performs
* a binaray search of `array` to determine the index at which `value` should be inserted
* into `array` in order to maintain its sort order
* @param {Array} array The sorted array to inspect
* @param {*} value The value to evaluate
* @param {boolean} [retHighest] Specify returning the highest qualified index
* @returns {number} Returns the index at which `value` should be inserted into `array`
*/
import baseSortedIndexBy from "./baseSortedIndexBy"
const MAX_ARRAY_LENGTH = 4294967295 //Used as references for the maximum length and index of an array
const HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1 //一半
// 这个方法返回首个提供的参数。
function identity(value) {
return value
}
function baseSortedIndex(array, value, retHighest) {
var low = 0,
high = array == null ? low : array.length
if (
typeof value === "number" &&
value === value &&
high <= HALF_MAX_ARRAY_LENGTH
) {
while (low < high) {
var mid = (low + high) >>> 1,
computed = array[mid]
if (
computed !== null &&
(retHighest ? computed <= value : computed < value)
) {
low = mid + 1
} else {
high = mid
}
}
return high
}
return baseSortedIndexBy(array, value, identity, retHighest)
}
export default baseSortedIndex
/**
* The base implementation of `sortedIndexBy` and `sortedLastIndexBy` which invokes `iteratee` for
* `value` and each element of `array` to compute their sort ranking.The iteratee is invoked with one argument
* @param {Array} array The sorted array to inspect
* @param {*} value The value to evaluate
* @param {Function} iteratee The iteratee invoked per element
* @param {boolean} [retHighest] Specify returning the highest qualified index
* @returns {number} Returns the index at which `value` should be inserted into `array`
*/
import isSymbol from "./isSymbol"
const MAX_ARRAY_LENGTH = 4294967295 //Used as references for the maximum length and index of an array
const MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1
function baseSortedIndexBy(array, value, iteratee, retHighest) {
value = iteratee(value)
var low = 0,
high = array == null ? 0 : array.length,
valIsNaN = value !== value,
valIsNull = value === null,
valIsSymbol = isSymbol(value),
valIsUndefined = value === undefined
while (low < high) {
var mid = (low + high) >>> 1,
computed = iteratee(array[mid]),
othIsDefined = computed !== undefined,
othIsNull = computed === null,
othIsReflexive = computed === computed,
othIsSymbol = isSymbol(computed)
if (valIsNaN) {
var setLow = retHighest || othIsReflexive
} else if (valIsUndefined) {
setLow = othIsReflexive && (retHighest || othIsDefined)
} else if (valIsNull) {
setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull)
} else if (valIsSymbol) {
setLow =
othIsReflexive &&
othIsDefined &&
!othIsNull &&
(retHighest || !othIsSymbol)
} else if (othIsNull || othIsSymbol) {
setLow = false
} else {
setLow = retHighest ? computed <= value : computed < value
}
if (setLow) {
low = mid + 1
} else {
high = mid
}
}
return Math.min(high, MAX_ARRAY_INDEX)
}
export default baseSortedIndexBy
/**
* 判断`value`是否是`Symbol`类型
* Checks if `value` is classified as a `Symbol` primitive or Object.
*
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
* @example
*
* isSymbol(Symbol(3))
* // => true
*
* isSymbol({[Symbol.toStringTag]: 'Symbol'})
* // => true
*
* isSymbol('abc')
* // => false
*/
const symbolTag = "[object Symbol]"
function isObjectLike(value) {
return typeof value == "object" && value !== null
}
function isSymbol(value) {
return (
typeof value === "symbol" ||
(isObjectLike(value) && Object.prototype.toString.call(value) === symbolTag)
)
}
export default isSymbol