不服进来试一试,你能做对吗?反正我是个小菜鸡

103 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

先来一道开胃菜,JavaScript中的神奇魔法

1. 神奇的null

[typeof nullnull instanceof Object]  
// A. ["object", false]  ✅
// B. [null, false]  
// C. ["object", true]  
// D. other

这是由Javascript规范规定的,Null和Object都是javascript中的数据类型。Null数据类型只有一个值:null。就像undefined数据类型只有一个值:undefined。问题出在typeof操作符的定义规范, 对于Null类型的值(只有null),规范就是定义返回"object"这个字符串。但是本质上Null和Object不是一个数据类型,null值并不是以Object为原型创建出来的。所以null instanceof Object是false。

  1. 在MDN关于 null 的文档中也特别指出来了,typeof null 的结果是 "object",它是ECMAScript的bug,其实应该是 "null"。

  2. 而 instanceof 运算符是用来测试一个对象在其原型链构造函数上是否具有 prototype 属性,null 值并不是以 Object 原型创建出来的,所以 null instanceof Object 返回 false。

2. + 的优先级

var val = 'smtg';  
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');  
  
// A. Value is Something  
// B. Value is Nothing  
// C. NaN  
// D. other ✅

实际上输出 "Something",因为 + 的优先级比条件运算符 condition ? val1 : val2 的优先级高。 先执行 'Value is ' + (val === 'smtg')

3. 过滤器filter的魔法

var ary = [0,1,2];  
ary[10] = 10;  
ary.filter(function(x) {  
  return x === undefined;  
});  
  
// A. [undefined x 7]  
// B. [0, 1, 2, 10]  
// C. []   ✅
// D. [undefined]

filter 为数组中的每个元素调用一次 callback 函数,并利用所有使得 callback 返回 true 或 等价于 true 的值 的元素创建一个新数组。callback 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。 那些没有通过 callback 测试的元素会被跳过,不会被包含在新数组中。

arr[10]创建的数组中间没有初始化

image.png

4. switch的严格相等比较

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'));  
  
// A. Case A  
// B. Case B  
// C. Do not know!   ✅
// D. undefined

在 switch 内部使用严格相等 === 进行判断,并且 new String("A") 返回的是一个对象,而 String("A") 则是直接返回字符串 "A"。

image.png

5. 再给你一次机会,看你听讲没

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(String('A'));  
  
// A. Case A  ✅
// B. Case B  
// C. Do not know!  
// D. undefined

image.png

6. 你真的懂强制转换吗?

var a = [0];  
if ([0]) {  
  console.log(a == true);  
} else {  
  console.log("wut");  
}  
  
// A. true  
// B. false   ✅
// C. "wut"  
// D. other
  1. 在if([0])时,[0] 需要被强制转成 Boolean 的时候会被认为是 true。所以进入第一个 if 语句,
  2. 而 a == true 的转换规则在ES5规范的第11.9.3节中已经定义过,你可以自己详细探索下。 规范指出,== 相等中,如果有一个操作数是布尔类型,会先把他转成数字,所以比较变成了 [0] == 1;同时规范指出如果其他类型和数字比较,会尝试把这个类型转成数字再进行宽松比较,而对象(数组也是对象)会先调用它的 toString() 方法,此时 [0] 会变成 "0",然后将字符串 "0" 转成数字 0,而 0 == 1 的结果显然是 false。

7. 你以为你会啦吗?

[]==[]  
  
// A. true  
// B. false   ✅
// C. error  
// D. other

ES5规范11.9.3.1-f指出:如果比较的两个对象指向的是同一个对象,就返回 true,否则就返回 false,显然,这是两个不同的数组对象。

总结:大家都太年轻啦,小伙子,放弃吧!