吉林信息港
您當前的位置 :主頁 > 吉林信息港 > 時尚 > 正文
只用這 6 個字符,就可以寫出任意 JavaScript 代碼
2019-12-27 16:20:03來源:閱讀:1

你可能在網上見過有人用 幾個不同的字符寫的各種稀奇古怪的 JavaScript 代碼,雖然看起來奇怪,但是能正常運行!比如這個:

(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]

你猜運行結果是什么?你可以自己去控制臺試一下。

看起來很神奇,但這到底是怎么回事呢?

事實上,你幾乎可以用下面這 6 個字符寫出任意的 JavaScript 程序:

[]()!+

很多人都知道這個技巧,但是沒有多少開發人員知道它到底是如何工作的。今天,我們就來看看它背后的執行原理。我們的目標是用這幾個字符來寫出字符串“self”。姑且用這個字符串向 Self 語言致敬,JavaScript 的靈感來源之一就是它。

只用這 6 個字符,就可以寫出任意 JavaScript 代碼

基本原理

我們之所以能夠拋開其他字符不用,要歸功于 JavaScript 的類型系統和數據類型轉換機制。

這 6 個字符是這樣各顯神通的:[]可以用來創建數組,!和+可以在數組上執行一些操作,再用()給這些操作分組。

先看一個簡單的數組:

[]

數組前加上!會把它轉成布爾值。數組被認為是真值,因此取非之后變成了false:

![] === false

除非轉換為類似類型,否則無法將不同類型的值加在一起。JavaScript 在進行轉換時遵循一個預定義的規則:

在表達式2 + true中,JavaScript 會將true轉成數字,得到表達式2+1。

在表達式2 + "2"中,JavaScript 會將數字轉成字符串,得到2 + "2" === "22"。

這些轉換規則還不算糟糕,但是對于其他類型,好戲馬上來了。

JavaScript 數組強制轉換

數組相加會轉換成字符串并連接起來。空數組轉換為空字符串,因此將兩個數組相加將得到空字符串。

[] + [] === "" + "" === ""

數組跟其他類型值相加時也一樣:

![] + [] === "false" + "" === "false"

驚不驚喜?我們得到了目標字符串"self"所包含的幾個字符!

如果我們能產生一些數字,就可以按正確的順序提取所需的字符:

"false"[3] === "s"(![] + [])[3] === "s"

那么,如何生成數字呢?

生成數字

前面提到了,可以把數組轉成布爾值。那如果用加號+把它轉成數字會怎樣?

+[] === ???

JavaScript 會嘗試調用數組的valueOf方法,但是發現不存在這個方法,然后就轉而調用toString()方法了。因此上面的代碼等效于:

+[] === +""

將字符串轉換為數字將產生以下結果:

+"42" === 42+"esg" == NaN+"" === 0

空字符串是一個 false值,跟 null,undefined和數字零類似,因此將其中任何一個轉換為數字都會變成零:

+null === 0+undefined === 0+false === 0+NaN === 0+"" === 0

因此,將數組轉換為數字需要先將其轉換為字符串,最后轉成 0:

+[] === +"" === 0

第一個數字已經造出來了!我們還需要更多數字,繼續:

!0 === !false!false === true!0 === true

將 0 取否就得到一個為真的布爾值。為真的布爾值轉成數字,就是1:

+true === 1

有了 1,自然就可以得到2,所謂道生一,一生二,二生三,三生萬物……

用上面的轉換大法,可以輕松得到我們想要的這些數字:

1 === +true == +(!0) ==== +(!(+[])) === +!+[]1 === +!+[]2 === +!+[] +!+[]3 === +!+[] +!+[] +!+[]4 === +!+[] +!+[] +!+[] +!+[]

臨門一腳,大功告成

總結下這些規則:

  • 數組屬于真值,取否就得到 false: ![] // false
  • 數組相加時會轉換成字符:[] + [] // ""
  • 空數組轉成數字得到 0,再去否得到 true,再轉成數字得到1:+(!(+[])) === 1

根據這些規則,我們就能得到想要的字符串。看下面這個示意圖就很清楚了:

![] + [] === "false"+!+[] === 1(![] + [])[3] + (![] + [])[4] + (![] + [])[2] + (![] + [])[0]^^^^^^^^^^      ^^^^^^^^^^      ^^^^^^^^^^      ^^^^^^^^^^        "false"         "false"         "false"         "false"       ^^^^^^^^^^^^^   ^^^^^^^^^^^^^   ^^^^^^^^^^^^^   ^^^^^^^^^^^^^          s               e               l               f         

最終的表達式就是這樣:

(![] + [])[+!+[]+!+[]+!+[]] + (![] + [])[+!+[]+!+[]+!+[]+!+[]] + (![] + [])[+!+[]+!+[]] +(![] + [])[+[]]

整理下空格和換行,就是一行代碼:

(![]+[])[+!+[]+!+[]+!+[]]+(![]+[])[+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+!+[]+!+[]]+(![]+[])[+[]]

現在你應該明白了那些神奇 JavaScript 代碼的原理了吧?發揮你的想象,看還能寫出其他什么來?比如,今天是圣誕節,來個 “Merry Christmas”?


作者:KaysonLi
原文鏈接:https://juejin.im/post/5e030041e51d45581c1aa097


推薦閱讀:葉紫網

版權和免責申明

吉林信息港所有文字、圖片、視頻、音頻等資料均來自互聯網,不代表本站贊同其觀點,本站亦不為其版權負責。相關作品的原創性、文中陳述文字以及內容數據龐雜本站無法一一核實,如果您發現本網站上有侵犯您的合法權益的內容,請聯系我們,本網站將立即予以刪除!

深海捕鱼大师攻略 兴动棋牌哈尔滨麻将 申城棋牌网站下载 今天18选7开奖结果公告 海南体彩4十1近期开奖号码 有没有打字赚钱的兼职 棋牌游戏交易平台 四川金7乐如何杀号 安徽快3实时开奖结果 1分赛车开奖直播 000408股票行情 怎么打篮球 私募基金配资 股票大盘怎么看图解 永利棋牌官网平台 体彩20选五开奖结果查询 河北排列五中奖规则