欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

怎么用JavaScript編寫(xiě)斐波那契程序

今天小編給大家分享一下怎么用JavaScript編寫(xiě)斐波那契程序的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

“專(zhuān)業(yè)、務(wù)實(shí)、高效、創(chuàng)新、把客戶(hù)的事當(dāng)成自己的事”是我們每一個(gè)人一直以來(lái)堅(jiān)持追求的企業(yè)文化。 創(chuàng)新互聯(lián)公司是您可以信賴(lài)的網(wǎng)站建設(shè)服務(wù)商、專(zhuān)業(yè)的互聯(lián)網(wǎng)服務(wù)提供商! 專(zhuān)注于成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、軟件開(kāi)發(fā)、設(shè)計(jì)服務(wù)業(yè)務(wù)。我們始終堅(jiān)持以客戶(hù)需求為導(dǎo)向,結(jié)合用戶(hù)體驗(yàn)與視覺(jué)傳達(dá),提供有針對(duì)性的項(xiàng)目解決方案,提供專(zhuān)業(yè)性的建議,創(chuàng)新互聯(lián)建站將不斷地超越自我,追逐市場(chǎng),引領(lǐng)市場(chǎng)!

掃描器

源代碼首先被分解成 chunk,每個(gè) chunk 都可能采用不同的編碼,稍后會(huì)有一個(gè)字符流將所有 chunk 的編碼統(tǒng)一為 UTF-16。

在解析之前,掃描器會(huì)將 UTF-16 字符流分解成 token。token 是一段腳本中具有語(yǔ)義的最小單元。有不同類(lèi)型的 token,包括空白符(用于 自動(dòng)插入分號(hào))、標(biāo)識(shí)符、關(guān)鍵字以及代理對(duì)(僅當(dāng)代理對(duì)無(wú)法被識(shí)別為其它東西時(shí)才會(huì)結(jié)合成標(biāo)識(shí)符)。這些 token 之后被送往預(yù)解析器中,接著再送往解析器。

預(yù)解析器

解析器的工作量是最少的,只要足夠跳過(guò)傳入的源代碼并進(jìn)行懶解析(而不是全解析)即可。預(yù)解析器確保輸入的源代碼包含有效語(yǔ)法,并生成足夠的信息來(lái)正確地編譯外部函數(shù)。這個(gè)準(zhǔn)備好的函數(shù)稍后將按需編譯。

解析

解析器接收到掃描器生成的 token 后,現(xiàn)在需要生成一個(gè)供編譯器使用的中間表示。

首先我們來(lái)討論解析樹(shù)。解析樹(shù),或者說(shuō) 具體語(yǔ)法樹(shù)(CST)將源語(yǔ)法表示為一棵樹(shù)。每個(gè)葉子節(jié)點(diǎn)都是一個(gè) token,而每個(gè)中間節(jié)點(diǎn)則表示一個(gè)語(yǔ)法規(guī)則。在英語(yǔ)里,語(yǔ)法規(guī)指的是名詞、主語(yǔ)等,而在編程里,語(yǔ)法規(guī)則指的是一個(gè)表達(dá)式。不過(guò),解析樹(shù)的大小隨著程序大小會(huì)增長(zhǎng)得很快。

相反,抽象語(yǔ)法樹(shù) 要更加簡(jiǎn)潔。每個(gè)中間節(jié)點(diǎn)表示一個(gè)結(jié)構(gòu),比如一個(gè)減法運(yùn)算(-),并且這棵樹(shù)并沒(méi)有展示源代碼的所有細(xì)節(jié)。例如,由括號(hào)定義的分組是蘊(yùn)含在樹(shù)的結(jié)構(gòu)中的。另外,標(biāo)點(diǎn)符號(hào)、分隔符以及空白符都被省略了。你可以在 這里 了解更多 AST 和 CST 的區(qū)別。

接下來(lái)我們將重點(diǎn)放在 AST 上。以下面用 JavaScript 編寫(xiě)的斐波那契程序?yàn)槔?/p>

function fib(n) {     if (n <= 1) return n;     return fib(n-1) + fib(n-2);     }

下面的 JSON 文件就是對(duì)應(yīng)的抽象語(yǔ)法

了。這是用 AST Explorer 生成的。(如果你不熟悉這個(gè),可以點(diǎn)擊這里來(lái)詳細(xì)了解 如何閱讀 JSON 格式的 AST)。

