["1", "2", "3"].map(parseInt)
答案: [1, NaN, NaN]
。
解析:
首先说说 parseInt
这个方法,他接收两个参数。第一个是要处理的字符串,第二个参数是转换的进制 radix
,取值是 2-36
的整数。10不是默认值,不同浏览器实现可能不同,虽然大部分浏览器都是将10作为默认值。
其次是数组的 map
方法,接受一个函数作为参数,这个参数函数接收三个参数:每一项的值、索引,数组本身。这里传入一个 parseInt
相当于是 parseInt
的第一个参数是数组的每一项,第二个参数是这一项的索引值。所以最终处理的是:
parseInt('1', 0)
parseInt('2', 1)
parseInt('3', 2)
这里有一个隐藏点,parseInt
第二个参数如果是 0,undefined,null,或者没有,按 10 处理 。
至于后面两项,来看这样一个例子
parseInt('123', 2)
最开始学习的时候你可能是这样学的,遇到字符串的第一个非数字停止,截取前面的,比如 100a
则截取前面的数字 100
,再比如 a100
截取 a
前面的,则为 ''
。现在再加一条,如果字符串中的数字大于 radix
,也停止,截取前面的。所以,这是按照二进制来处理的,字符串 123
的第一项是小于 2 的,后面两项都是大于 2 的,所以直接忽略,相当于是求 parseInt('1', 2)
的值。
至于超过 radix
范围的,则全部为 NaN
其次是第二项。没有取值为 1
的情况,则是 NaN
。
最后第三项。 3
的首位大于 2,直接截断,相当于 parseInt('', 2)
,则为 NaN
[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)没有原型链
[ [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
也是一样的。
var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');
答案: Something
解析: +
操作的优先级高于三元表达式。
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
,那么因为不存在变量提升,所以会走 else
, name
取全局的 name = 'World'
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) - 1
到 Math(2, 53) - 1
之间的数值(包含边界),上面的 END
超出了边界,这会是一个无限循环的。
var ary = [0,1,2];
ary[10] = 10;
ary.filter(function(x) { return x === undefined;});
答案: []
解析:缺少的元素不会调用 filter
。还有 map
不会处理没有初始化的 item
,返回 undefined
。
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
操作符才会创建对象。
Array.isArray( Array.prototype )
答案:true
解析: Array.prototype
是一个数组而不是一个对象。
var a = [0];
if ([0]) {
console.log(a == true);
} else {
console.log("wut");
}
答案: false
解析: [0]
作为布尔值(或者说数组作为布尔值)的时候都认为是 true
。但是在进行相当判断的时候,会进行转换,调用 valueOf()
判断,如果无法比较,则继续调用 toString()
进行判断。
1 + - + + + - + 1
答案: 2
解析:相当于 1 + ( - + + + - + 1 )
的值。后面的计算: + 1 = 1
- 1 = -1
+ (-1) = -1
- (-1) = 1
。所以。两个减号相抵消,加好不用管。最终是 1 + 1
3.toString()
3..toString()
3...toString()
答案: error, '3', error
解析: toString()
方法不能作用于整数。但是可以作用于小数。所以第一个报错。第二个呢, 3.
其实是一个小数,知道这个,那就没问题了。第三个,虽然是小数了,但是后面的两个点,语法都错了。
function foo() { }
var oldName = foo.name;
foo.name = "bar";
[oldName, foo.name]
答案: ['foo', 'foo']
解析:函数的 name
是只读的,返回函数的名字。
var lowerCaseOnly = /^[a-z]+$/;
[lowerCaseOnly.test(null), lowerCaseOnly.test()]
答案: [true, true]
解析:正则调用 test
的时候会把测试的数据转换为字符串。所以上面的测试的是 'null'
和 'undefined'
var min = Math.min(), max = Math.max()
min < max
答案: false
解析: Math.min()
返回 +Infinity
而 Math.max()
返回 -Infinity
。所以,min > max
。So,terrible。我还以为最大的就是正无穷,最小就是负无穷呢。
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
。