JavaScript Puzzlers详解

作者 : 开心源码 本文共13470个字,预计阅读时间需要34分钟 发布时间: 2022-05-13 共137人阅读

前言

题目来自JavaScript Puzzlers,涉及的知识点很广,本文的解题过程尽量做到详细易懂。因为文章篇幅较长,推荐先马后看,相信肯定可以在文章中找到不熟或者者概念模糊的知识点。(全篇共44题,笔者连蒙带猜一刷成绩为27/44,有几题都是蒙对的,勉强及格)


正文

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

考察知识点:
1.map函数
2.parseInt函数

解析:map函数的callback默认有三个参数,分别为currentValue、currentIndex、arrary。此处用parseInt作为callback,而parseInt只能接收两个参数,所以callback中的默认第三个参数array被忽略。假如把map的回调拆分开,此时相当于这样:

parseInt("1", 0)  // 1parseInt("2", 1)  // NaNparseInt("3", 2)  // NaN

parseInt的第二个参数取值范围是2~36,此参数省略或者者为0时,以十进制方式解析,所以“parseInt(“1”, 0)”返回1。
“parseInt(“2”, 1)”第二个参数为1,不在取值范围内,所以返回NaN。
“ parseInt(“3”, 2)”以二进制的方式解析字符串3,但是二进制中的有效数字只有0和1,所以返回NaN。

答案:[1, NaN, NaN]

第二题
[typeof null, null instanceof Object]

考察知识点:
1.null
2.instanceof

解析:原型链的源头为null,所有对象都是通过null派生出来的,null本身也被定义为对象,所以“typeof null”返回object字符串。instanceof用于判断构造函数的prototype属性能否在对象的原型链上,由于null为原型链顶端,而“Object.prototype”有值,显然“null instanceof Object”返回false。

答案:[“object”, false]

第三题
[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow) ]

考察知识点:
1.reduce

解析:reduce函数的callback默认有四个参数,分别为accumulator、currentValue、currentIndex、array。此处用Math.pow作为callback,而Math.pow只能接收两个参数,所以currentIndex和array被忽略。

假如没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。假如提供initialValue,从索引0开始。在没有初始值的空数组上调用 reduce 将报错
–摘自MDN

“[3,2,1].reduce(Math.pow)”拆分后等价于:

Math.pow(3, 1)  // 3Math.pow(3, 2)  // 9Math.pow(9, 1)  // 9

对于“[].reduce(Math.pow)”,由于使用空数组调用reduce,所以报错。

答案:error

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

考察知识点:
1.运算符的优先级
2.“+”运算符的隐式转换
3.字符串的隐式转换

解析:“+”运算符的优先级大于三目运算符的优先级,所以执行过程如下:

val === 'smtg'  // 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);    }})();

考察知识点:
1.块级作用域与变量提升

解析:使用var公告的变量没有块级作用域(注意区分块级作用域与函数作用域),使用let、const公告的变量有块级作用域,由于函数内的name用var公告,所以不存在块级作用域,导致变量提升。等价写法如下:

var name = 'World!';(function () {    var name;    if (typeof name === 'undefined') {        name = 'Jack';        console.log('Goodbye ' + name);    } else {        console.log('Hello ' + name);    }})();

答案:”Goodbye Jack”

第六题
var END = Math.pow(2, 53);var START = END - 100;var count = 0;for (var i = START; i <= END; i++) {    count++;}console.log(count);

考查知识点:
1.JS中能存储的最大值

分析:能存储的最大值

64位浮点数能表示的整数范围是-2^53~2^53,即最大值为Math.pow(2, 53),当超出这个值时,自动转为最大值。因而本题的for循环会一直执行下去,console.log语句永远无法执行。

答案:死循环

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

考察知识点:
1.数组跳index赋值
2.filter

解析:ary初始化为3个元素后赋值ary[10],数组中index从3到9的元素是未定义的,不会被自动填充为undefined,而filter函数的callback不会回调数组中的未定义元素。验证如下:

未定义 filter

注意区分未定义元素与undefined元素,filter函数的callback是会回调数组中undefined元素的,验证如下:

undefined filter

由于本题中的数组不存在undefined元素,所以不存在通过条件挑选的元素,最终返回[]。

