JS经典题目解析

此次列举出一些觉得有意思的JS题目(来源于出了名的44题),相信有非常多关于这些题目的博客,写这篇博客的目的在于巩固一些知识点,希望能和读者共同进步。

1. map函数执行过程

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

答案: [1, NaN, NaN]

解析: map(function callback(current, index, array)), map 回掉提供三个参数,current value, index of current value, array.

parseInt(value, radix), parseInt 提供两个参数,value 表示需要转换的string,radix表示string原本的进制单位,从2到36.

所以这道题的执行过程是这样的:

array.map(parseInt(value(current), radix(index) )); 回掉会自动按序分配参数

current => value, index => radix;

真实执行过程

array.map(parseInt(1, 0)) => parseInt(1, 0), 0 默认代表十进制。

parseInt(2, 1), 没有1进制,所以返回NaN,

parseInt(3,2), 2进制只有0,1, 所以同样返回NaN

2.[typeof null, null instanceof Object]

答案: [object, false]

解析: typeof 返回一个表示类型的字符串, typeof null == object.

instanceof 用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性, 显而易见,null 没有构造函数,所以返回的是false

3. 运算符优先级

var val = ‘smtg‘;

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

答案:Something

解析:+ 运算符优先级高于 > ,所以没有括号的情况下, 会先执行字符串连接操作。

所以等价于 ‘Value is true‘? ‘Something‘ : ‘Nothing‘

如果搞不清运算符优先级的时候,可以加上括号

4. 稀疏数组与Array.filter

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

答案:[]

解析: 这边的ary 是一个稀疏数组,index从3到9都没有定义,所以ary[3~9]的值是undefined(可以在chrome tool里通过ary[index]来查看),那么乍一看这个题的答案应该是返回7个undefined组成的数组。

但是这里返回的是[],原因在于filter函数的作用。

if (!Array.prototype.filter){
  Array.prototype.filter = function(func, thisArg) {
    ‘use strict‘;
    if ( ! ((typeof func === ‘Function‘ || typeof func === ‘function‘) && this) )
        throw new TypeError();

    var len = this.length >>> 0,
        res = new Array(len), // preallocate array
        t = this, c = 0, i = -1;
    if (thisArg === undefined){
      while (++i !== len){
        // checks to see if the key was set
        //看这里 看这里
        if (i in this){
          if (func(t[i], i, t)){
            res[c++] = t[i];
          }
        }
      }
    }
    else{
      while (++i !== len){
        // checks to see if the key was set
        if (i in this){
          if (func.call(thisArg, t[i], i, t)){
            res[c++] = t[i];
          }
        }
      }
    }

    res.length = c; // shrink down array to proper size
    return res;
  };
}

可以看红色文字下方的代码,filter函数会先判断当前index是否在数组中被设置,即是否有ary[index] = value的过程,否则会跳过这个index。

所以对于稀疏数组,未定义的index会被跳过,从而导致这道题的答案是[]。 如果有ary[index] = undefined, 那么结果就会是返回由undefined 组成的数组。

array.filter

5. String(‘A‘) 和 new String(‘A‘) 的区别

以下两个代码段的输出结果是?

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‘));
function showCase2(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!‘);
    }
}
showCase2(String(‘A‘));

答案:‘Do not know!‘ ; ‘Case A‘

解析:为什么两个代码段的输出不一致呢?

两个原因:1.switch进行比较的时候用的是全等符“===”,所以不会做类型转换,即“10”不会等于10;

2. new String() 和 String 返回的类型不同,前者返回的是object,后者返回的是string,所以在做全等比较的时候,返回的结果是false。

所以如果有需要用到switch对于字符串做比较的时候,需要注意传入的参数类型。

6. 你真的了解"=="吗?

下面两个代码段的输出是?

var a = [0];
if ([0]) {
  console.log(a == true);
} else {
  console.log("wut");
}
[]==[]
 

答案:false, false

解析:如果单纯的把[0]转换成boolean类型的话,结果会是true,所以if判断语句的结果是true。

看了很多其他的博客,都有说到“==”会做类型转换,比较其值,我觉得这个答案依然无法详细解释上述代码的结果。

查阅了更多资料后,找到了一些“==“的规则:

1、如果两个值类型相同,进行 === 比较,比较规则同上 
2、如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较: 
a、如果一个是null、一个是undefined,那么[相等]。 
b、如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。 
c、如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。 
d、如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。非js核心的对象,令说(比较麻烦,我也不大懂) 
e、任何其他组合(array数组等),都不相等。

所以其实”==“的转换规则,并没有想象的那么简单,由此可见[0] == true, 应该采用的是规则c, 而[] == [] 应该采用的是规则e.

最后附上一张”==“比较的结果图

7.  Arguments of methods

function sidEffecting(ary) {
  ary[0] = ary[2];
}
function bar(a,b,c) {
  c = 10
  sidEffecting(arguments);
  return a + b + c;
}
bar(1,1,1)
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)

答案:21, 12

解析:第一个代码段的答案,我相信很容易得出。问题是第二个代码段,乍一看结果应该和第一个代码段相同,实则不然,那么是为什么呢?

其实这边不同的结果是由arguments 这个对象(arguments 不是数组)造成的,如果函数的参数有默认值的时候,那么arguments这个对象不会追踪参数值的变化,并且只记录传递过来的值。