{    "type": "Program",    "start": 0,    "end": 73,    "body": [      {        "type": "FunctionDeclaration",        "start": 0,        "end": 73,        "id": {          "type": "Identifier",          "start": 9,          "end": 12,          "name": "fib"        },        "expression": false,        "generator": false,        "async": false,        "params": [          {            "type": "Identifier",            "start": 13,            "end": 14,            "name": "n"          }        ],        "body": {          "type": "BlockStatement",          "start": 16,          "end": 73,          "body": [            {              "type": "IfStatement",              "start": 20,              "end": 41,              "test": {                "type": "BinaryExpression",                "start": 24,                "end": 30,                "left": {                  "type": "Identifier",                  "start": 24,                  "end": 25,                  "name": "n"                },                "operator": "<=",                "right": {                  "type": "Literal",                  "start": 29,                  "end": 30,                  "value": 1,                  "raw": "1"                }              },              "consequent": {                "type": "ReturnStatement",                "start": 32,                "end": 41,                "argument": {                  "type": "Identifier",                  "start": 39,                  "end": 40,                  "name": "n"                }              },              "alternate": null            },            {              "type": "ReturnStatement",              "start": 44,              "end": 71,              "argument": {                "type": "BinaryExpression",                "start": 51,                "end": 70,                "left": {                  "type": "CallExpression",                  "start": 51,                  "end": 59,                  "callee": {                    "type": "Identifier",                    "start": 51,                    "end": 54,                    "name": "fib"                  },                  "arguments": [                    {                      "type": "BinaryExpression",                      "start": 55,                      "end": 58,                      "left": {                        "type": "Identifier",                        "start": 55,                        "end": 56,                        "name": "n"                      },                      "operator": "-",                      "right": {                        "type": "Literal",                        "start": 57,                        "end": 58,                        "value": 1,                        "raw": "1"                      }                    }                  ]                },                "operator": "+",                "right": {                  "type": "CallExpression",                  "start": 62,                  "end": 70,                  "callee": {                    "type": "Identifier",                    "start": 62,                    "end": 65,                    "name": "fib"                  },                  "arguments": [                    {                      "type": "BinaryExpression",                      "start": 66,                      "end": 69,                      "left": {                        "type": "Identifier",                        "start": 66,                        "end": 67,                        "name": "n"                      },                      "operator": "-",                      "right": {                        "type": "Literal",                        "start": 68,                        "end": 69,                        "value": 2,                        "raw": "2"                      }                    }                  ]                }              }            }          ]        }      }    ],    "sourceType": "module"  }  (來(lái)源:GitHub)

上面代碼的要點(diǎn)是,每個(gè)非葉子節(jié)點(diǎn)都是一個(gè)運(yùn)算符,而每個(gè)葉子節(jié)點(diǎn)都是操作數(shù)。這棵語(yǔ)法樹(shù)稍后將作為輸入傳給 JavaScript 接著要執(zhí)行的兩個(gè)階段。

三個(gè)技巧優(yōu)化你的 JavaScript

下面羅列的技巧清單中,我會(huì)省略那些已經(jīng)廣泛使用的技巧,例如縮減代碼來(lái)最大化信息密度,從而使掃描器更具有時(shí)效性。另外,我也會(huì)跳過(guò)那些適用范圍很小的建議,例如避免使用非 ASCII 字符。

提高解析性能的方法數(shù)不勝數(shù),讓我們著眼于其中適用范圍最廣泛的方法吧。

1.盡可能遵從工作線程

主線程被阻塞會(huì)導(dǎo)致用戶(hù)交互的延遲,所以應(yīng)該盡可能減少主線程上的工作。關(guān)鍵就是要識(shí)別并避免會(huì)導(dǎo)致主線程中某些任務(wù)長(zhǎng)時(shí)間運(yùn)行的解析行為。

這種啟發(fā)式超出了解析器的優(yōu)化范圍。例如,用戶(hù)控制的 JavaScript 代碼段可以使用 web workers 達(dá)到相同的效果。你可以閱讀 實(shí)時(shí)處理應(yīng)用 和 在 angular 中使用 web workers 來(lái)了解更多信息。

避免使用大量的內(nèi)聯(lián)腳本

內(nèi)聯(lián)腳本是在主線程中處理的,根據(jù)之前的說(shuō)法,應(yīng)該盡量避免這樣做。事實(shí)上,除了異步和延遲加載之外,任何 JavaScript 的加載都會(huì)阻塞主線程。

避免嵌套外層函數(shù)

懶編譯也是發(fā)生在主線程上的。不過(guò),如果處理得當(dāng)?shù)脑挘瑧薪馕隹梢约涌靻?dòng)速度。想要強(qiáng)制進(jìn)行全解析的話,可以使用諸如 optimize.js(已經(jīng)不維護(hù))這樣的工具來(lái)決定進(jìn)行全解析或者懶解析。

分解超過(guò) 100kB 的文件

將大文件分解成小文件以最大化并行腳本的加載速度?!?019 年 JavaScript 的性能開(kāi)銷(xiāo)”一文比較了 Facebook 網(wǎng)站和 Reddit 網(wǎng)站的文件大小。前者通過(guò)在 300 多個(gè)請(qǐng)求中拆分大約 6MB 的 JavaScript ,成功將解析和編譯工作在主線程上的占比控制到 30%;相反,Reddit 的主線程上進(jìn)行解析和編譯工作的達(dá)到了將近 80%。

2. 使用 JSON 而不是對(duì)象字面量 &mdash;&mdash; 偶爾

在 JavaScript 中,解析 JSON 比解析對(duì)象字面量來(lái)得更加高效。 parsing benchmark 已經(jīng)證實(shí)了這一點(diǎn)。在不同的主流 JavaScript 執(zhí)行引擎中分別解析一個(gè) 8MB 大小的文件,前者的解析速度最高可以提升 2 倍。

