稀疏数组和密集数组

稀疏数组 Sparse arrays

一般来说,JavaScript 中的数组都是稀疏数组-它们可以拥有空槽,所谓空槽,指的就是数组的某个位置没有任何值,既不是 undefined,也不是 null,因为数组只是索引到值的简单映射。

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 ]

位移操作符

按位移动操作符有两个操作数:第一个是要被移动的数字,而第二个是要移动的长度

移动的方向根据操作符的不同而不同。

按位移动会先将操作数转换为大端字节序顺序(big-endian order)的32位整数,并返回与左操作数相同类型的结果。右操作数应小于 32位,否则只有最低 5 个字节会被使用。

Big-Endian: 高位字节排放在内存的低地址端,低位字节排放在内存的高地址端,又称为"高位编址"。

Big-Endian是最直观的字节序:

  1. 把内存地址从左到右按照由低到高的顺序写出;
  2. 把值按照通常的高位到低位的顺序写出;
  3. 两者对照,一个字节一个字节的填充进去。

<< 左移

该操作符会将第一个操作数向左移动指定的位数。向左被移出的位被丢弃,右侧用 0 补充

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)

lodash.slice

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

lodash - slice的更多相关文章

  1. 读lodash源码之从slice看稀疏数组与密集数组

    卑鄙是卑鄙者的通行证,高尚是高尚者的墓志铭. --北岛<回答> 看北岛就是从这两句诗开始的,高尚者已死,只剩卑鄙者在世间横行. 本文为读 lodash 源码的第一篇,后续文章会更新到这个仓 ...

  2. 函数式 js 接口实现原理,以及 lodash/fp 模块

    函数式 js 接口 之前在 youtube 上看到一个技术视频,讲“underscore.js的接口为什么不好用”,以及什么样的接口更好用.演讲者是 lodash.js 的作者,他提出了一种“全面函数 ...

  3. lodash源码(2)

    1.flatten 对深层嵌套数组的抹平 _.flatten([1, [2, 3, [4]]]);* // => [1, 2, 3, [4]]** // using `isDeep`* _.fl ...

  4. lodash的源码(1)

    数组篇 1.compact,就是将数组中的false值去掉 function compact(array) { var index = -1, length = array ? array.lengt ...

  5. lodash框架中的chunk与drop函数源码逐行分析

    lodash是一个工具库,跟underscore差不多 chunk函数的作用: 把一维数组,按照固定的长度分段成二维数组 如: chunk( [ 10, 20, 30, 40 ], 2 )     结 ...

  6. lodash源码分析之chunk的尺与刀

    以不正义开始的事情,必须用罪恶使它巩固. --莎士比亚<麦克白> 最近很多事似乎印证了这句话,一句谎言最后要用一百句谎言来圆谎. 本文为读 lodash 源码的第二篇,后续文章会更新到这个 ...

  7. lodash 实现一些常见的功能

    排序 const sorted = _.orderBy(filtered, [sortColumn.path], [sortColumn.order]); 数组切片 普通的 slice 可传递两个参数 ...

  8. lodash用法系列(6),函数种种

    Lodash用来操作对象和集合,比Underscore拥有更多的功能和更好的性能. 官网:https://lodash.com/引用:<script src="//cdnjs.clou ...

  9. lodash用法系列(5),链式

    Lodash用来操作对象和集合,比Underscore拥有更多的功能和更好的性能. 官网:https://lodash.com/引用:<script src="//cdnjs.clou ...

随机推荐

  1. 第五届蓝桥杯C++B组国(决)赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.年龄巧合 小明和他的表弟一起去看电影,有人问他们的年龄.小明说:今年是我们的幸运年啊.我出生年份的四位数字加起来刚好是我的年龄.表弟的 ...

  2. java实现第七届蓝桥杯七星填数

    七星填数 如图[图1.png]所示. 在七角星的14个节点上填入1~14 的数字,不重复,不遗漏. 要求每条直线上的四个数字之和必须相等. 图中已经给出了3个数字. 请计算其它位置要填充的数字,答案唯 ...

  3. Linux 最大有效权限与删除ACL

    最大有效权限mask mask是用来指定最大有效权限的.如果给用户赋予了acl权限,则需要与mask权限”相与“才能得到用户的真正权限 setfacl -m m:rx 文件名,指定最大有效权限.例如: ...

  4. 聊聊依赖注入注解@Resource和@Autowired

    1. 前言 @Resource和@Autowired注解都可以在Spring Framework应用中进行声明式的依赖注入.而且面试中经常涉及到这两个注解的知识点.今天我们来总结一下它们. 2. @R ...

  5. javascript 面向对象学习(一)——构造函数

    最近在学习设计模式,找了很多资料也没有看懂,看到怀疑智商,怀疑人生,思来想去还是把锅甩到基础不够扎实上.虽然原型继承.闭包.构造函数也都有学习过,但理解得不够透彻,影响到后续提高.这次重新开始学习,一 ...

  6. 【 转】百度地图Canvas实现十万CAD数据秒级加载

    Github上看到: https://github.com/lcosmos/map-canvas 这个实现台风轨迹,这个数据量非常庞大,当时打开时,看到这么多数据加载很快,感到有点震惊,然后自己研究了 ...

  7. python2.7 正则表达式的学习

    正则表达式是一种用来匹配字符串的强有力的武器.它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的. 因正则表达式也是用字符 ...

  8. 关于wifi营销的看过来

    亲测可用.对于一个开发者来说,终于如获至宝.详情联系qq2455994690.源码可二开.包括微信一键关注上网,手机验证码上网.

  9. python实现批量文件重命名

    本文实例为大家分享了python批量文件重命名的具体代码,供大家参考,具体内容如下 问题描述 最近遇到朋友求助,如何将大量文件名前面的某些字符删除. 即将图中文件前的编号删除. Python实现 用到 ...

  10. mitmdump+python的使用(代码篇)

    mitmproxy+python代码篇 一.上个推文我们介绍了mitmdump的简单操作,下面我们开始学习,mitmdump配合python脚本的使用.第一点先讲日志输出.请看图片 先导入ctx模块: ...