今天這篇文章整理了幾道常見的Javascript筆試題,這些題目看似簡單,但一不注意就會出錯,來看看你都會做嗎?
Javascript
我們都知道typeof是用于檢測一個變量的數據類型的,instanceof是用于判斷某個變量是否是指定類型的實例。
我們來看看下面的代碼。
題目1
在Javascript中Null作為一種單獨的數據類型,其類型只有一個值null。Null是一個特殊的Object類型,因此在typeof null時,返回的是‘object’。
既然typeof null返回的是object,那么null instanceof Object是不是就返回true呢?結果是否定的。
由于Null的特殊性,null值的產生并不是通過Object原型鏈的,通過Object類型的原型鏈不能追溯到Null值,因此null instanceof Object返回值為false。
第二道題是reduce方法與Math.pow()方法結合,確定輸出結果,代碼如下。
題目2
首先我們來看看reduce方法的使用,它的API如下。
recude方法
接收一個回調函數,對數組中的元素依次進行處理,從參數名可以很容易看出previousValue為上一次計算結果的值,currentValue表示當前處理值。
同時可選擇接收一個初始值initialValue,如果這個initialValue傳遞了,那么第一次調用回調函數時的previousValue就等于initialValue,如果沒有傳遞則previousValue就等于數組的第一個值。
理解上述的原則后,我們再來看看這道題目。
題目2中的回調函數是Math.pow(),Math.pow(a, b)表示的是a的b次方。其中a就是reduce回調函數的previousValue,b就是currentValue了。
在第一段代碼中,沒有傳遞initialValue,則previousValue為3,currentValue為2,那么計算后是Math.pow(3, 2)=9。
同理在第二次計算時,previousValue為9,currentValue為1,則計算結果時Math.pow(9, 1)=9。
因此第一段代碼最終結果是9。
再來看看第二段代碼,不同于第一段的是它傳遞了initialValue為0,那么在進行第一次計算時,previousValue為0,currentValue為3,則第一次計算是Math.pow(0, 3)=0;
接下來進行第二次計算,previousValue為上一次計算結果0,currentValue為2,則計算結果是Math.pow(0, 2)=0;
同理最后一次計算,previousValue為0,currentValue為1,計算結果是Math.pow(0, 1)=0;
因此第二段代碼最終結果是0。
第三道題考察的是Boolean與[0]的用法,代碼如下所示。
題目3
代碼首先定義了一個變量a,為只有一個元素0的數組。
然后通過if語句判斷[0]是否為true,進而輸出不同的值。
這道題的核心在于if語句中的返回結果,需要注意的是,if語句的判斷結果實際是利用了Boolean的構造方法,看看利用Boolean的構造方法能否將if語句中的值轉化為true。
根據Boolean構造方法的定義,如果邏輯對象無初始值或者其值為 0、-0、null、""、false、undefined 或者 NaN,Boolean構造方法會返回false,否則返回true。
從題目中我們可以看出if語句中的值為[0],不滿足任何一個返回false值的條件,因此Boolean([0])=true,那么if判斷語句就進入到true的判斷中。
那么就會執行console.log(a==true),注意這里的判斷并不會調用Boolean的構造方法,而是直接比較[0]與true。
這個時候true會轉換為1,[0]會進行隱式轉換,[0]會轉換為'0',然后轉換為數字0,相當于比較0與1的值。
很明顯0與1比較返回false,那么最終的結果是輸出false。
題目4主要考察的是算術運算符與正負運算符,題目代碼如下。
題目4
很多人看到這么多加減號,都以為這題目是不是出錯了?其實是沒有問題的。
遇到這樣的題目,只要記住以下這點內容:
在數字后面的第一個符號為算術運算符加/減,其他加減號都是正負數轉換的運算符。
第一行代碼可以拆分成這樣的內容。
1 + (- + + + - + 1)
優先處理后面括號中的值,其中的加減號表示正負數轉換的。
從右往左看,首先是+1,然后是負號-,變為-1,在連續三個正號+,還是-1,最后是一個負號-,變為+1。
其實最后計算就是1 + 1=2。
懂得這個原理后,我們直接看第三行代碼,拆分后變成這個樣子。
1 - (- + + + - - - - + + 1) + (1) + (- - - - + - 1)
對括號中的數優先處理,第一個括號中得到的值是-1,第二個括號中得到的值是1,第三個括號中得到的值是-1。
所以實際的運算是1-(-1)+1+(-1)=2。
在JavaScript中有一個arguments對象,表示的是傳遞給函數的參數對象,這道題目也與arguments有關。
題目5
我們來分析下上面的代碼。
定義一個函數,用于將數組的第三個元素值賦給第一個元素。
定義第二個函數,傳遞的參數先賦初始值,然后經過第一個函數處理。
計算三個參數相加的和并返回。
在函數中arguments是直接代表該函數接收的參數列表的,上面的bar函數內部的arguments實際就是[a, b, c]。
我們需要記住以下這條規則,在函數沒有接收變長參數(...擴展運算符),默認參數和結構賦值等ES6的新特性時,arguments對象的值和參數的值是相互影響的。
因此第一個函數中將第三個元素值賦給第一個元素是生效的,那么c=10,a=10,b=1,所以最終結果返回21。
但是如果使用了ES6中的幾個新特性時,arguments對象的值和參數值是不會相互受影響的。
我們來看看以下的例子。
使用變長參數
只需要將上面的題目做簡單的修改,第一個函數的參數ary變為...ary即可。
修改1-變長參數
使用變長參數后,對ary進行修改,不會影響到原來函數的參數a,b,c的值,所以a=1, b=1,c=10,最終結果返回12。
使用默認參數
同樣對以上原始題目做簡單的修改,對c使用默認參數。
默認參數
修改后的代碼中,給c設定默認值為2。使用默認參數后情況與上面一種一樣,最終的結果也是返回12。
使用解構賦值
對以上代碼進行簡單的改造,得到如下使用解構賦值的代碼。
使用解構賦值
同樣最終的結果返回12。
今天這篇文章講解了幾道JavaScript相關的題目,雖然代碼量都很少,但是理解起來卻不是那么容易,需要慢慢消化,希望今天的文章對你們有幫助噢~
avaScript作為一門如此靈活的語言,自然在編碼時給我們帶來了很多方便,但方便的同時,也衍生出了很多變態的語法,下面我們來梳理一些常見的變態語法,希望你下次在某位大牛的代碼中看到這樣的東西,不要驚掉下巴。
?
NO.1
Number.prototype.add=function(n){
return this+n;
}
2["add"](3)
最后一句話是什么玩意兒?好像沒看懂呢? 我們來運行一下看看:
擦? 居然執行了?結果是5,看上去似乎對2和3做了加法。不是說變量名不能數字開頭么?這是怎么回事?瀏覽器抽風了?
實際上js有很多不能說的秘密,其中一個就叫做自動裝箱,這是引用java里的叫法。也就是說,當我們試圖2[“add”]的時候,這個數字2已經不再是2了,它被自動轉換成了Number對象,跟java中的包裝類型是一個意思。
等價于這樣寫:
new Number(2)
而對象是可以通過[“prop"]這種形式來獲取屬性的,于是我們就不難推理了~
2["add"] 相當于new Number(2).add
最終變成
new Number(2).add(3);
結果是 5
NO.2
+function(){;}()
這又是個什么玩意兒?函數前面帶個+號? 這難道是自動類型轉換?等等,里面是個;號? 后面還有一對( )?
先不要著急驚訝,其實還有很多,例如:
-function(){;}()
!function(){;}()
~function(){;}()
void function(){;}()
new function(){;}()
delete function(){;}()
var i=function(){;}()
1 && function(){;}()
0 || function(){;}()
1 & function(){;}()
1 | function(){;}()
1 ^ function(){;}()
1, function(){;}()
這些“喪盡天良”的寫法是誰發明的?!你給我站出來,我保證不打死你!(此處作者冷靜了5分鐘)……
接下來說說它的原理吧!
首先 , ;號本身也是一條語句,相信大多數同學應該是知道的,就不多說了。其次,一個函數的自調用,如果寫成這樣:
錯誤的原因在于,函數聲明和函數調用是不可以混在一起的,所以通常的寫法是:
這并不是把函數當成了一個整體來運行,這里其實還有一個不能說的秘密。
( )這個符號,在js里是運算符。(A)的結果是返回表達式A
所以它的出現,讓這個匿名函數從聲明變成了執行,也就是編譯期間瀏覽器不會提前準備它,自然就沒有語法錯誤。而幾分鐘前我們看到的那些喪心病狂的寫法,其實原理都一樣,通過運算符把聲明變成執行。當然這些符號都不會影響函數的正常執行結果。
但是問題又來了,這種泯滅人性的寫法,現在居然還挺常見的,例如:
沒錯,這就是著名的bootstrap的js源碼,連它都是這么寫的,莫非真有什么好處?
通過在網上查詢大量的資料,我還真發現有人專門對此做了研究,將上面這些寫法全部在各個瀏覽器中間做了壓力測試,發現+function( ){;}( ) 執行速度最快,比(function( ){})( )要快出好幾倍,而 new function( ){;}( ) 執行速度最慢。
不過為了追求效率而把代碼寫成這樣到底值不值,那只能你自己去判斷了。
NO.3
!!a
這又是什么鬼啊?!!a 實際上等價于 a || false
由于js中所有的內容都是可以跟布爾類型互換的,這也是js特別讓人費解的地方,比如
if(window.VBArray){…}
可以用來判斷IE瀏覽器,因為對象存在時,等價于true,undefined等價于false,但是!很多時候我們判斷一個屬性是否存在,并不需要馬上作出反應,而是將結果告知他人,比如說有個函數,test(hasSuperman),函數規定調用時需要傳入一個布爾類型,告知它superman是否存在,你可能會這樣寫:
if(window.superman){
test(true);
} else {
test(false);
}
但你最好不要這么寫:
test(window.superman);
因為你并不知道test函數內部發生了什么,所以很難預料會不會產生錯誤,因此最好的寫法是這樣:
test(!!window.superman);
通過兩次取反,保證了值沒有變化,但類型已經被轉為了布爾類型。好吧,似乎這么寫還有點道理。
NO.4 最短IE(6,7,8)判定
if(!-[1,]){
//判斷IE6,7,8
}
它的原理實際上是利用了IE的bug。
當我們寫下一個數組 [1,].length
在IE中 [1,].length -------> 2
在非IE中 [1,].length -------> 1
當我們試圖打印[1,],相當于調用toString()方法
在IE中 [1,] -------> "1,"
在非IE中 [1,] -------> "1"
當我們給它加上負號-[1,]
在IE中 -[1,] -------> NaN
在非IE中 -[1,] -------> -1
當我們對它進行取反!-[1,]
在IE中 !-[1,] -------> true
在非IE中 !-[1,] -------> false
這樣我們就可以判斷是否為IE瀏覽器了,這個bug一直到IE9之后才消失的。
好了,這次的變態語法就先講這么多,以后碰到更新鮮的再來給大家更新,拜拜。
編輯:千鋒web前端
今天這篇文章整理了幾道常見的Javascript筆試題,這些題目看似簡單,但一不注意就會出錯,來看看你都會做嗎?
Javascript
我們都知道typeof是用于檢測一個變量的數據類型的,instanceof是用于判斷某個變量是否是指定類型的實例。
我們來看看下面的代碼。
題目1
在Javascript中Null作為一種單獨的數據類型,其類型只有一個值null。Null是一個特殊的Object類型,因此在typeof null時,返回的是‘object’。
既然typeof null返回的是object,那么null instanceof Object是不是就返回true呢?結果是否定的。
由于Null的特殊性,null值的產生并不是通過Object原型鏈的,通過Object類型的原型鏈不能追溯到Null值,因此null instanceof Object返回值為false。
第二道題是reduce方法與Math.pow()方法結合,確定輸出結果,代碼如下。
題目2
首先我們來看看reduce方法的使用,它的API如下。
recude方法
接收一個回調函數,對數組中的元素依次進行處理,從參數名可以很容易看出previousValue為上一次計算結果的值,currentValue表示當前處理值。
同時可選擇接收一個初始值initialValue,如果這個initialValue傳遞了,那么第一次調用回調函數時的previousValue就等于initialValue,如果沒有傳遞則previousValue就等于數組的第一個值。
理解上述的原則后,我們再來看看這道題目。
題目2中的回調函數是Math.pow(),Math.pow(a, b)表示的是a的b次方。其中a就是reduce回調函數的previousValue,b就是currentValue了。
在第一段代碼中,沒有傳遞initialValue,則previousValue為3,currentValue為2,那么計算后是Math.pow(3, 2)=9。
同理在第二次計算時,previousValue為9,currentValue為1,則計算結果時Math.pow(9, 1)=9。
因此第一段代碼最終結果是9。
再來看看第二段代碼,不同于第一段的是它傳遞了initialValue為0,那么在進行第一次計算時,previousValue為0,currentValue為3,則第一次計算是Math.pow(0, 3)=0;
接下來進行第二次計算,previousValue為上一次計算結果0,currentValue為2,則計算結果是Math.pow(0, 2)=0;
同理最后一次計算,previousValue為0,currentValue為1,計算結果是Math.pow(0, 1)=0;
因此第二段代碼最終結果是0。
第三道題考察的是Boolean與[0]的用法,代碼如下所示。
題目3
代碼首先定義了一個變量a,為只有一個元素0的數組。
然后通過if語句判斷[0]是否為true,進而輸出不同的值。
這道題的核心在于if語句中的返回結果,需要注意的是,if語句的判斷結果實際是利用了Boolean的構造方法,看看利用Boolean的構造方法能否將if語句中的值轉化為true。
根據Boolean構造方法的定義,如果邏輯對象無初始值或者其值為 0、-0、null、""、false、undefined 或者 NaN,Boolean構造方法會返回false,否則返回true。
從題目中我們可以看出if語句中的值為[0],不滿足任何一個返回false值的條件,因此Boolean([0])=true,那么if判斷語句就進入到true的判斷中。
那么就會執行console.log(a==true),注意這里的判斷并不會調用Boolean的構造方法,而是直接比較[0]與true。
這個時候true會轉換為1,[0]會進行隱式轉換,[0]會轉換為'0',然后轉換為數字0,相當于比較0與1的值。
很明顯0與1比較返回false,那么最終的結果是輸出false。
題目4主要考察的是算術運算符與正負運算符,題目代碼如下。
題目4
很多人看到這么多加減號,都以為這題目是不是出錯了?其實是沒有問題的。
遇到這樣的題目,只要記住以下這點內容:
在數字后面的第一個符號為算術運算符加/減,其他加減號都是正負數轉換的運算符。
第一行代碼可以拆分成這樣的內容。
1 + (- + + + - + 1)
優先處理后面括號中的值,其中的加減號表示正負數轉換的。
從右往左看,首先是+1,然后是負號-,變為-1,在連續三個正號+,還是-1,最后是一個負號-,變為+1。
其實最后計算就是1 + 1=2。
懂得這個原理后,我們直接看第三行代碼,拆分后變成這個樣子。
1 - (- + + + - - - - + + 1) + (1) + (- - - - + - 1)
對括號中的數優先處理,第一個括號中得到的值是-1,第二個括號中得到的值是1,第三個括號中得到的值是-1。
所以實際的運算是1-(-1)+1+(-1)=2。
在JavaScript中有一個arguments對象,表示的是傳遞給函數的參數對象,這道題目也與arguments有關。
題目5
我們來分析下上面的代碼。
定義一個函數,用于將數組的第三個元素值賦給第一個元素。
定義第二個函數,傳遞的參數先賦初始值,然后經過第一個函數處理。
計算三個參數相加的和并返回。
在函數中arguments是直接代表該函數接收的參數列表的,上面的bar函數內部的arguments實際就是[a, b, c]。
我們需要記住以下這條規則,在函數沒有接收變長參數(...擴展運算符),默認參數和結構賦值等ES6的新特性時,arguments對象的值和參數的值是相互影響的。
因此第一個函數中將第三個元素值賦給第一個元素是生效的,那么c=10,a=10,b=1,所以最終結果返回21。
但是如果使用了ES6中的幾個新特性時,arguments對象的值和參數值是不會相互受影響的。
我們來看看以下的例子。
使用變長參數
只需要將上面的題目做簡單的修改,第一個函數的參數ary變為...ary即可。
修改1-變長參數
使用變長參數后,對ary進行修改,不會影響到原來函數的參數a,b,c的值,所以a=1, b=1,c=10,最終結果返回12。
使用默認參數
同樣對以上原始題目做簡單的修改,對c使用默認參數。
默認參數
修改后的代碼中,給c設定默認值為2。使用默認參數后情況與上面一種一樣,最終的結果也是返回12。
使用解構賦值
對以上代碼進行簡單的改造,得到如下使用解構賦值的代碼。
使用解構賦值
同樣最終的結果返回12。
今天這篇文章講解了幾道JavaScript相關的題目,雖然代碼量都很少,但是理解起來卻不是那么容易,需要慢慢消化,希望今天的文章對你們有幫助噢~
*請認真填寫需求信息,我們會在24小時內與您取得聯系。