所以第二个代码段中,arguments的结果是(1,1,1),sideEffecting函数拿到的结果是ary[0] =1, ary[2] =1; 所以回到a+b+c = 1+1+10 ==》 12。更多详情可以点击下方链接。

Arguments

8. 有趣的比较符又来了

[1 < 2 < 3, 3 < 2 < 1]

答案: true, true

解析:1<2<3 等价于1<2=> true; true<3 => 1<3=> true;

3<2=> false; false<1 => 0<1=> true.

9.变量提升

(function(){
  var x = y = 1;
})();
console.log(y);
console.log(x);

答案: 1, error

解析:这道题目涉及到变量提升的范围,以及赋值语法。

var x=y=1 等价于 var x=1; y=1; 这里的y会被提升至全局域,所以的除上述答案。

var x=1,y=1 等价于var x=1; var y=1, 这样写的话,x,y都是局部变量,不会被提升。

先总结这么几道,之后碰到觉得有趣的题目,会持续更新。

原文地址:https://www.cnblogs.com/ChallengeEverything/p/9250657.html

时间: 2024-10-28 20:49:32

JS经典题目解析的相关文章

JS代码预解析原理、函数相关、面向对象

JS重要知识点 这里列出了一些JS重要知识点(不全面,但自己感觉很重要).彻底理解并掌握这些知识点,对于每个想要深入学习JS的朋友应该都是必须的. 讲解还是以示例代码搭配注释的形式,这里做个小目录: JS代码预解析原理(包括三个段落): 函数相关(包括 函数传参,带参数函数的调用方式,闭包): 面向对象(包括 对象创建.原型链,数据类型的检测,继承). JS代码预解析原理 /****************** JS代码预解析原理 ******************//*JS代码预解析.变量作

【前端】Vue.js经典开源项目汇总

Vue.js经典开源项目汇总 原文链接:http://www.cnblogs.com/huyong/p/6517949.html Vue是什么? Vue.js(读音 /vju?/, 类似于 view) 是一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合.另一方面,Vue 完全有能力驱动采用单文件组件和 Vue 生态系统支持的库开发的复杂单页应用. Vue.js 的目标是通过

CSV.js – 用于 CSV 解析和编码的 JS 工具库

逗号分隔值(CSV )文件用于以以纯文本的形式存储表格化数据(数字和文本). CSV 文件包含任意数量的记录,通过某种换行符分隔,每条记录由字段,其他一些字符或字符串分隔,最常用的是文字逗号或制表符.CSV.js 是一个简单,超快的用于 CSV 解析和编码的 JavaScript 工具库,兼容浏览器,AMD 和 NodeJS 环境. 您可能感兴趣的相关文章 Web 开发中很实用的10个效果[附源码下载] 精心挑选的优秀jQuery Ajax分页插件和教程 12款经典的白富美型 jQuery 图片

Vue.js经典开源项目汇总

Vue.js经典开源项目汇总 原文链接:http://www.cnblogs.com/huyong/p/6517949.html Vue是什么? Vue.js(读音 /vju?/, 类似于 view) 是一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合.另一方面,Vue 完全有能力驱动采用单文件组件和 Vue 生态系统支持的库开发的复杂单页应用. Vue.js 的目标是通过

矩阵经典题目七:Warcraft III 守望者的烦恼(矩阵加速递推)

https://www.vijos.org/p/1067 很容易推出递推式f[n] = f[n-1]+f[n-2]+......+f[n-k]. 构造矩阵的方法:构造一个k*k的矩阵,其中右上角的(k-1)*(k-1)的矩阵是单位矩阵,第k行的每个数分别对应f[n-1],f[n-2],,f[n-k]的系数.然后构造一个k*1的矩阵,它的第i行代表f[i],是经过直接递推得到的.设ans[][]是第一个矩阵的n-k次幂乘上第二个矩阵,f[n]就是ans[k][1]. 注意:用__int64 #in

There&#39;s Treasure Everywhere! poj1473题目解析

题目: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 总时间限制:  1000ms 内存限制:  65536kB 描述 Finding buried treasures is simple: all you need is a map! The pirates in the Caribbean were famous for their enormous buried treasures and their elaborate maps

js中eval详解,用Js的eval解析JSON中的注意点

先来说eval的用法,内容比较简单,熟悉的可以跳过eval函数接收一个参数s,如果s不是字符串,则直接返回s.否则执行s语句.如果s语句执行结果是一个值,则返回此值,否则返回undefined. 需要特别注意的是对象声明语法“{}”并不能返回一个值,需要用括号括起来才会返回值,简单示例如下: var s1='"a" + 2'; //表达式var s2='{a:2}'; //语句alert(eval(s1)); //->'a2'alert(eval(s2)); //->und

js原生offsetParent解析

offsetParent是个只读属性,返回最近显示指定位置的容器元素的引用.如果元素没有指定位置,最近的元素或者根元素(标准模式下是html,怪异模式下是body)就是offsetParent.当元素的style.display='none'时,offsetParent返回null.由于offsetTop和offsetLeft是相对于页边距,因此offsetParent是非常有用的. 浏览器兼容性 在以WebKit为核心的浏览器上,如果元素是隐藏的(该元素或者上级元素style.display=

增量备份,11g052题目解析

增量备份分为差异备份(differential incremental backup)和累积备份(cumulative incremental backup),这是两种执行增量备份操作的不同方法. 80. You perform differential incremental level 1 backups of your database on each working day and level 0 backup on Sundays, to tape. Which two stateme