Javascript 一直是神奇的语言。 不相信我? 尝试使用map和parseInt将字符串数组转换为整数。打开 Chrome 的控制台(F12),粘贴以下内容,然后按回车,查看输出结果:
['1', '7', '11'].map(parseInt);
我们得到的不是一个整数数组[1,7,11],而是[1,NAN, 3],要了解究竟发生了什么,我们首先要讨论一些Javascript概念。
以下是 JS 中一个简单的if-else语句:
if (true) {
// this always runs
} else {
// this never runs
}
在上例中,if 条件为 true,因此总是执行if块,忽略else块。这是一个简单的例子,因为true是一个布尔值。如果我们把非布尔值作为条件呢 ?
if ("hello world") {
console.log("Condition is truthy");
} else {
console.log("Condition is falsy");
}
打开控制台并运行上述代码,会打印 Condition is truthy,说明条件 "hello world" 为真(true)值。
在 JavaScript 中,Truthy (真值)指的是在 布尔值 上下文中转换后的值为真的值。所有值都是真值,除非它们被定义为 falsy (即除了 false,0,"",null,undefined 和 NaN 外)。
falsy(虚值)是在 Boolean 上下文中已认定可转换为‘假‘的值。
JS中的对象不是真值就是虚值。
令人困惑的是,这意味着字符串“false”,字符串“0”,空对象{}和空数组[]都是真的。 使用使用 Boolean 方法来验证,如 Boolean("0")。
出于我们的目的,接下来只要记住0是假的就行了。
在数学上,基数(cardinal number)是集合论中刻画任意集合大小的一个概念。两个能够建立元素间一一对应的集合称为互相对等集合。例如3个人的集合和3匹马的集合可以建立一一对应,是两个对等的集合。
0 1 2 3 4 5 6 7 8 9 10
当我们从0数到9时,每个数字(0-9)都有不同的符号,但是当我们数到10时,我们需要两个不同的符号(1和0)来表示这个数字。这是因为我们的十进制计数系统的基数是10。
基数是最小的数字,只能由多个符号表示。 不同的计数系统具有不同的基数,因此,相同的数字在不同的计数系统中可以表示不同的数字。
十进制 二进制 十六进制
RADIX=10 RADIX=2 RADIX=16
0 0 0
1 1 1
2 10 2
3 11 3
4 100 4
5 101 5
6 110 6
7 111 7
8 1000 8
9 1001 9
10 1010 A
11 1011 B
12 1100 C
13 1101 D
14 1110 E
15 1111 F
16 10000 10
17 10001 11
看上表,可以看到相同的数字11在不同的计数系统中可以表示不同的数字。如果基数是2,那么它表示数字为 3。如果基数是16,那么它指的是数字17。
你可能已经注意到,在我们的示例中,当输入为11时,parseInt返回3,这对应于上表中的二进制列。
JS 中函数调用,我们可以传入任意的参数,即使它们不等于声明时的函数参数的数量。缺少的参数被视为undefined 的,并且会忽略额外的参数,但会保存在类似数组的arguments对象中。
function foo(x, y) {
console.log(x);
console.log(y);
}
foo(1, 2); // 打印 1, 2
foo(1); // 打印 1, undefined
foo(1, 2, 3); // 打印 1, 2
map是 Es6 中新出的一个数组方法,它是一个高阶函数,通过传入一个函数进行逻辑操作,并返回一个数组, 例如,以下代码将数组中的每个元素乘以3:
function multiplyBy3(x) {
return x * 3;
}
const result = [1, 2, 3, 4, 5].map(multiplyBy3);
console.log(result); // logs [3, 6, 9, 12, 15];
现在,将console.log作为参数传给 map,来打印数组的元素:
[1, 2, 3, 4, 5].map(console.log);
等价于
[1, 2, 3, 4, 5].map((val, index, array) =>
console.log(val, index, array));
所以 map 回调方法中会传入三个参数,分别是 当前遍历的项,当前索引,及遍历的整个数组。
ParseInt有两个参数:string和radix。 如果提供的基数是虚值,则默认情况下,基数设置为10。
parseInt('11'); => 11
parseInt('11', 2); => 3
parseInt('11', 16); => 17
parseInt('11', undefined); => 11 (radix is falsy)
parseInt('11', 0); => 11 (radix is falsy)
现在一步一步解析开头的事例。
['1', '7', '11'].map(parseInt); => [1, NaN, 3]
// 第一次迭代: val = '1', index = 0, array = ['1', '7', '11']
parseInt('1', 0, ['1', '7', '11']); => 1
因为0是虚值,基数设置为默认值10。parseInt()只接受两个参数,因此忽略了第三个参数['1'、'7'、'11']。以10为基数的字符串“1”表示数字1。
// 第二次迭代: val = '7', index = 1, array = ['1', '7', '11']
parseInt('7', 1, ['1', '7', '11']); => NaN
在基数1系统中,符号“7”不存在。与第一次迭代一样,忽略最后一个参数。因此,parseInt()返回NaN。
// Third iteration: val = '11', index = 2, array = ['1', '7', '11']
parseInt('11', 2, ['1', '7', '11']); => 3
在基数2(二进制)系统中,符号“11”表示数字3。
至此原因已经明了了。 有兴趣可以试着写下下列的打印结果:
['1', '7', '11'].map(numStr => parseInt(numStr));
原文:https://medium.com/dailyjs/parseint-mystery-7c4368ef7b21
翻译来自:https://segmentfault.com/a/1190000019479803
在 Javascript 中,一个函数可以传递任何多个数量的参数,即使调用时传递的数量与定义时的数量不一致。缺失的参数会以 undefined 作为实际值传递给函数体,然后多余的参数会直接被忽略掉
在JavaScript中,Map 是存储键/值对的对象。Map 类似于一般 JavaScript 对象 ,但对象与 Map 之间一些关键的差异使 Map 很有用。如果你要创建一个存储一些键/值路径的 JavaScript 对象
Map、Set的polyfill实现是可以继承的;//可继承的Array替换原生Array,Array要改的地比较多,除了替换原生Array还需修改继承函数,供参考
普通的 JavaScript 对象通常可以很好地保存结构化数据。但是它们有一些限制:只能用字符串或符号用作键,自己的对象属性可能会与从原型继承的属性键冲突(例如,toString,constructor 等)。对象不能用作键
Map的出现解决了传统object无法直接解决的问题,更好地向标准编程语言靠近(标准编程语言一般会提供Map集合),使用的坑也比较少(比如没有object作为key时转换为[object Object]的问题)。
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
ES6的Map的键可以是任意的数据结构,并且不重复。那么map的底层原理是啥呢?Map利用链表,hash的思想来实现。首先,Map可以实现删除,而且删除的数据可以是中间的值。
JavaScript中,数组的遍历我们肯定都不陌生,最常见的两个便是forEach 和 map。(当然还有别的譬如for, for in, for of, reduce, filter, every, some, ...)
JS 普通对象 {key: value} 用于存放结构化数据。但有一件事我觉得很烦:对象键必须是字符串(或很少使用的 symbol)。如果将数字用作键会怎样? 在这种情况下不会有错误:
JSON 对象保存在大括号内。就像在JavaScript中, 对象可以保存多个 键/值 对。Map对象保存键/值对,是键/值对的集合。任何值(对象或者原始值) 都可以作为一个键或一个值。Object结构提供了“字符串—值”的对应
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!