JS有哪些變態語法

JS做爲一門如此靈活的語言,天然在編碼時給咱們帶來了不少方便,但方便的同時,也衍生出了不少變態的語法,下面咱們來梳理一些常見的變態語法,但願你下次在某位大牛的代碼中看到這樣的東西,不要驚掉下巴。java

  NO.1bootstrap

——————————————————————————————————————數組

  Number.prototype.add = function(n){瀏覽器

  return this+n;函數

}測試

  2"add"
——————————————————————————————————————this

  最後一句話是什麼玩意兒?好像沒看懂呢? 咱們來運行一下看看編碼

  我擦? 它竟然執行了?結果是5,看上去彷佛對2和3作了加法。prototype

  不是說變量名不能數字開頭麼?這是怎麼回事?瀏覽器抽風了?對象

  實際上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

  因此它的出現,讓這個匿名函數從聲明變成了執行,也就是編譯期間瀏覽器不會提早準備它,天然就沒有語法錯誤。而5分鐘前咱們看到的那些喪心病狂的寫法,其實原理都同樣,經過運算符把聲明變成執行。固然這些符號都不會影響函數的正常執行結果。

  可是問題又來了,這種泯滅人性的寫法,如今竟然還挺常見的,例如:

  沒錯,這就是著名的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以後才消失的。

  好了,此次的變態語法就先講這麼多,之後碰到更新鮮的再來給你們更新,拜拜。

相關文章
相關標籤/搜索