答案:[]

第八题
var two   = 0.2var one   = 0.1var eight = 0.8var six   = 0.6[two - one == one, eight - six == two]

考查知识点:
1.浮点数的精度及表达方式

解析:这题比较简单,但为了说明起因还是啰嗦一下。老司机都知道,浮点数的运算会存在精度缺失问题,为什么会精度缺失?我们知道计算机中的数值是以二进制方式存储的,以3.14的小数部分0.14为例,转换如下:

// 0.140.14 * 2 = 0.28    00.28 * 2 = 0.56    00.56 * 2 = 1.12    10.12 * 2 = 0.24    00.24 * 2 = 0.28    00.48 * 2 = 0.96    00.96 * 2 = 1.92    10.92 * 2 = 1.84    1...

所以0.14取8位二进制有效数字的表达式为0.00100011,显然当小数部分转成二进制时,可能存在有效数字范围内无法准确表达的问题,因而浮点数运算会存在精度缺失问题。

回到本题,来计算一下0.1、0.2、0.6、0.8转成二进制是怎么表达的:

// 0.10.1 * 2 = 0.2    00.2 * 2 = 0.4    00.4 * 2 = 0.8    00.8 * 2 = 1.6    10.6 * 2 = 1.2    00.2 * 2 ...

可以看到,以0.1为源,在转换的过程中出现了0.2、0.4、0.8、0.6,在0.6之后又出现了0.2。所以,本题的四个小数在转成二进制后都是循环小数。

// 0.2 - 0.1      0.2 => 0.001000100010...      0.1 => 0.000100010001...0.2 - 0.1 => 0.000100010001...      0.1 => 0.000100010001...

显然,0.2 – 0.1的二进制运算结果与0.1的二进制表达方式相等

// 0.8 - 0.6      0.8 => 0.100010001000...      0.6 => 0.000100010001...0.8 - 0.6 => 0.011101110111...      0.2 => 0.001000100010...

显然,0.8 – 0.6的二进制运算结果大于0.2的二进制表达方式

答案:[true, false]

第九题
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'));

考查知识点:
1.字符串对象与原生字符串的区别

解析:这一题也很简单,通过String构造函数生成的字符串对象与原生字符串不相等,验证如下

字符串对象与原生字符串

  1. 原生字符串类型为”string”,字符串对象类型为”object”
  2. 通过new调用String构造函数生成的是字符串对象,直接调用String构造函数生成的是原生字符串

除此之外,字符串对象与原生字符串在作为eval参数时,体现也是不同的:

eval解决字符串

  1. 当参数为原生字符串时,eval会将字符串当做源代码解决
  2. 当参数为字符串对象时,eval会将字符串当做对象解决

除此之外,在代码里可以通过原生字符串访问到字符串对象的方法,这是由于JS在解析时会自动将原生字符串转换为字符串对象。

答案:”Do not know!”

第十题
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'));

考察知识点:
1.字符串对象与原生字符串的区别

解析:见第九题

答案:”Case A”

第十一题
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];values.map(isSane);

考察知识点:
1.字符串转数字
2.Infinity
3.map

解析:本题关键点在于Infinity。Infinity表示正无穷大,所以任何数乘以无穷大仍为无穷大,任何数(除Infinity与-Infinity外)除以无穷大都为0。由于Infinity无法用精确的数值来表示,所以Infinity除以Infinity的值为NaN。同理,由于无法精确表示Infinity的值,所以“Infinity % 2”的值也为NaN。另外:

-9 % 2 // -1

答案:[true, true, true, false, false]

第十二题
parseInt(3, 8)parseInt(3, 2)parseInt(3, 0)

考察知识点:
1.parseInt

解析:见第一题

答案:3, NaN, 3

第十三题
Array.isArray( Array.prototype )

考察知识点:
1.Array.isArray
2.Array.prototype

解析:Array.isArray用来检测对象能否为数组,Array.prototype也是数组,所以本题返回true。

比照instanceof,“Array.prototype instanceof Array”返回false。由于instanceof的检测机制为,检测构造函数的prototype能否在对象的原型链上。此时构造函数的prototype就是要检测的对象本身,显然不在检测对象的原型链上,所以返回false。再来做个实验:

