Javascript中几个看起来简单,却不一定会做的题

时间:2024-01-15 15:49:02

Javascript作为前端开发必须掌握的一门语言,因为语言的灵活性,有些知识点看起来简单,在真正遇到的时候,却不一定会直接做出来,今天我们就一起来看看几道题目吧

题目1

var val = 'smtg';

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

这道题考察的知识点是运算符的优先级。

首先,小括号的优先级是最高的,所以首先会做判断,val与smtg相等返回true。因此最后这道题等价于判断是执行下面的语句1还是语句2.

//语句1

'Value is' + (true ? 'Something' : 'Nothing');

//语句2

'Value is true' ? 'Something' : 'Nothing';

根据运算符优先级我们知道,连接元算符+的优先级要高于条件运算符?的优先级,因此实际执行的是语句2,所以最后返回的结果是

'Something'.

题目2

我们再来看看下面这道题。

var ary = [0,1,2];

ary[6] = 6;

var result = ary.filter(function(x){

  return x === undefined;

});

console.log(result);

这道题考察的时候数组的初始化和filter方法。

第一眼看上去,以为会输出[undefined,undefined,undefined],但是实际输出却是undefined,为什么会这样?

这是因为在JavaScript里存在稀疏数组的概念,数组在初始化时,只会对已经确定索引的选项进行初始化,对于不存在索引的选项不进行初始化,通过以下代码可以确定。

0 in ary;//true

1 in ary;//true

3 in ary;//false 

4 in ary;//false

6 in ary;//true 

对数组使用in运算符时,是通过枚举数组的索引,通过3和4返回false可以知道,ary[3]和ary[4]实际是不存在的,未进行初始化。

我们再来看看 Array.prototype.filter方法和polyfill,注意代码中标注的地方。

Array.prototype.filter = function(fun /*thisArg*/){

  if(this === void 0 || this === null){

    throw new TypeError();

  }

  var t = Object(this);

  var len = t.length >>> 0;

  if(typeof fun !== 'function'){

    throw new TypeError();

  }

  var res = [];

  var thisArg = arguments.length >=2 ? arguments[1]:void 0;

  for(var i = 0;i<len;i++){

    if(i in t){  //注意这里,使用的是in运算符

      var val = t[i];

      if(fun.call(thisArg,val,i,t)){

        res.push(val);

      }

    }

  }

  return res;

}

在filter方法源码中,我发现使用了in运算符,而arg数组没有对索引为3,4,5的值进行初始化,因此会直接跳过执行,所以最后返回undefined。

题3

function caseshow(val){

  switch(val){

    switch(value){

      case 'A':

        console.log('A');

   break;

       case 'B':

        console.log('B');

   break;

         case 'C':

        console.log('C');

   break;

      default:
        console.log('do not know!');

    }  

  }

}

caseshow(new String('A'));

咋一看,很多人会以为输出'case A',但实际输出'do not know'。why?
这道题考察的知识点是:switch和string,我们需要知道一下两点:

1,JavaScript中switch执行的是严格相等(===)。
2,字符串和string的实例不一样。

第二点我们可以测试下。

var s_p = 'foo';
var s_o = new String(s_p)

console.log(typeof s_p) //'string'
onsole.log(typeof s_o) //'object'
onsole.log(s_p === s_o) //'false'

因此针对题目中的'A'与String('A')并不严格相等,最终会返回‘do not know’

题4
针对上面的题目3,我们稍作一点改动,成为下面的题目4,再看看结果输出什么?
function caseshow2(val){
switch(val){
  case 'A':
    console.log('A');
    break;
  case 'B':
    console.log('B');
    break;
  case undefined:
    console.log('undefined');
    break;
  default:
    console.log('do not know!');
}
}
caseshow2(String('A'));
题目4相对于题目3,只是在最后调用的时候传入的参数是String('A'),它的结果就变成了'Case A'。这是为什么呢?

其实很简单,String(X)返回的是一个字符串而不会生成一个新的String实例,因此与'A'是严格相等的。