js筆試題系列之———基礎類型與運算符

  前端技術的發展速度你們有目共睹,js的ECMA標準也再也不是3的天下,但無論再怎麼山雨欲來風滿樓,基礎語法仍是得溫故而知新。不管你是初學則仍是多年js的編程者,均可以試着作作下面的測試題,我相信總仍是會有些收穫的。由於所有是本身總結和手打的,有紕漏錯誤之處請留言,謝謝。javascript

一:考察基本數據類型與運算符前端

(1)未定義變量問題java

var a;
console.log(typeof a); ==>undefined

  先以一個最多見也是最簡單的測試案例開始,未定義的變量或者未賦值則爲undefined編程

(2)++/--運算符問題數組

var a = '1a';
console.log(a++); ==>NaN

  ++操做符將對a變量隱式轉換爲number類型,字符串'1a'沒法正常轉換爲數字,因此返回NaN。函數

  這裏能夠總結出如下幾點:測試

  1. 除了+操做符之外,-、*、/、%、++、--都將隱式轉換參與運算的變量爲number類型,若是能正常轉換爲數字則返回該數字,不然返回NaN;spa

  2. 能正常轉換爲數字的有以下幾種狀況:prototype

    純數字類字符串如'123'、'1e2'(轉換爲1*10的2次方等於100);對象

    null參與運算轉換爲0(null-4等於-4,null+null等於0);

    boolean類型的true和false分別可轉換爲1和0;

  3. 只有可以轉換爲數字的變量才能參與++或--運算,不然將報錯,好比:  

console.log(3++); ==>報錯,常量不能直接運算++
var a = 3;
console.log(a++); ==>3

  其中有個特例:NaN++能夠正常返回結果,仍然是NaN

(3)+運算符之四則運算與字符合並

console.log(2+'1'); ==>'21'
console.log(2-'1'); ==>1
console.log(1+NaN); ==>NaN
console.log('1'+NaN); ==>'1NaN'

  1. +運算符有必要單獨一提,由於除了+之外的其它算術運算符,都會對參與運算的變量或值默認隱式轉換爲number,但+由於在js中還肩負着字符串合併的重大任務,因此它有特殊'國情':

    1.1 當+的左右兩邊均是數字類型時,則執行算術運算,好比1+2返回三、NaN+1返回NaN;

    1.2 當+的左右兩邊均是字符串類型時,則執行字符串合併,好比'1'+'2'返回'12';

    1.3 當+的左右兩邊一個是數字、一個是字符串類型時候,則先將數字轉換爲字符串再合併,好比1+'1'返回'11';

  2. 在實際開發過程當中,咱們使用+運算符基本上都是處理字符串類型或者數字類型的,因此上面的三種狀況可以應對大部分開發場景。可是當+運算符的左右兩邊出現了第三種數據類型時,狀況就會顯得複雜了(如下其它數據類型是指除了string和number的之外類型):

    2.1 其它數據類型+字符串類型

console.log(null+'1'); ==>'null1'
console.log(undefined+'1'); ==>'undefined1'
console.log([1,2]+'1'); ==>'121'
console.log((function(){})+'1'); ==>'function (){}1'
console.log(({})+'1'); ==>'[object Object]1'

  執行辦法:其它數據類型將被轉換爲字符串再合併,且對象類型將調用自身toString()方法轉換結果。另外,其實對象類型+運算不管另一個參與運算的值是否是字符串類型,都只能與它進行字符串合併操做,而不能是四則運算,下面會具體講到。

    2.3 其它數據類型+數字類型

console.log(null+1); ==>1
console.log(undefined+1); ==>NaN
console.log(true+1); ==>2
console.log([1]+1); ==>'11'
console.log((function(){})+1); ==>'function (){}1'
console.log(({})+1); ==>'[object Object]1'

  執行辦法:非對象類型將進行四則運算,而對象類型場景則仍然是字符串合併的操做。

    2.2 其它數據類型+其它數據類型

console.log(null+null); ==>0
console.log(undefined+undefined); ==>0
console.log(true+true); ==>2
console.log([1]+[2]); ==>'12'
console.log((function(){})+(function(){})); ==>'function (){}function (){}'
console.log(({})+({})); ==>'[object Object][object Object]'

  執行辦法:非對象類型將進行四則運算,而對象類型場景則仍然是字符串合併的操做。

  因此,關於有其它類型參與+運算的場景,咱們能夠再稍總結下最終的結果:只要有對象類型參與+運算,則永遠是作字符串合併;若是是null/undefined/boolean類型參與+運算,當另外一個參與運算的值爲字符串,則進行字符串合併,不然進行四則運算。

思考題:alert({name:'mofei'})

(4)+運算符之轉換數字問題

console.log(1+ +1); ==>2
console.log(1e+1+1); ==>11

  這個測試仍然是+運算,可是並無和上一個測試案例合併在一塊兒而是單獨出來,緣由很簡單:此+非彼+。

  +運算符實際上在js中有三種應用場景:轉換爲數字、四則運算加、字符串鏈接。在上一個測試案例中咱們講了後兩種應用場景,而這裏是則是對第一個應用場景的補充。關於轉換爲數字的理解也不難,咱們常常用a+''的寫法將一個變量轉換爲字符串類型,因此咱們也能夠利用+運算符將其它類型轉換爲數值類型,好比+null返回結果爲0。因此在這個案例中,1+ +1等同與1+1,由於後面那個+1其實就是將1轉換爲number類型,仍然是1,而1e+1+1等效於1e1+1,也就是11。

