JavaScript Puzzlers! (javascript的魅力!)
今天按例刷微博,忽然看到一个关于javascript的测试,试了一下,简直被虐成狗好吧==。
因为都是关于javascript的一些语法细节上的,平时很容易忽视,所以把题目贴上来和大家分享一下。
题目
No.1
以下JavaScript表达式的结果是?
1 | ["1", "2", "3"].map(parseInt) |
这是因为数组的map
方法传的参数依次为item, index, array
(数组的每一项, 每一项的索引, 原数组),而parseInt
方法则只接受2个参数string, radix
前一个表示解析的字符串, 后一个表示解析的基数。
No.2
以下JavaScript表达式的结果是?
1 | [typeof null, null instanceof Object] |
对于typeof null
来讲,始终会返回object
,记住就好!
No.3
以下JavaScript表达式的结果是?
1 | [ [3,2,1].reduce(Math.pow), [].reduce(Math.pow) ] |
结果是[an error]
reduce
在一个没有初始化值的空数组上面调用会抛出错误。
No.4
以下JavaScript表达式的结果是?
1 | var val = 'smtg'; |
+
操作符比三元运算符有更高的优先级,所以最后的结果是Something
, 这里有关于javascript的运算符优先级
No.5
以下JavaScript表达式的结果是?
1 | var name = 'World!'; |
这里为了便于观看结果,我把console
改为innerHTML
方便大家查看结果,原理是一样的。这里想要说的就是javascript中的变量声明提前,在javascript里面没有块级作用域,所以对于这个立即执行匿名函数来说真实的过程是var name
会提到函数最前面,在if判断的时候是已经声明了变量但是未赋值,这种情况下变量默认取得undefined
No.6
以下JavaScript表达式的结果是?
1 | var END = Math.pow(2, 53); |
这个结果不好展示,程序会一直停留在for循环中,这是因为2^53
对于javascript来说是它能表示的最大值,所以i永远也不可能大于END,这就造成无限循环。
No.7
以下JavaScript表达式的结果是?
1 | var ary = [0,1,2]; |
filter会默认跳过这些值为undefined
的数组项,所以返回一个空数组,这也是上面的结果点击没有任何显示的原因。
No.8
以下JavaScript表达式的结果是?
1 | var two = 0.2 |
javascript没有精确度,即使有些时候一些计算结果看起来是正确的。
No.9
以下JavaScript表达式的结果是?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function 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'));
在switch
语句中使用的是 ===
全等判断,而new String('A') !== "A"
No.10
以下JavaScript表达式的结果是?
What is the result of this expression? (or multiple ones)
1 | function showCase2(value) { |
String('a')
返回的是一个基本字符串类型,typeof String('A') === 'string'
,而实用new
操作符则会返回String Object
No.11
以下JavaScript表达式的结果是?
1 | function isOdd(num) { |
Infinity % 2
返回NaN
,-9 % 2
则返回-1
No.12
以下JavaScript表达式的结果是?
1 | parseInt(3, 8) |
parseInt
的第二个参数表示要解析的数字的基数,当为0或没有时默认以10进制来解析。所以第一个和第三个都能解析为3,但是对于第二个表达式3
不能解析为以2
为基数的数字,故返回NaN
,点击这里查看parseInt知识
No.13
以下JavaScript表达式的结果是?
1 | Array.isArray( Array.prototype ) |
Array.prototype
竟然是数组!!!记住。 你可以试一下打开控制台console.log(Object.prototype.toString.call(Array.prototype)
返回的结果是"[object Array]"
No.14
以下JavaScript表达式的结果是?
1 | var a = [0]; |
[0]
作为一个布尔值返回true
,但是在判断的时候却是会返回false
.
No.15
以下JavaScript表达式的结果是?
1 | [ ]==[ ] |
对于引用类型来说,变量里面仅仅是保存了指向对象在堆内存的指针而已,所以判断引用类型是否相等时是根据变量中的指针是否相等来判断的,这里时2个不同的数组对象,虽然他们表面上看起来一样,但是在内存中占据着不同的空间位置。
No.16
以下JavaScript表达式的结果是?
1 | '5' + 3 |
对于+
操作符,当右边的值为字符串时候,它会将右边的变量转为字符串,所以'5' + 3
就转为'5' + '3'
,而对于-
操作符号则是会将两边的变量都转为number
类。
No.17
以下JavaScript表达式的结果是?
1 | 1 + - + + + - + 1 |
也是考察javascript中的运算符的优先级,a++
后置递增高于一元加法+
,一元加法高于前置递增++a
No.18
以下JavaScript表达式的结果是?
1 | var ary = Array(3); |
map
方法仅仅返回那些经过初始化的数组项,向Array
构造函数传入的参数表示新生成的数组有三项。
所以结果是[1, undefined, undefined]
No.19
以下JavaScript表达式的结果是?
1 | function sidEffecting(ary) { |
在函数内部有一个特殊的类数组对象arguments(注意区分和数组的不同)
,在函数内部通过argument[i]
来访问传进函数内部的参数,任何对参数的更改都会反映到arguments
对象上,同理,任何对arguments
的更改也会反应到本地作用域参数上。
No.20
以下JavaScript表达式的结果是?
1 | var a = 111111111111111110000, |
javascript缺乏精度会同时影响较大值和较小值。(这里是说javascript不能做精确的计算么?)
No.21
以下JavaScript表达式的结果是?
1 | var x = [].reverse; |
结果是window
,[].reverse
会返回this
的值,当返回的值没有显示的赋值时this
将会指代当前默认的窗口windows
作者原译[].reverse will return this and when invoked without an explicit receiver object it will default to the default this AKA window
No.22
以下JavaScript表达式的结果是?
1 | Number.MIN_VALUE > 0 |
Number.MIN_VALUE is the smallest value bigger than zero, -Number.MAX_VALUE gets you a reference to something like the most negative number.
Number.MIN_VALUE
是比0大的最小值,如果想要表示最小的负数应该使用-Number.MAX_VALUE
来表示。
No.23
以下JavaScript表达式的结果是?
1 | [1 < 2 < 3, 3 < 2 < 1] |
对于<
运算符来说结合性时从左到右的,1 < 2 < 3
先转化为 true < 3
在转化为true
,比较运算符会讲布尔值转为数值,true => 1, false => 0
,所以结果也就不难预料了~
No.24
以下JavaScript表达式的结果是?
1 | 2 == [[[2]]] |
在比较==
两端的值时,当其中一个为对象时会调用对象上的valueOf()
方法得到基本类型值,然后再进行比较。
No.25
以下JavaScript表达式的结果是?
1 | 3.toString() |
3.x is a valid syntax to define “3” with a mantissa of x, toString is not a valid number, but the empty string is.
这里的意思是说3.
这样的定义就相当于定义了一个字符串'3'
所以可以调用toString
方法,其他2个调用的时候会发生错误。
No.26
以下JavaScript表达式的结果是?
1 | (function(){ |
一个立即执行函数,这里主要看var x = y = 1
,其实这里的可以看作var x = 1; y = 1
那这样的话就会默认定义一个全局变量y
所以在控制台就能取得y
的值,至于x
的值,开玩笑,这个妥妥的闭包,函数外面无法访问闭包定义的局部变量。
No.27
以下JavaScript表达式的结果是?
1 | var a = /123/, |
Per spec Two regular expression literals in a program evaluate to regular expression objects that never compare as === to each other even if the two literals' contents are identical.
正则对象,引用类型,所以相等的评判标准当然是指针指向的是同一个堆对象。
No.28
以下JavaScript表达式的结果是?
1 | var a = [1, 2, 3], |
数组不能用==
或===
比较,因为数组时引用类型,同上题。
No.29
以下JavaScript表达式的结果是?
1 | var a = {}, b = Object.prototype; |
a.prototype
属性不存在,Object.prototype
指向的是所有Object
实例的原型对象。Object.getPrototypeOf()
可以取得一个对象的原型
No.30
以下JavaScript表达式的结果是?
1 | function f() {} |
f
的原型是Function.prototype
。f.prototype
是f
当作构造器构造的对象的原型对象。
No.31
以下JavaScript表达式的结果是?
1 | function foo() { } |
foo.name
函数的name
属性是只读的,但是为什么不回抛出错误呢?
No.32
以下JavaScript表达式的结果是?
1 | "1 2 3".replace(/\d/g, parseInt) |
传入parseInt
中的参数有2个,第一个是正则对象匹配到的数字,第二个参数是数字在字符串中的位置,依次传给parseInt
的参数为[1, 0] [2, 2] [3, 4]
。所以答案是1, NaN, 3
No.33
以下JavaScript表达式的结果是?
1 | function f() {} |
作者的答案:"f", "Empty", "function", error
解释:The function prototype object is defined somewhere, has a name, can be invoked, but it's not in the current scope.
函数原型对象定义的某个地方,有一个名字,可以被调用,但它不是在当前范围内。
这个地方有点意思,我发现typeof 在对eval()使用的时候有一些有趣的现象,我稍后会发博文来讲解eval的前世今生。
No.34
以下JavaScript表达式的结果是?
1 | var lowerCaseOnly = /^[a-z]+$/; |
传入test
的参数arguments
将会通过toString
转化为'null'
和'undefined'
。所以当然符合正则匹配~
No.35
以下JavaScript表达式的结果是?
1 | [,,,].join(", ") |
javascript定义数组的时候运行以逗号结尾,但这样定义的数组将会获得3个undefined
值
No.36
以下JavaScript表达式的结果是?
1 | var a = {class: "Animal", name: 'Fido'}; |
你可以点击查看结果,这个结果可能比较特殊,它视你使用的浏览器类型,如果是safari/chrome/firefox/
会正常获取到class
属性,但是对于IE来说可能会抛出一个异常,这是因为在javascript中class
是一个保留字。
No.37
以下JavaScript表达式的结果是?
1 | var a = new Date("epoch") |
作者解释:You get "Invalid Date", which is an actual Date object (a instanceof Date is true). But invalid. This is because the time is internally kept as a Number, which in this case it's NaN.
a
的确是一个日期对象,但是在日期对象内部要表示一个number
数值,但是传入的参数的确会使得这个数值转变为NaN
No.38
以下JavaScript表达式的结果是?
1 | var a = Function.length, |
Function.length
被定义为1,而新的函数b的length属性为0,因为参入的参数个数为0。
No.39
以下JavaScript表达式的结果是?
1 | var a = Date(0); |
When Date is invoked as a constructor it returns an object relative to the epoch (Jan 01 1970). When the argument is missing it returns the current date. When it is invoked as a function, it returns a String representation of the current time.
当日期构造函数没有使用new
操作符调用时,它会返回当前日期的字符串,当当作构造器调用并且没有参入参数的情况下将会返回当前时间作为参数的日期对象。当传入的参数为0时表示的就是1970年1月1日的日期对象。typeof a === "string" typeof b ==="object" typeof c === "object"
No.40
以下JavaScript表达式的结果是?
1 | var min = Math.min(), max = Math.max() |
当没有传入参数的时候Math.min()
返回Infinity
,Math.max()
将会返回-Infinify
remember it!
No.41
以下JavaScript表达式的结果是?
1 | function captureOne(re, str) { |
这个结果看起来有些奇怪,但是这个的确是我们会经常忽略的细节!当正则对象带有i
标志代表着忽略大小写,这个没问题,但是当带有g
标志的时候结果就有些不一样的,它不会从一个字符串开始处进行匹配而是在上次匹配结束的地方开始!!!也就是a3
会出一些问题,他不会得到我们希望得到的结果。
No.42
以下JavaScript表达式的结果是?
1 | var a = new Date("2014-03-19"), |
hava fun!!!
这里要获得某个月的第几天应该使用的是getDate()
方法!对于月份是从0开始计时,1月代表0,2月代表1以此类推。
No.43
以下JavaScript表达式的结果是?
1 | if ('http://giftwrapped.com/picture.jpg'.match('.gif')) { |
匹配到的字符串是http://giftwrapped.com/picture.jpg
中的/gif
。
No.44
以下JavaScript表达式的结果是?
1 | What is the result of this expression? (or multiple ones) |
在javascript中变量重复声明是会被忽略的,除非在声明的同时对变量进行赋值,这样会完全覆盖原来的变量值,这里的答案也就显而易见了。
结语
任何一门语言,都有属于它自己的魅力,javascript也不例外,作为一名前端工程师,我们应该为javascript拥有如此魅力而高兴。
子曰:温故而知新。时刻注意javascript的魅力吧!!!
有任何疑问欢迎E-mail:xushujun_sunny@163.com