第一道:
["1", "2", "3"].map(parseInt)
解析: .map(callback(value, index, array))
回调函数传入三个参数, parseInt(string, radix)
接收两个参数。
所以map传递给parseInt的参数是这样的(parseInt忽略map传递的第三个参数)[1, 0],[2, 1],[3, 2],然乎parseInt()解析传过来的参数。
相当于执行以下语句:
parseInt('1', 0); 当radix为0时,默认为10进制,所以返回1
parseInt('2', 1); 没有1进制,所以返回NaN
parseInt('3', 2); 二进制中只有数字1、2,没有数字3,所以返回NaN
('1', 0); 当radix为0时,默认为10进制,所以返回1
parseInt('2', 1); 没有1进制,所以返回NaN
parseInt('3', 2); 二进制中只有数字1、2,没有数字3,所以返回NaN
parseInt(string, radix)
radix可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。如果省略该参数或其值为 0,则数字将以 10 为基础来解析。如果它以 “0x” 或 “0X” 开头,将以 16 为基数。
如果该参数小于 2 或者大于 36,则 parseInt() 将返回 NaN
所以结果为 [1, NaN, NaN]
第二道:
[typeof null, null instanceof Object];
解析:typeof 返回一个表示类型的字符串,总是返回一个字符串。
instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,总是返回布尔值。
typeof null === 'object'
typeof undefined === 'undefined'
typeof Infinity === 'number'
typeof NaN === 'number'
null === 'object'
typeof undefined === 'undefined'
typeof Infinity === 'number'
typeof NaN === 'number'
function c () {}
function d () {}
let o = new c();
o instanceof c; //true,因为Object.getPrototypeOf(o) === c.prototype)
o instanceof Object; //true;因为Object.prototype.isPrototypeOf(o)返回true
c () {}
function d () {}
let o = new c();
o instanceof c; //true,因为Object.getPrototypeOf(o) === c.prototype)
o instanceof Object; //true;因为Object.prototype.isPrototypeOf(o)返回true
所以结果为 [object, false]
第三道:(还是理解不了)
[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow) ]
3,2,1].reduce(Math.pow), [].reduce(Math.pow) ]
解析: arr.reduce(callback, [initialValue])
callback包含四个参数
-
accumulator上一次调用回调返回的值,或者是提供的初始值(initialValue)
-
currentValue 数组中正在处理的元素
-
currentIndex 数组中正在处理的的元素索引
-
array 调用reduce的数组
-
initialValue 其值用于第一次调用callback的第一个参数
另外如果数组为空并且没有提供initialValue,会抛出TypeError
第一个表达式等价于Math.pow(3, 2) => 9, Math.pow(9, 1) => 9
第二个, Uncaught TypeError: Reduce of empty array with no initial value
所以结果为 an error
第四道:
var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');
val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');
解析: 大多数人都会先看到三元运算符,然后输出结果Value is somethin
我也是这样/(ㄒoㄒ)/~~
这里主要是考虑了优先级。 + 的优先级是高于 ? 的 ,
所以执行顺序是
val === 'stmg' => true
'Value is' + true => 'Value is true'
'Value is true ' ? 'Something' : 'Nothing' => 'Something'
=== 'stmg' => true
'Value is' + true => 'Value is true'
'Value is true ' ? 'Something' : 'Nothing' => 'Something'
所以结果为 'Something'
第五题:
var name = 'World!';
(function () {
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
name = 'World!';
(function () {
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
解析:主要考虑变量声明提升,本题相当于把name声明到顶部但是未定义。
这里扩充一下函数提升
dohois(); //"提升了"
donothois(); //TypeError: undefined is not a function
//函数声明提升
function dohois () {
console.log("提升了");
}
//函数表达式不提升
var donothois = function () {
console.log("没有提升");
}
//"提升了"
donothois(); //TypeError: undefined is not a function
//函数声明提升
function dohois () {
console.log("提升了");
}
//函数表达式不提升
var donothois = function () {
console.log("没有提升");
}
所以结果为 Goodbye Jack
var name = 'World!';
(function (name) {debugger
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})(name);
// Hello World!
第六道:
var END = Math.pow(2, 53);//Math.pow(底数,几次方)
var START = END - 100;
var count = 0;
for (var i = START; i <= END; i++) {
count++;
}
console.log(count);
END = Math.pow(2, 53);//Math.pow(底数,几次方)
var START = END - 100;
var count = 0;
for (var i = START; i <= END; i++) {
count++;
}
console.log(count);
解析:JS里Math.pow(2, 53)是可以表示的最大值,最大值加1还是最大值。发生的情况是这样的 : Math.pow(2, 53) == Math.pow(2, 53) + 1
,所以永远不可能大于Math.pow(2, 53)。
console.log(Infinity); //Infinity
console.log(Infinity + 1); //Infinity
.log(Infinity); //Infinity
console.log(Infinity + 1); //Infinity
所以结果是 无限循环
第七道:
var ary = [0,1,2];
ary[10] = 10;
//ary: [0, 1, 2, empty × 7, 10]
ary.filter(function(x) { return x === undefined;});
ary = [0,1,2];
ary[10] = 10;
//ary: [0, 1, 2, empty × 7, 10]
ary.filter(function(x) { return x === undefined;});
解析:首先需要理解稀疏数组和密集数组
创建一个稀疏数组,遍历稀疏数组时,会发现这个数组并没有元素,js会跳过这些坑。
//第一种情况
var a = new Array(3);
console.log(a); //[, , ,]
//第二种情况
var arr = [];
arr[0] = 1;
arr[100] = 100;
//arr: (101) [1, empty × 99, 100]
a.map(function (x, i) {return i}); //[, , ,]
var a = new Array(3);
console.log(a); //[, , ,]
//第二种情况
var arr = [];
arr[0] = 1;
arr[100] = 100;
//arr: (101) [1, empty × 99, 100]
a.map(function (x, i) {return i}); //[, , ,]
创建一个密集数组,可以遍历到这些数组元素
var a = Array.apply(null, Array(3));
console.log(a); //[undefined, undefined, undefined]
a.map(function (x, i) {return i}); //[0, 1, 2]
a = Array.apply(null, Array(3));
console.log(a); //[undefined, undefined, undefined]
a.map(function (x, i) {return i}); //[0, 1, 2]
这道题目里的数组是一个稀疏数组,不会遍历到(从索引3-9)“坑”,这些索引都不存在数组中,会直接跳过这些坑。所以永远筛选不到等于undefined的值。
所以结果为 []
第八道:
var two = 0.2
var one = 0.1
var eight = 0.8
var six = 0.6
[two - one == one, eight - six == two] //eight - six: 0.20000000000000007
two = 0.2
var one = 0.1
var eight = 0.8
var six = 0.6
[two - one == one, eight - six == two] //eight - six: 0.20000000000000007
解析: js的浮点数运算,不能精确的表达小数。什么时候会精确呢,都不知道( ╯□╰ )。
所以结果为 [true, false]
第九道:
function showCase(value) {
typeof value; //Object
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'));
showCase(value) {
typeof value; //Object
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'));
解析:switch是严格比较。
这里要考虑字符串。
var s_prim = 'foo';
var s_obj = new String(s_prim);
console.log(typeof s_prim); //"String"
console.log(typeof s_obj); //"object"
s_prim = 'foo';
var s_obj = new String(s_prim);
console.log(typeof s_prim); //"String"
console.log(typeof s_obj); //"object"
所以不可能匹配到case,所以结果为 Do not know
第十道:
function showCase2(value) {
typeof value; //String
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!');
}
}
showCase2(String('A'));
showCase2(value) {
typeof value; //String
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!');
}
}
showCase2(String('A'));
解析:和第九题类似,但是注意此时 typeof String('A') === 'string'
所以结果为 Case A
第11题
function isOdd(num) {
return num % 2 == 1;
}
function isEven(num) {
return num % 2 == 0;
}
function isSane(num) {
return isEven(num) || isOdd(num);
}
var values = [7, 4, '13', -9, Infinity];
//map: 方法返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组。
values.map(isSane);
isOdd(num) {
return num % 2 == 1;
}
function isEven(num) {
return num % 2 == 0;
}
function isSane(num) {
return isEven(num) || isOdd(num);
}
var values = [7, 4, '13', -9, Infinity];
//map: 方法返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组。
values.map(isSane);
解析:主要在于 -9 % 2 == -1
保留正负号。 Infinity % 2
得到的是NaN,但是注意NaN与所有值都不相等包括本身。
所以结果为 [true, true, true, false, false]
第12题
parseInt(3, 8)
parseInt(3, 2)
parseInt(3, 0)
(3, 8)
parseInt(3, 2)
parseInt(3, 0)
解析:和第一题考察的概念一样。2进制里没有数字3,radix为0时时10进制
所以结果为 [3, NaN, 3]
第13题
Array.isArray( Array.prototype )
.isArray( Array.prototype )
解析:Array.prototype本身是一个数组,这只能牢牢记住了~
所以结果为 [true]
第14题
var a = [0];
if ([0]) {//[0]: array
console.log(a == true);
} else {
console.log("wut");
}
a = [0];
if ([0]) {//[0]: array
console.log(a == true);
} else {
console.log("wut");
}
解析:所有对象都是true,但是当执行a == true时会进行隐式转换。
所以结果为 false
第15题
[] == []
解析:2个引用的是同一个对象、函数、数组,则它们相等,如果引用的不是同一个对象、函数、数组,则不相同,即使这2个对象、函数、数组可以转换成完全相等的原始值。
所以结果为 false
第16题
'5' + 3 //"53"
'5' - 3 //2
+ 3 //"53"
'5' - 3 //2
解析:考察字符串拼接
第17题
1 + - + + + - + 1
解析:从后面开始计算,首先得到一个正数(+1),然后往前都是符号的改变得到(-1 -1 -1 -1 +1 ),等于1+(+1)
+1 //1
- + 1 //-1
+ - + 1 //-1
+ + - + 1 //-1
+ + + - + 1 //-1
- + + + - + 1 //1
所以结果为 2
第18题
var ary = Array(3);
ary[0]=2
ary; //[2, empty × 2]
ary.map(function(elem) { return '1'; });
ary = Array(3);
ary[0]=2
ary; //[2, empty × 2]
ary.map(function(elem) { return '1'; });
解析: 稀疏数组,会跳过这些未被赋值的“坑”。所以只有ary[0]能被遍历到
所以结果为 [1, undefined × 2], // [2, empty × 2]
第19题
function sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a,b,c) {
c = 10
sidEffecting(arguments);//arguments: [1, 1, 10, callee: ƒ, Symbol(Symbol.iterator): ƒ]
return a + b + c;
}
bar(1,1,1)
sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a,b,c) {
c = 10
sidEffecting(arguments);//arguments: [1, 1, 10, callee: ƒ, Symbol(Symbol.iterator): ƒ]
return a + b + c;
}
bar(1,1,1)
解析:
so changing the variables changes arguments and changing arguments changes the local variables even when they are not in the same scope.
改变变量改变了arguments,改变argumnets也改变了本地变量,即时他们不在一个作用域。
arguments就是传进来的参数组成的类数组。所以sidEffecting([a, b, c]),就知道a和c都为10,b为1。
ヽ(*。>Д<)o゜
但是当函数参数涉及到 any rest parameters, any default parameters(默认参数) or any destructured parameters 的时候, 这个 arguments 就不在是一个 mapped arguments object 了
function sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a,b,c=3) {
c = 10
sidEffecting(arguments);
return a + b + c;
}
bar(1,1,1) //12
sidEffecting(ary) {
ary[0] = ary[2];
}
function bar(a,b,c=3) {
c = 10
sidEffecting(arguments);
return a + b + c;
}
bar(1,1,1) //12
所以结果为 21
第20题
var a = 111111111111111110000,
b = 1111;
a + b;
a = 111111111111111110000,
b = 1111;
a + b;
解析:由于JS能表示整数范围为-2^53~2^53,这里的a已经超过了2^53,与第六题类似,最大值加上一个数还是最大值。所以还是a
所以结果为 a : 111111111111111110000
第21题
var x = [].reverse(); //[].reverse() : []
x();
x = [].reverse(); //[].reverse() : []
x();
解析:最后会返回这个调用者(this),x执行的时候的上下文是全局,所以返回的是window。
所以结果为 window
第22题
Number.MIN_VALUE > 0 //Number.MIN_VALUE: 5e-324
.MIN_VALUE > 0 //Number.MIN_VALUE: 5e-324
解析:Number.MIN_VALUE 属性表示在 JavaScript 中所能表示的最小的正值。MIN_VALUE 属性是 JavaScript 里最接近 0 的正值,而不是最小的负值。
乐意黎
2018-04-02