instanceof

只需将obj的原型指向Array.prototype,此时instanceof就返回true。那么如何检测对象的真是类型呢?typeof显然不行,他对于实例对象都返回’object’。我们可以通过toString的默认实现来获取当前对象的类型标识:

function objectType(obj) {    return Object.prototype.toString.apply(obj)}

对象类型检测

显然,只是将obj的__proto__属性指向Array.prototype,由Object构造函数创立的obj对象并不会变成数组,他的类型标识依然是’Object’。

答案:true

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

考查知识点:
1.if条件判断的自动转换

解析:送分题。“if([0])”为真,“[0] == true”为假,所以输出false

答案:false

第十五题
[]==[]

考察知识点:
1.==
2.深拷贝与浅拷贝

解析:先简单说说深拷贝与浅拷贝

深拷贝与浅拷贝

深拷贝可以了解为重新创立一个与原对象各数据相同的对象,浅拷贝可以了解为引用。上图中,a0、a1互为深拷贝关系,a1、a2互为浅拷贝关系。由于深拷贝为重新创立对象,所以a0和a1是不等的。而浅拷贝为引用关系,所以a1和a2是相等的。
回到本题,“[] == []”显然等号两端为两个同类型,但不同的对象,所以返回false。

对于“==”而言,当发现等号两端数据类型不一致时会进行隐式转换,可以看一下这道题的变种:

[] == ![]  // true

“!”运算符优先级高于“==”优先级,所以先计算“![]”,此时“![]”的值为false,所以相当于比较[]false能否相等。由于等号两端数据类型不一致,此时进行隐式转换。[]为空数组转换成0,false转换成0,所以此时两者是相等的。

答案:false

第十六题
'5' + 3'5' - 3

考察知识点:
1.加法运算符
2.减法运算符

解析:送分题,直接给答案。

答案:”53″,2

第十七题
1 + - + + + - + 1

考察知识点:
1.加减运算符的叠加使用

解析:这道题很偏很烂,就跟当年C语言用“++”操作符出的烂题一样,没啥实际意义

加减运算符的叠加使用-1

可以看到,JS中允许加减运算符连接使用,但是不允许出现两个加或者者两个减。当加减运算符连接使用时,和单独使用减法运算符是一致的。

加减运算符的叠加使用-2

但是,当加减运算符中间出现空格时,此时两个加号与两个减号是可以出现的,运算规则相当于“正正得正,负负得正,正负得正,负正得正”。

回到本题,可拆解为如下运算:

1 + (- + + + - + 1)

括号内运算结果为1,所以本题等价于计算1+1的值,结果为2

答案:2

第十八题
var ary = Array(3);ary[0]=2ary.map(function(elem) { return '1'; });

考查知识点:
1.数组中的未定义元素能否会触发map函数的callback

解析:在“第七题”的知识点filter中,我们说过,数组中的undefined元素会触发filter函数的callback,而未定义元素不会触发,这个结论同样适用于map及reduce。reduce相对于map和filter在这一点又略有不同,map和filter可以通过空数组调用,而reduce通过空数组调用会引发error,reduce空数组调用引发error的这个特性在“第三题”中也提到过。
知识都是想通的,在后面的解题中会越来越多提到前面的知识。

回到本题,首先生成一个长度为3的空数组ary,而后将这个ary的第0个元素设置为2,此时ary的后两个元素都是未定义的,通过ary调用map。所以返回的新数组第0个元素为”1″,后两个仍为未定义元素。

map

答案:长度为3,第0个元素为”1″,后两个元素未定义的数组(再次强调,注意区分未定义与undefined)

第十九题
function sidEffecting(ary) {  ary[0] = ary[2];}function bar(a,b,c) {  c = 10  sidEffecting(arguments);  return a + b + c;}bar(1,1,1)

考查知识点:
1.arguments

解析:本题相对来说难度不大,但是假如配合默认参数和剩余参数就有点绕了,先说本题解法。在没有默认参数及剩余参数的正常模式(非严格模式)下,函数的参数与arguments是互通的,所以在bar函数中将c赋值为10,arguments[2]也变成了10,再调用sidEffecting函数将arguments[0]赋值为10,所以a也变成了10。最终a、b、c对应的值为10、1、10,所以最终结果为21。