(5)除/取模運算符的極端場景問題

console.log(10/0); ==>Infinity
console.log(10%0); ==>NaN

  除0返回Infinity,對0取模(求除法運算的餘數,對2取模經常使用在判斷奇偶)返回NaN。

(6)!運算符問題

console.log(!!false); ==>false
console.log(!!4); ==>true
console.log(!!'false'); ==>true

  這裏考察了取反運算符。雙取反實際上就是將運算對象強制轉換爲boolean型,其中最後一個要注意'false'自己是個非空字符串,轉換爲布爾值爲true。

  大部分狀況下轉布爾值都是返回true,除了如下幾種狀況:false自己、null、nudefined、空字符串''、數字0、數字NaN

思考題:!!undefined 

(7)typeof運算符問題

console.log(typeof(0)); ==>number
console.log(typeof(NaN)); ==>number console.log(typeof('0')); ==>string console.log(typeof('false')); ==>string console.log(typeof(false)); ==>boolean console.log(typeof(undefined)); ==>undefined console.log(typeof(null)); ==>object console.log(typeof([1,2])); ==>object console.log(typeof(function(){})); ==>function

  這裏羅列了typeof能夠返回的全部可能值:number、string、boolean、undefined、object、function

  能夠總結的知識點是:

  1. 凡是帶上引號的typeof就是string,而不須要管裏面內容是什麼,好比不要誤覺得typeof('undefined')結果就是undefined

  2. null、數組array、普通對象的typeof返回爲object

  3. 函數自己也是對象,可是它的typeof返回爲特殊的function

  4. 並不能依靠typeof所有分別出變量到底屬於8種數據類型中的哪種(好比數組和普通對象),可是能夠直接區分基本數據類型中的四種類型:number、string、boolean、undefined,若是要所有區分類型能夠結合其它方法共同判斷(如instanceof、constructor),或者使用Object.prototype.toString.call(...)

 (8)寬鬆等於嚴格等問題

console.log(null == undefined); ==>true
console.log(false == ''); ==>true
console.log(false === !true); ==>true
console.log([] === []); ==>false

  關於等於運算符==:比較雙方是否相等,這種比較是容許進行類型轉換的,好比1 == '1'將返回true,至於它們是怎樣進行類型轉換能夠參照《javascript權威指南》75頁有很是詳細的描述,這裏再也不闡述了。嚴格等運算符常常在對象的比較中被考察,咱們要知道對象的比較是經過引用比較的,因此在這個測試案例中,它們雖然看上去很像,實際上是兩個不一樣的對象(這裏也是數組),它們並無引用同一個地址,因此並不嚴格等,對象嚴格等的狀況以下: 

var a = [];
var b = a;
console.log(a === b); ==>true

  b變量被賦值爲a,a本質是對象,對象賦值爲引用賦值,此時a和b公用一個地址,因此嚴格等成立。

  此外,關於==還有個比較經典的問題:

console.log([] == ![]); ==>true

  由於!運算符優先級緣由,將先執行![],因此這裏等效於 [] == false,按照常識在boolean環境下空數組是轉換爲true的,可是實際上在==環境中,是經過轉換爲數字或字符串來比較的,當操做值有boolean類型時轉換爲數值比較,也就是[]轉換爲number類型爲0,false轉換爲number類型爲0,因此結果返回true。看上去這些繁瑣的轉換實在使人擔心,但實際也沒有這麼糟糕,畢竟這種看上去「非人性」的結果在實際開發場景中極少遇到,當你有必定的經驗的時候,絕大部分寬鬆相等的結果你仍是可以一眼識破的。  

 (9)或與問題

console.log(1&&2); ==>2
console.log(1||2); ==>1
console.log(1&&a=2); ==>error
console.log(1&&(a=2)); ==>2

  關於&&和||兩個運算符,也是筆試中的常客。這裏有幾點須要注意:

  1. &&和||返回的是表達式的值,而並非true或者false

  2. 從左到右執行,&&左側的表達式返回值若是轉換布爾型爲true時,則將執行右側的表達式;||左側的表達式返回值若是轉換布爾型爲true時,則直接返回該表達式返回值且再也不執行右側表達式

  有了以上兩點,前兩個測試則比較容易理解了,而對於1&&a=2,實際等同於——(1&&a)=2——undefined=2,執行將報錯;只要給a=2加上小括號優先執行則能夠正常運行,其中a=2的返回值爲2,因此最終表達式的值爲2。

(10)浮點數字不精確問題

console.log(0.1*0.1); ==>0.010000000000000002

  在js中採用的是一種二進制表示法,能夠精確的表示分數,好比1/21/81/1024。可是其它浮點值實際上只是真實值的一個近視表示,好比0.1,二進制浮點數表示法並不能精確的表示0.1這樣簡單的數字。因此,當遇到小數點的四則運算的時候須要特殊處理,最典型的場景就是支付了,好比1.1元每一個,用戶購買3個,則不能直接使用相乘結果,可使用toFixed控制結果,或者以乘法爲例可以使用如下方法保證精確性: 

//乘法處理
function FloatMul(arg1,arg2)   {   
  var m=0,s1=arg1.toString(),s2=arg2.toString();   
  try{m+=s1.split(".")[1].length}catch(e){}   
  try{m+=s2.split(".")[1].length}catch(e){}   
  return  Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);    
}   
相關文章
相關標籤/搜索