JavaScript一题一理

第一题:下面代码输出的结果是什么

1
["1", "2", "3"].map(parseInt)

答案: [1, NaN, NaN]

解析:

首先,这种写法,函数里面只写了一个 parseInt 就可以执行了。这个是函数式编程的一种概念,叫做 point free,具体的 point free 是个什么东西,还请您自行去 google 吧。这不是本章关注的重点。

在说说 parseInt 这个方法,他接收两个参数。第一个是要处理的字符串,第二个参数是转换的进制 radix ,取值是 2-36 的整数。10不是默认值,不同浏览器实现可能不同,虽然大部分浏览器都是将10作为默认值

其次是数组的 map 方法,接受一个函数作为参数,这个参数函数接收三个参数:每一项的值、索引,数组本身。这里传入一个 parseInt 相当于是 parseInt 的第一个参数是数组的每一项,第二个参数是这一项的索引值。所以最终处理的是:

  • parseInt('1', 0)
  • parseInt('2', 1)
  • parseInt('3', 2)

这里有一个隐藏点,parseInt 第二个参数如果是 0,undefined,null,或者没有,按 10 处理 。

至于后面两项,来看这样一个例子

1
parseInt('123', 2)

最开始学习的时候你可能是这样学的,遇到字符串的第一个非数字停止,截取前面的,比如 100a 则截取前面的数字 100 ,再比如 a100 截取 a 前面的,则为 '' 。现在再加一条,如果字符串中的数字大于 radix ,也停止,截取前面的。所以,这是按照二进制来处理的,字符串 123 的第一项是小于 2 的,后面两项都是大于 2 的,所以直接忽略,相当于是求 parseInt('1', 2) 的值。

至于超过 radix 范围的,则全部为 NaN

其次是第二项。没有取值为 1 的情况,则是 NaN

最后第三项。 3 的首位大于 2,直接截断,相当于 parseInt('', 2) ,则为 NaN

第二题:下面代码输出的结果是什么

1
[typeof null, null instanceof Object]

答案: ['object', false]

解析:

typeof null —> ‘object’ 这是 ECMA-262规定的不多说。

object instanceof constructor 判断 constructor.prototype 是否在 object 的原型链上。基本数据类型(null,undefined,number,bool,string,symbol,bigInt)没有原型链

第三题:下面代码输出的结果是什么

1
[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow) ]

答案:报错

解析:

数组的 reduce 方法 array.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

前一个计算 $3^2=9$,在计算 $9^1=9$。最终是 9。

第二项是一个空数组, reduce 如果是一个空数组则会报错。reduceRight 也是一样的。

第四题:下面代码输出的结果是什么

1
2
var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');

答案: Something

解析: + 操作的优先级高于三元表达式。

第五题:下面代码输出的结果是什么

1
2
3
4
5
6
7
8
9
var name = 'World!';
(function () {
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();

答案: Goodbye Jack

解析:

var 存在变量提升,在 IIFE 中,先声明了变量 name 值是 undefined 。所以走了上面的 if 。如果将 var 变为 let ,那么因为不存在变量提升,所以会走 elsename 取全局的 name = 'World'

第六题:下面代码输出的结果是什么

1
2
3
4
5
6
7
var END = Math.pow(2, 53);
var START = END - 100;
var count = 0;
for (var i = START; i <= END; i++) {
count++;
}
console.log(count);

答案:不是 100 也不是 101,而是其他,也不会报错。

解析:JavaScript中的数字使用了 IEEE 754 中规定的双精度浮点数数据类型,而这一数据类型能够安全存储 -Math.pow(2, 53) - 1Math(2, 53) - 1 之间的数值(包含边界),上面的 END 超出了边界,这会是一个无限循环的。

第七题:下面代码输出的结果是什么

1
2
3
var ary = [0,1,2];
ary[10] = 10;
ary.filter(function(x) { return x === undefined;});

答案: []

解析:缺少的元素不会调用 filter 。还有 map 不会处理没有初始化的 item ,返回 undefined

第八题:下面代码输出的结果是什么

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function showCase(value) {
switch(value) {
case 'A':
console.log('Case A');
break;
case 'B':
console.log('Case B');
break;
case undefined:
console.log('undefined');
break;
default:
console.log('Do not know!');
}
}
showCase(new String('A'));

答案: 'Do not know!'

解析:switch 使用 === 进行比较。 new String('A') == 'A' 但是 new String('A') !== 'A'。那如果是 String('A') 呢,答案则是 Case A 。因为这个没有创建对象。使用 new 操作符才会创建对象。

第九题:下面代码输出的结果是什么

1
Array.isArray( Array.prototype )

答案:true

解析: Array.prototype 是一个数组而不是一个对象。

https://pic-go-1253455210.cos.ap-chengdu.myqcloud.com/blog/20201118150851.png

第十题:下面代码输出的结果是什么

1
2
3
4
5
6
var a = [0];
if ([0]) {
console.log(a == true);
} else {
console.log("wut");
}

答案: false

解析: [0] 作为布尔值(或者说数组作为布尔值)的时候都认为是 true 。但是在进行相当判断的时候,会进行转换,调用 valueOf() 判断,如果无法比较,则继续调用 toString() 进行判断。

第十一题:下面代码输出的结果是什么

1
1 + - + + + - + 1

答案: 2

解析:相当于 1 + ( - + + + - + 1 ) 的值。后面的计算: + 1 = 1 - 1 = -1 + (-1) = -1 - (-1) = 1 。所以。两个减号相抵消,加好不用管。最终是 1 + 1

第十二题:下面代码输出的结果是什么

1
2
3
3.toString()
3..toString()
3...toString()

答案: error, '3', error

解析: toString() 方法不能作用于整数。但是可以作用于小数。所以第一个报错。第二个呢, 3. 其实是一个小数,知道这个,那就没问题了。第三个,虽然是小数了,但是后面的两个点,语法都错了。

第十三题:下面代码输出的结果是什么

1
2
3
4
function foo() { }
var oldName = foo.name;
foo.name = "bar";
[oldName, foo.name]

答案: ['foo', 'foo']

解析:函数的 name 是只读的,返回函数的名字。

第十四题:下面代码输出的结果是什么

1
2
var lowerCaseOnly =  /^[a-z]+$/;
[lowerCaseOnly.test(null), lowerCaseOnly.test()]

答案: [true, true]

解析:正则调用 test 的时候会把测试的数据转换为字符串。所以上面的测试的是 'null''undefined'

第十五题:下面代码输出的结果是什么

1
2
var min = Math.min(), max = Math.max()
min < max

答案: false

解析: Math.min() 返回 +InfinityMath.max() 返回 -Infinity 。所以,min > max 。So,terrible。我还以为最大的就是正无穷,最小就是负无穷呢。

第十六题:下面代码输出的结果是什么

1
2
3
4
5
6
7
8
9
function foo(a) {
var a;
return a;
}
function bar(a) {
var a = 'bye';
return a;
}
[foo('hello'), bar('hello')]

答案: ['hello','bar']

解析: 在函数被声明与函数参数同名的变量,声明将会被移除,但是赋值不会被移除。所以 foo 中的声明被移除,是 hello ,而 bar 中的声明移除赋值保留 a = 'bye' ,是 bye

最后。掘金很少发文章了,大部分文章都放在自己的博客里面了。

文章作者: 踏浪
文章链接: https://www.lyt007.cn/技术/JavaScript一题一理.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 平凡的生活,不平凡的人生
支付宝
微信打赏