拓展:
1.默认参数
2.剩余参数

下面说有默认参数的情况:

function argumentsTest(a = 1) {    console.log(a)    console.log(arguments[0])    a = 2    console.log(arguments[0])    arguments[0] = 3    console.log(a)}

默认参数-1默认参数-2

可见,只需函数表达式中存在默认参数,不论在调用的时候能否给函数的默认参数传值,这个参数和对应arguments中的数据都是分离的。但是注意,这两种调用方式有一点不同:当调用时不给a赋值,取出来的arguments[0]是undefined。
假如函数表达式是这样的:

function argumentsTest(a = 1, b)

b与arguments[1]也是分离的,这里不再赘述。

接着说剩余参数的情况:

function argumentsTest(a, ...theArgs) {    console.log(a)    console.log(arguments[0])    a = 2    console.log(arguments[0])    arguments[0] = 3    console.log(a)}

剩余参数

显然,含剩余参数的函数,参数与arguments中对应的元素也不互通。

答案:21

第二十题
var a = 111111111111111110000,    b = 1111;a + b;

考查知识点:

  1. JS中能存储的最大值

解析:本题考点与第六题相同,a的值111111111111111110000已超出64未浮点数能表示的最大整数,因而a + b的结果仍为a

答案:111111111111111110000

第二十一题
var x = [].reverse;x();

考察知识点:
1.reverse

解析:本题用变量x接收reverse函数,而后调用“x()”,因为reverse是属于Array.prototype,所以应该由数组来调用,而当前调用方式相当于通过全局作用域中的this调用(即window),但是window本身不是数组,所以返回error。笔者在Chrome和Firefox中验证了一下,的确返回error。
不过原网站给的答案是window,而非error。解释是,此时reverse函数(即x)中的this指向window,所以返回window。介于出题时间很早,猜测那个时候的reverse函数没有做类型校验?

答案:error

第二十二题
Number.MIN_VALUE > 0

考察知识点:
1.Number.MIN_VALUE

解析:送分题。Number.MIN_VALUE为在JS中能表示的最小正数,值约为 5e-324,很接近于+0,但依然大于0。

答案:true

第二十三题
[1 < 2 < 3, 3 < 2 < 1]

考察知识点:
1.<

解析:送分题。<运算符得到的结果为true或者者false(当然,>运算符也一样),因而本题可拆解为如下步骤:

// 1 < 2 < 3true < 31 < 3true// 3 < 2 < 1false < 10 < 1true

答案:[true, true]

第二十四题
// the most classic wtf2 == [[[2]]]

考察知识点:
1.==

解析:送分题。==运算符在等号两边类型不一致时会进行隐式转换,直到转换为相同类型再做比较。数值类型与引用类型进行比较,会将引用类型转换成数值类型。因而等号右边最终被转换为2,此时相当于:

// 2 == [[[2]]]2 == [[2]]2 == [2]2 == 2

答案:true

第二十五题
3.toString()3..toString()3...toString()

考察知识点:
1.浮点数的表示方法

解析:这一题也不难,先看代码

浮点数的表示方法

因而,.33.都是合法的表达方式,此时相当于省略了数字0。回到本题,可做以下等价写法:

// 3.toString()3.0toString()// 3..toString()3.0.toString()// 3...toString()3.0..toString()

显然,一和三语法错误,二可以解析。因而,最终答案为error, “3.0”, error。

答案:error, “3.0”, error

第二十六题
(function(){  var x = y = 1;})();console.log(y);console.log(x);

考察知识点:
1.作用域

解析:本题其实也很简单,来看等价写法

// (function() { var x = y = 1})()(function() {  y = 1  var x = y )()

显然,x的作用域仅在匿名函数内部,而y的作用域为全局。因而,第一句log输出为1,而第二句log输出error。

答案:1, error

第二十七题
var a = /123/,    b = /123/;a == ba === b

考察知识点:
1.==
2.===

解析:送分题。正则是对象,对于==,等号两边类型相等,但不是指向同一个对象,所以返回false。对于===,直接比较等号两端能否指向同一个地址,因为是不同对象,所以地址不同,返回false。

答案:false, false