2019 年谷歌開(kāi)發(fā)者大會(huì) 也討論過(guò) JSON 解析如此高效的兩個(gè)原因:

  1.  JSON 是單字符串 token,而對(duì)象字面量可能包含大量的嵌套對(duì)象和 token;

  2.  語(yǔ)法對(duì)上下文是敏感的。解析器逐字檢查源代碼,并不知道某個(gè)代碼塊是一個(gè)對(duì)象字面量。而左大括號(hào)不僅可以表明它是一個(gè)對(duì)象字面量,還可以表明它是一個(gè)解構(gòu)對(duì)象或者箭頭函數(shù)。

不過(guò),值得注意的是,JSON.parse 同樣會(huì)阻塞主線程。對(duì)于超過(guò) 1MB 的文件,可以使用 FlatBuffers 提高解析效率。

3. 最大化代碼緩存

最后,你可以通過(guò)完全規(guī)避解析來(lái)提高解析效率。對(duì)于服務(wù)端編譯來(lái)說(shuō), WebAssembly (WASM) 是個(gè)不錯(cuò)的選擇。然而,它沒(méi)辦法替代 JavaScript。對(duì)于 JS,更合適的方法是最大化代碼緩存。

值得注意的是,緩存并不是任何時(shí)候都生效的。在執(zhí)行結(jié)束之前編譯的任何代碼都會(huì)被緩存 &mdash;&mdash; 這意味著處理器、監(jiān)聽(tīng)器等不會(huì)被緩存。為了最大化代碼緩存,你必須最大化執(zhí)行結(jié)束之前編譯的代碼數(shù)量。其中一個(gè)方法就是使用立即執(zhí)行函數(shù)(IIFE)啟發(fā)式:解析器會(huì)通過(guò)啟發(fā)式的方法標(biāo)識(shí)出這些 IIFE 函數(shù),它們會(huì)在稍后立即被編譯。因此,使用啟發(fā)式的方法可以確保一個(gè)函數(shù)在腳本執(zhí)行結(jié)束之前被編譯。

此外,緩存是基于單個(gè)腳本執(zhí)行的。這意味著更新腳本將會(huì)使緩存失效。V8 團(tuán)隊(duì)建議可以分割腳本或者合并腳本,從而實(shí)現(xiàn)代碼緩存。但是,這兩個(gè)建議是互相矛盾的。你可以閱讀“JavaScript 開(kāi)發(fā)中的代碼緩存”來(lái)了解更多代碼緩存相關(guān)的信息。

結(jié)論

解析時(shí)間的優(yōu)化涉及到工作線程的延遲解析以及通過(guò)最大化緩存來(lái)避免完全解析。理解了 V8 的解析機(jī)制后,我們也能推斷出上面沒(méi)有提到的其它優(yōu)化方法。

下面給出了更多了解解析機(jī)制的資源,這個(gè)機(jī)制通常來(lái)說(shuō)同時(shí)適用于 V8 和 JavaScript 的解析。

  •  V8 文檔

  •  V8 博客

  •  V8-perf

額外小貼士:理解 JavaScript 的錯(cuò)誤和性能是如何影響你的用戶(hù)的。

跟蹤生產(chǎn)過(guò)程中 JavaScript 的異常或者錯(cuò)誤是很耗時(shí)的,而且也很令人傷腦筋。如果你有興趣監(jiān)控 JavaScript 的錯(cuò)誤和應(yīng)用性能是如何對(duì)用戶(hù)造成影響的,可以嘗試使用 LogRocket。

LogRocket 就像是為 web 應(yīng)用量身訂造的 DVR(錄像機(jī)),它可以確切地記錄你的網(wǎng)站上發(fā)生的所有事情。LogRocket 可以幫助你統(tǒng)計(jì)并報(bào)告錯(cuò)誤,以查看錯(cuò)誤發(fā)生的頻率以及它們對(duì)你的用戶(hù)群的影響程度。你可以輕松地重現(xiàn)錯(cuò)誤發(fā)生時(shí)特定的用戶(hù)會(huì)話,以查看是用戶(hù)的哪些操作導(dǎo)致了 bug。

LogRocket 可以記錄你的 app 上的請(qǐng)求和響應(yīng)(包含 header 和 body)以及用戶(hù)相關(guān)的上下文信息,從而窺探問(wèn)題全貌。它也可以記錄頁(yè)面的 HTML 和 CSS,即使是面對(duì)最復(fù)雜的單頁(yè)面應(yīng)用,也可以重構(gòu)出像素完美級(jí)別的視頻。

以上就是“怎么用JavaScript編寫(xiě)斐波那契程序”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

分享標(biāo)題:怎么用JavaScript編寫(xiě)斐波那契程序
URL分享:http://chinadenli.net/article6/ppgcig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營(yíng)銷(xiāo)、定制開(kāi)發(fā)網(wǎng)站設(shè)計(jì)、網(wǎng)站收錄面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司