前言
題目來自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) // 1
parseInt("2", 1) // NaN
parseInt("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) // 3
Math.pow(3, 2) // 9
Math.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不會回調數組中的未定義元素。驗證如下:
注意區分未定義元素與undefined元素,filter函數的callback是會回調數組中undefined元素的,驗證如下:
因為本題中的數組不存在undefined元素,所以不存在通過條件篩選的元素,最終返回[]。
答案:[]
第八題
var two = 0.2
var one = 0.1
var eight = 0.8
var six = 0.6
[two - one == one, eight - six == two]
考查知識點:
1.浮點數的精度及表達方式
解析:這題比較簡單,但為了說明原因還是啰嗦一下。老司機都知道,浮點數的運算會存在精度缺失問題,為什么會精度缺失?我們知道計算機中的數值是以二進制方式存儲的,以3.14的小數部分0.14為例,轉換如下:
// 0.14
0.14 * 2 = 0.28 0
0.28 * 2 = 0.56 0
0.56 * 2 = 1.12 1
0.12 * 2 = 0.24 0
0.24 * 2 = 0.28 0
0.48 * 2 = 0.96 0
0.96 * 2 = 1.92 1
0.92 * 2 = 1.84 1
...
所以0.14取8位二進制有效數字的表達式為0.00100011,顯然當小數部分轉成二進制時,可能存在有效數字范圍內無法精確表達的問題,因此浮點數運算會存在精度缺失問題。
回到本題,來計算一下0.1、0.2、0.6、0.8轉成二進制是怎樣表達的:
// 0.1
0.1 * 2 = 0.2 0
0.2 * 2 = 0.4 0
0.4 * 2 = 0.8 0
0.8 * 2 = 1.6 1
0.6 * 2 = 1.2 0
0.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構造函數生成的字符串對象與原生字符串不相等,驗證如下
- 原生字符串類型為"string",字符串對象類型為"object"
- 通過new調用String構造函數生成的是字符串對象,直接調用String構造函數生成的是原生字符串
除此之外,字符串對象與原生字符串在作為eval參數時,表現也是不同的:
- 當參數為原生字符串時,eval會將字符串當做源代碼處理
- 當參數為字符串對象時,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。再來做個試驗:
只要將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語言用“++”操作符出的爛題一樣,沒啥實際意義
可以看到,JS中允許加減運算符連接使用,但是不允許出現兩個加或者兩個減。當加減運算符連接使用時,和單獨使用減法運算符是一致的。
但是,當加減運算符中間出現空格時,此時兩個加號與兩個減號是可以出現的,運算規則相當于“正正得正,負負得正,正負得正,負正得正”。
回到本題,可拆解為如下運算:
1 + (- + + + - + 1)
括號內運算結果為1,所以本題等價于計算1+1的值,結果為2
答案:2
第十八題
var ary = Array(3);
ary[0]=2
ary.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",后兩個仍為未定義元素。
答案:長度為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)
}
可見,只要函數表達式中存在默認參數,不管在調用的時候是否給函數的默認參數傳值,這個參數和對應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;
考查知識點:
- 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 < 3
true < 3
1 < 3
true
// 3 < 2 < 1
false < 1
0 < 1
true
答案:[true, true]
第二十四題
// the most classic wtf
2 == [[[2]]]
考察知識點:
1.==
解析:送分題。==
運算符在等號兩邊類型不一致時會進行隱式轉換,直到轉換為相同類型再做比較。數值類型與引用類型進行比較,會將引用類型轉換成數值類型。因此等號右邊最終被轉換為2,此時相當于:
// 2 == [[[2]]]
2 == [[2]]
2 == [2]
2 == 2
答案:true
第二十五題
3.toString()
3..toString()
3...toString()
考察知識點:
1.浮點數的表示方法
解析:這一題也不難,先看代碼
因此,.3
與3.
都是合法的表達方式,此時相當于省略了數字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 == b
a === b
考察知識點:
1.==
2.===
解析:送分題。正則是對象,對于==
,等號兩邊類型相等,但不是指向同一個對象,所以返回false。對于===
,直接比較等號兩端是否指向同一個地址,由于是不同對象,所以地址不同,返回false。
答案:false, false
第二十八題
var a = [1, 2, 3],
b = [1, 2, 3],
c = [1, 2, 4]
a == b
a === b
a > c
a < 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().length
a === 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()]
考察知識點:
- Date
解析:這題有點讓人難受,因為第一種寫法表達的是2014年3月19號星期三,而第二種寫法表達的是2014年4月19號星期六。在getDay這塊也有坑,getDay返回的是星期幾,因此“a.getDay()”的值為3,而“b.getDay()”的值為6,如果想獲取Date實例對象當前月份的天數,要使用date函數。再說說getMonth的坑,getMonth確實是獲取月份的,但是month是從0開始數的,所以獲取到的月份會比實際月份少一個月。就本題而言,a.getMonth()獲取到的月份是2,b.getMonth獲取到的月份是3。
真難受。。
答案:[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!