第二十八题
var a = [1, 2, 3],    b = [1, 2, 3],    c = [1, 2, 4]a ==  ba === ba >   ca <   c

考察知识点:
1.==
2.===
3.>、<

解析:送分题。本题前两个答案都为false,解释同第二十七题。当大于和小于运算符两端都为数组时,一一取出进行比较,因而后两个答案分别为false和true。

答案:false, false, false, true

第二十九题
var a = {}, b = Object.prototype;[a.prototype === b, Object.getPrototypeOf(a) === b]

考察知识点:
1.函数的prototype属性
2.对象的__proto__属性
3.大括号生成的对象的constructor

解析:送分题。a为实例对象,在为自己设置prototype属性前,prototype的值为undefined。因而,“a.prtotype == b”返回false。对于用大括号生成的对象,实际是调用Object构造函数创立的。而“Object.getPrototypeOf(a)”访问的属性是对象的__proto__,实例对象的__proto__指向对象构造函数的prtotype属性,而a对象的构造函数就是Object,因而“Object.getPrototypeOf(a) === b”返回true。

答案:[false, true]

第三十题
function f() {}var a = f.prototype, b = Object.getPrototypeOf(f);a === b

考察知识点:
1.prototype与__proto__的区别

解析:送分题。在未手动指定两个属性指向的情况下,两者显然是不等的。(详细解读可以参考笔者之前写的《大话JavaScript对象》这篇文章)

答案:false

第三十一题
function foo() { }var oldName = foo.name;foo.name = "bar";[oldName, foo.name]

考查知识点:
1.configurable与writable

解析:送分题。我们知道每个函数内部都有name属性,这个属性是只读的,显然他来自函数的原型链上。并且name属性的configurable为true,而writable为false,因而foo.name可以赋值,但是并不会改变name中存储的值。

答案:[“foo”, “foo”]

第三十二题
"1 2 3".replace(/\d/g, parseInt)

考察知识点:
1.replace

解析:当replace函数的第二个参数为函数时,对应的函数参数为match、p1,p2, …、offset、string。所以可分解为如下表达方式:

 parseInt('1', 0) parseInt('2', 2)  //2进制中不存在2 parseInt('3', 4)

因而答案为,”1 NaN 3″。

答案:”1 NaN 3″

第三十三题
function f() {}var parent = Object.getPrototypeOf(f);f.name // ?parent.name // ?typeof eval(f.name) // ?typeof eval(parent.name) //  ?

考察知识点:
1.typeof
2.eval

解析:f.name显然返回函数名”f”,parent为f对象的原型,是个匿名函数,因而parent.name返回""。对于后两句,等价于如下写法:

// typeof eval(f.name)typeof eval("foo")typeof foo// typeof eval(parent.name)typeof eval("")typeof undefined

由于foo已定义为函数所以等价后的第一句返回function,第二句仍返回undefined。
原题给的最后一个答案为error,但经Chrome和Firefox验证后的确返回undefined,猜测老版本的”typeof undefined”不符合语义所以抛错?

答案:”f”, “”, function, undefined

第三十四题
var lowerCaseOnly =  /^[a-z]+$/;[lowerCaseOnly.test(null), lowerCaseOnly.test()]

考察知识点:
1.test函数的隐式转换

解析:送分题。正则对象的test函数对应参数为字符串,假如传入的不是字符串,会通过toString函数进行转换,假如传入的参数不含有toString方法,这里又分为两种情况:
1.不是继承自Object.prototype的对象,如Object.create(null)
2.null、undefined

对于不是继承自Object.prototype的对象会由于找不到toString方法而报错,对于null、undefined会直接转换成对于的字符串”null”、”undefined”。
回到本题,等价写法如下:

// lowerCaseOnly.test(null)lowerCaseOnly.test("null")// lowerCaseOnly.test()lowCaseOnly.test("undefined")

答案:[true, true]

第三十五题
[,,,].join(", ")

考察知识点:
1.数组中的逗号

解析:JS中的数组允许最后一个元素后跟上,

数组中的逗号

显然,这里是3个未定义元素,而非4个。因而,最终结果为:”, , “(注意,join函数内部的字符串中逗号后面还有个空格)

答案:”, , “

