稀疏数组 Sparse arraysjavascript
通常来讲,JavaScript 中的数组都是稀疏数组-它们能够拥有空槽,所谓空槽,指的就是数组的某个位置没有任何值,既不是 undefined
,也不是 null
,由于数组只是索引到值的简单映射。java
let a = new Array(3); console.log(a); // (3) [空 × 3] console.log(a[0]); // undefined a.forEach(function (x, i) { console.log(i, x) }); // 没有打印任何东西 a.map(function (x, i) { return i }) // (3) [空 × 3]
密集数组 Dense arrays数组
let a = Array.apply(null, Array(3)); // 至关于 Array(undefined, undefined, undefined) console.log(a); // [ undefined, undefined, undefined ] console.log(a[0]); // undefined a.forEach(function (x, i) { console.log(i+". "+x) }); // 0 undefined // 1 undefined // 2 undefined a.map(function (x, i) { return i }) // [ 0, 1, 2 ]
按位移动操做符有两个操做数:第一个是要被移动的数字,而第二个是要移动的长度。app
移动的方向根据操做符的不一样而不一样。prototype
按位移动会先将操做数转换为大端字节序顺序(big-endian order)的32位整数,并返回与左操做数相同类型的结果。右操做数应小于 32位,不然只有最低 5 个字节会被使用。code
Big-Endian: 高位字节排放在内存的低地址端,低位字节排放在内存的高地址端,又称为"高位编址"。索引
Big-Endian是最直观的字节序:ip
<<
左移内存
该操做符会将第一个操做数向左移动指定的位数。向左被移出的位被丢弃,右侧用 0 补充。io
9 (base 10) -> 00000000000000000000000000001001 (base 2)
console.log(9 << 2); // 36 // 00000000000000000000000000001001 -> 00000000000000000000000000100100 = 36 (base 10)
>>
有符号右移
该操做符会将第一个操做数向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧。因为新的最左侧的位老是和之前相同,符号位没有被改变。因此被称做符号传播。
console.log(9 >> 2); // 2 // 00000000000000000000000000001001 -> 00000000000000000000000000000010 = 2 (base 10)
console.log(-9 >> 2 ); // -3 由于符号被保留了 // 11111111111111111111111111110111 -> 11111111111111111111111111111101 = -3 (base 10)
>>>
无符号右移
该操做符会将第一个操做数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。由于符号位变成了 0,因此结果老是非负的。(译注:即使右移 0 个比特,结果也是非负的。)
对于非负数,有符号右移和无符号右移老是返回相同的结果。例如 9 >>> 2 和 9 >> 2 同样返回 2:
console.log(9 >>> 2); // 2 // 00000000000000000000000000001001 -> 00000000000000000000000000000010 = 2 (base 10)
可是对于负数却不尽相同。 -9 >>> 2 产生 1073741821 这和 -9 >> 2 不一样:
console.log(-9 >>> 2); // 1073741821 // 11111111111111111111111111110111 -> 00111111111111111111111111111101 = 1073741821 (base 10)
console.log([1, 2, 3, 4].slice(-1))
/** * 裁剪数组,从 start 位置开始到 end 结束,但不包括 end 自己的位置。 * 代替 Array.prototype.slice,确保密集数组被返回。 * * @param {Array} array 要裁剪的数组 * @param {number} [start=0] 开始的位置 | 负指数将被视为距结束的偏移量。 * @param {number} [end=array.length] 结束的位置 | 负指数将被视为距结束的偏移量。 * @returns {Array} 返回裁切后的数组 * @example * * var array = [1, 2, 3, 4] * _.slice(array, 2) * // => [3, 4] */ function slice(array, start, end) { // 若 array 为 null 返回 [] let length = array == null ? 0 : array.length if (!length) { return [] } // 若 start 为 null 取第 0 位 start = start == null ? 0 : start // 若 end 为 undefined(没传该值),end 取数组 length end = end === undefined ? length : end // start 为负值,若大于数组长度,start 取第零位,不然从最后觉得往前减 if (start < 0) { start = -start > length ? 0 : (length + start) } // 若结束位置大于数组 length 取 length end = end > length ? length : end if (end < 0) { end += length } // x >>> 0 保证 x 为数字类型且为正整数,在无心义的状况下缺省值为0。 length = start > end ? 0 : ((end - start) >>> 0) // start = start >>> 0 start >>>= 0 // 构建新数组并返回 let index = -1 const result = new Array(length) while (++index < length) { result[index] = array[index + start] } return result } export default slice