第三十六题
var a = {class: "Animal", name: 'Fido'};a.class

考察知识点:
1.关键字作为属性名称

解析:这完全取决于JS引擎能否支持关键字作为属性名,若支持则返回”Animal”,不支持则报错。经测试,Chrome和Firefox均返回”Animal”。

答案:”Animal”

第三十七题
var a = new Date("epoch")

考察知识点:
1.Date传参

解析:显然Date构造函数的参数不合法,所以返回一个不合法的Date实例对象,即Invalid Date。

答案:Invalid Date

第三十八题
var a = Function.length,    b = new Function().lengtha === b

考查知识点:
1.Function的length
2.函数的length

解析:Function.length定义为1,而函数的length属性是形参的个数,这其中不包括剩余参数,假如参数中存在默认值,则length的长度为第一个含默认参数之前参数的个数。由于“new Function().length”没有形参,所以b的值为0,而a的值为1。因而,最终结果为false。

答案:false

第三十九题
var a = Date(0);var b = new Date(0);var c = new Date();[a === b, b === c, a === c]

考察知识点:
1.Date作为构造函数与普通函数调用时的返回值
2.===

解析:Date作为普通函数调用返回字符串,作为构造函数调用返回Date实例对象。因而a为字符串类型,b和c为Date类型,但是b和c为两个不同的实例对象,指向的地址不同,因而“b===c”返回false。其余两个等号左右两边的数据类型都不相同,自然都返回false。

答案:[false, false, false]

第四十题

var min = Math.min(), max = Math.max()min < max

考察知识点:
1.Math.min
2.Math.max

解析:min返回一组数据中的最小值,max返回一组数据中的最大值。但是本题min和max都没有参数,在这种情况下,min返回+Infinity,而max返回-Infinity。因而,“min < max”返回false。

答案:false

第四十一题
function captureOne(re, str) {  var match = re.exec(str);  return match && match[1];}var numRe  = /num=(\d+)/ig,    wordRe = /word=(\w+)/i,    a1 = captureOne(numRe,  "num=1"),    a2 = captureOne(wordRe, "word=1"),    a3 = captureOne(numRe,  "NUM=2"),    a4 = captureOne(wordRe,  "WORD=2");[a1 === a2, a3 === a4]

考察知识点:
1.exec

解析:当正则表达式使用“g”标记时,执行exec时,查找的起点为上一次执行exec后lastIndex的值。而正则表达式中不带“g”标记的,每次重头查找。由于numRe中带“g”,所以a1的值为1, a3的值为null。而wordRe中不带“g”,所以a2的值为1,a4的值为2。

答案:[true, false]

第四十二题
var a = new Date("2014-03-19"),    b = new Date(2014, 03, 19);[a.getDay() === b.getDay(), a.getMonth() === b.getMonth()]

考察知识点:

  1. Date

解析:这题有点让人难受,由于第一种写法返回的是正确日期,而第二种写法的月份从0开始索引。因而第一种写法表达的是2014年3月19号星期三,而第二种写法表达的是2014年4月19号星期六。在getDay这块也有坑,getDay返回的是星期几,因而“a.getDay()”的值为3,而“b.getDay()”的值为6,假如想获取Date实例对象当前月份的天数,要使用date函数。
真难受。。

答案:[false, false]

第四十三题
if ('http://giftwrapped.com/picture.jpg'.match('.gif')) {  'a gif file'} else {  'not a gif file'}

考察知识点:
1.String.prototype.match()

解析:这题比较简单。假如match中传入的obj不是正则表达式对象,JS会通过 new RegExp(obj) 将其转换成一个正则表达式对象。假如match参数为空,则直接返回[""]。回到本题,match内的参数.gif就被转换成/.gif/,因而可以匹配。

答案:”a gif file”

第四十四题
function foo(a) {    var a;    return a;}function bar(a) {    var a = 'bye';    return a;}[foo('hello'), bar('hello')]

考察知识点:
1.函数内部变量的公告

解析:送分题。直接上等价写法:

function foo(a) {  a;  return a}function bar(a) {  a = 'bye';  return a;}

答案:[“hello”, “bye”]


JavaScript真让人头大

Have fun!

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » JavaScript Puzzlers详解

发表回复