Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲国产精品国产自在在线 ,一区二区三区不卡视频,亚洲一区二区高清

          整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          js基礎面試題21-30道

          1.for in、Object.keys 和 Object.getOwnPropertyNames 對屬性遍歷有什么區(qū)別?

          參考答案:

          • for in 會遍歷自身及原型鏈上的可枚舉屬性
          • Object.keys 會將對象自身的可枚舉屬性的 key 輸出
          • Object.getOwnPropertyNames會將自身所有的屬性的 key 輸出

          解析:

          ECMAScript 將對象的屬性分為兩種:數(shù)據(jù)屬性和訪問器屬性。

          var parent = Object.create(Object.prototype, {
              a: {
                  value: 123,
                  writable: true,
                  enumerable: true,
                  configurable: true
              }
          });
          // parent繼承自Object.prototype,有一個可枚舉的屬性a(enumerable:true)。
          
          var child = Object.create(parent, {
              b: {
                  value: 2,
                  writable: true,
                  enumerable: true,
                  configurable: true
              },
              c: {
                  value: 3,
                  writable: true,
                  enumerable: false,
                  configurable: true
              }
          });
          //child 繼承自 parent ,b可枚舉,c不可枚舉

          for in

          for (var key in child) {
              console.log(key);
          }
          // b
          // a
          // for in 會遍歷自身及原型鏈上的可枚舉屬性

          如果只想輸出自身的可枚舉屬性,可使用 hasOwnProperty 進行判斷(數(shù)組與對象都可以,此處用數(shù)組做例子)

          let arr = [1, 2, 3];
          Array.prototype.xxx = 1231235;
          for (let i in arr) {
              if (arr.hasOwnProperty(i)) {
                  console.log(arr[i]);
              }
          }
          // 1
          // 2
          // 3

          Object.keys

          console.log(Object.keys(child));
          // ["b"]
          // Object.keys 會將對象自身的可枚舉屬性的key輸出

          Object.getOwnPropertyNames

          console.log(Object.getOwnPropertyNames(child));
          // ["b","c"]
          // 會將自身所有的屬性的key輸出

          參與互動

          文最初發(fā)布于 Dropbox 技術博客,經(jīng) Dropbox 授權由 InfoQ 中文站翻譯并分享。譯文經(jīng)過了 Dropbox 團隊的審核和修訂。

          序言

          2017 年 5 月,我首度加入 Dropbox 的時候,從 CoffeeScript 向 TypeScript 遷移的工作已經(jīng)接近尾聲。彼時,需要對已有的 CoffeeScript 文件更改時,一般都會先將它轉換為 TypeScript。我們的部分代碼庫仍在使用 react-dom-factories,并且在 Redux 之前有一個自定義的 flux 實現(xiàn)。

          那時我們的 Web 平臺團隊正全速向 TypeScript 遷移,但這一工作的規(guī)?;驈碗s性尚不為外人所知。如今 TypeScript 已成為 JavaScript 事實上的超集,我們的這段往事也是時候公之于眾了。故事主要發(fā)生在 2017 年,在今天依舊頗具參考價值。

          我聯(lián)絡到該項目的首席工程師之一 David Goldstein 來撰寫本文。此外,還找到了另一位見證者,Web 平臺工程師 Samer Masterson 來補充細節(jié)。

          將數(shù)十萬行 CoffeeScript 代碼遷移到 TypeScript 是一項龐大的工程,本文將涉及其中的方方面面。我們將介紹一開始為什么選擇了 TypeScript,如何規(guī)劃遷移工作,還有那些計劃外的各種細節(jié)。

          遷移在 2017 年秋季結束。在此過程中我們開發(fā)了一些優(yōu)秀的工具,并成為了首批大規(guī)模采用 TypeScript 的公司之一?!狹atthew Gerstman

          歷史:采用 CoffeeScript

          早在 2012 年,我們還是一家只有約 150 名員工的新興公司。當時瀏覽器中的最新技術是 jQuery 和 ES5。HTML5 還有兩年才會正式登臺,而 ES6 還要等三年。由于 JavaScript 技術似乎停滯不前,我們想要找到一種更先進的 Web 開發(fā)方法。

          當時,CoffeeScript 非常流行。它支持箭頭函數(shù),智能 this 綁定,甚至可選鏈,都比標準 JavaScript 領先數(shù)年。最后,我們的兩名工程師在 2012 年的“黑客周”中將整個 dropbox.com Web 應用程序從 JavaScript 遷移到了 CoffeeScript 上。彼時 dropbox 規(guī)模不大,所以遷移很容易。我們從 CoffeeScript 社區(qū)獲得了指導,并采納了他們的樣式建議,最終將 coffeelint 集成到了工作流程中。

          在 CoffeeScript 中,花括號、圓括號,有時甚至逗號都是非必須的,是可有可無的選項。

          例如,foo 12 與 foo(12) 是等同的。

          多行數(shù)組可以不用逗號:

          復制代碼

          // CoffeeScript["foo""bar"]  // JavaScript["foo", "bar"]

          這種語法方法在那時很流行,我們甚至采納了社區(qū)的“可選的符號就不用寫”建議。

          當時,代碼庫包含約 100,000 行 JavaScript。所有文件按預先指定的順序串聯(lián)在一起打包發(fā)布。盡管公司的許多工程師都可以看到這些代碼,但其中全職的 Web 工程師卻不到 10 位。

          自然,這種方法無法很好地擴展;在 2013 年我們采用了 RequireJS 模塊系統(tǒng),并開始編寫新代碼以符合“異步模塊定義”(簡稱 AMD)規(guī)范。我們確實考慮過 CommonJS,但那時 npm 和 Node 生態(tài)系統(tǒng)尚未成熟,因此我們選擇了專為在瀏覽器中使用而設計的工具。如果是幾年后再做同樣的決策,我們可能會改用 CommonJS。

          語言遷移的號角聲

          一開始還好,但到了 2015 年底,產(chǎn)品工程師開始對 CoffeeScript 愈加不滿。ES6 于當年早些時候發(fā)布,覆蓋了 CoffeeScript 的那些最佳特性,與 CoffeeScript 相比,它具備更多優(yōu)勢。它支持對象和數(shù)組解構、類語法和箭頭函數(shù)。結果一些團隊搶先一步,開始在自己的獨立項目中使用 ES6。

          與此同時,CoffeeScript 代碼庫維護難度在加大。由于 CoffeeScript(和標準 JavaScript)都沒有類型,因此很容易在無意間破壞某些內(nèi)容。防御式編程隨處可見,但卻使代碼難以理解。我們?yōu)?null 和 undefined 添加了額外的保護措施,還針對某種極端場景采用了特殊對策,無需 new 操作便可以安全構造一個函數(shù)。

          復制代碼

          class URI    constructor: (x) ->      # enable URI as a global function that returns a new URI instance      unless @ instanceof URI        return new URI(x)      ...

          此外,CoffeeScript 是一種基于空格的語言,即 tab 和空格具備不同的含義的,這與用 Python 構建 Dropbox 類似。然而,CoffeeScript 對標點卻過于寬容。通常,“可選的標點”實際上意味著“CoffeeScript 會將其編譯為意想不到的含義?!?/p>

          舉個例子:在 2013 年的秋天,曾經(jīng)遇到過一個關于標點符號的 bug,Python 無法編譯通過,CoffeeScript 將它進行了錯誤的編譯。雖然 Coffee Script 與 Python 的相似性可能有助于 Dropbox 的應用,但這些差異往往會出問題。一些更有經(jīng)驗的開發(fā)人員選擇通過將 JavaScript 與 CoffeeScript 代碼并排打開來工作。

          2015 年 11 月,對 Dropbox 的前端工程師進行了一項調(diào)查,發(fā)現(xiàn)只有 15%的受訪者認為應該繼續(xù)使用 CoffeeScript,而 62%的受訪者則認為應該放棄它:

          開發(fā)人員經(jīng)常抱怨:

          • 缺少分隔符
          • 過于固執(zhí)己見的句法糖
          • 缺乏社區(qū)對語言的支持
          • 由于語法密集而難以理解
          • 由于句法歧義而容易出錯

          基于開發(fā)人員的這些反饋,于是我們將目光轉向業(yè)界,決定試用 TypeScript 和標準 ES6。我們將它們都集成到了 dropbox.com 技術棧中以選出更適合的選項。我們也考慮過 Flow,但它不如 TypeScript 流行,相關支持也較少。最后我們決定,如果要用類型語言就用 TypeScript,這在 2015 年是不尋常的決策。

          2016 年上半年,有一位工程師將 Babel 和 Type 腳本集成到我們的構建腳本中。我們現(xiàn)在可以在主網(wǎng)站試用兩種語言。經(jīng)過生產(chǎn)測試,我們認為 TypeScript 實際上是帶有類型的 ES6。由于團隊偏愛類型,最終選擇了 TypeScript。

          但是有一個小問題:那時我們的代碼庫已增長到 329,000 行 CoffeeScript;我們的工程團隊也大幅擴張,不再由單個團隊負責整個網(wǎng)站。所以我們的遷移速度不會像上次那么快了。

          樂觀的遷移計劃

          最初的計劃有 5 大里程碑:

          M1:基本支持

          • 添加 TypeScript 編譯器。
          • 使 TypeScript 和 CoffeeScript 代碼可以互操作。
          • TypeScript 的基本測試、國際化和 linting。

          M2:選定 TypeScript 為新代碼的默認語言

          • 優(yōu)化開發(fā)人員體驗。
          • 遷移核心庫。
          • 為最佳實踐編寫文檔。
          • 為代碼遷移編寫文檔。

          M3:TypeScript 成為代碼庫的主成員

          • 在 M2 基礎上更進一步,通過更多的教育過程,完整 linting 和測試支持,將其余重要的庫進行轉換。

          M4:預期在 2017 年 4 月,將編輯最多的一組文件遷移到 TypeScript

          • 手動將約 100 個經(jīng)常編輯的文件從 Coffeescript 轉換為 TypeScript。原始的 CoffeeScript 將在 git 歷史中可用。

          M5:預期在 2017 年 7 月,刪除 CoffeeScript 編譯器

          • 將所有剩余 CoffeeScript 代碼轉換成 JavaScript。源 CoffeeScript 將在 git 歷史中可用。
          • 更改這些 JavaScript 代碼前需將整個文件遷移到 TypeScript。

          2016 年下半年,M1、M2 和 M3 順利完成。我們成功構建了穩(wěn)健的 Coffee/TypeScript 互操作程序。測試很簡單:重用現(xiàn)有的基于 Jasmine 的基礎架構來測試兩種語言(之后遷移到了 Jest,但這是另一個故事了)。我們整合了 TSLint 并編寫了樣式指南。

          M4 和 M5 遇到了不少障礙,因為產(chǎn)品團隊需要將已有代碼移植到 TypeScript 上。我們希望各個團隊負責遷移各自開發(fā)的代碼,并決定給產(chǎn)品團隊留出一年中 20%的時間用于“基礎工作”,后文會詳細說明。

          CoffeeScript/TypeScript 的互操作性

          我們實現(xiàn)了 CoffeeScript 和 TypeScript 的互操作,如下所示:對于每個 CoffeeScript 文件,在類型文件夾中創(chuàng)建了一個相應的.d.ts 聲明文件。這些都是自動創(chuàng)建的,如:

          復制代碼

          declare module "foo/bar" {  const exports: any;  export = exports;}

          也就是說所有內(nèi)容都變成了 any 類型。重要模塊可以轉換為 TypeScript,或者逐步改變類型。對于流行的外部庫(如 jQuery 或 React),可以從 DefinitelyTyped 找出可用的類型。對于不太常見的庫,采用與默認存根相同的方法。

          將所有 TypeScript 和 CoffeeScript 文件放在同一文件夾中,所以兩種語言的文件模塊 ID 都一樣。在學習 AMD import/export 與 TypeScript 的語法如何對應時我們遇到了些麻煩,還好問題不大。我們沒有使用 --esModuleInterop。

          等效的 import 語句如下:

          TypeScript(推薦)

          復制代碼

          import * as foo from "foo";

          TypeScript(不推薦)

          復制代碼

          import foo = require("foo");

          與 AMD JavaScript(或等效的 CoffeeScript)相同

          復制代碼

          define(["foo", ...], function(foo, ...) { ... }

          將導出命名為 export const foo 類;可以導入模塊然后解構{foo},實現(xiàn)在 CoffeeScript 中讀取。這樣就和標準的 ES6 命名 import 建立了良好的語法關系。TypeScript 的 export default 導入到 AMD 模塊后,等效于對象{default: …},真是令人驚訝。

          大多數(shù)模塊都可以用這些等效方法,但有些模塊會動態(tài)確定它們將導出的內(nèi)容。我們從每個文件導出了所有可能的導出,如果沒有返回的話就改為 undefined。

          之前

          復制代碼

          define([...], function(...) {  ...  if (foo) {    return {bar};  } else {    return {baz};  }})

          之后

          復制代碼

          let foo, bar;if (foo) {  bar = // define bar;} else {  baz = // define baz;}// Export both regardless.export {bar, baz}

          禁用 CoffeeScript 新文件

          M2 階段代碼庫不再接收新的 CoffeeScript 文件。已有 CoffeeScript 的編輯不受影響,但多數(shù)工程師也因此開始學習 TypeScript 了。

          一開始我們編寫了一個遍歷代碼庫的測試,找到所有.coffee 文件并將其路徑加入白名單。對此測試文件的任何更改都需要經(jīng)過一位 Web 平臺工程師的審核。

          同時我們采用了 Bazel 作為構建系統(tǒng)。在遷移到 Bazel 期間這一測試暫時失效了,為已有的 CoffeeScript 文件返回了一個空列表,還斷言該空列表是已有 CoffeeScript 文件白名單的子集。還好我們很快修復了這個問題,沒有造成嚴重影響。

          我們在這里學到了一個教訓:如果測試中帶有任何假設,請試著確保它們能夠測試這些假設并在中斷時報錯。原始測試應該斷言 CoffeeScript 文件列表為非空,這樣一旦出錯時,就能立刻發(fā)現(xiàn)問題。

          修復這個問題時,我們對白名單加入了嚴格的檢查,這樣文件刪除時也必須從白名單中移除,且不能重新引入(除非明確地重新添加文件)。這種方法之后用在了所有白名單相關工作上,既能讓不符合測試假設的問題快速暴露,又能避免人們無意間回退遷移工作。這里有一個小的缺陷:縮小白名單會阻斷代碼審核,但問題不大,我們會盡快(在一個工作日內(nèi))接受這些審核。

          早期經(jīng)驗:沒有遺漏 CoffeeScript 的語法糖

          最初選擇要遷移的語言時,我們擔心的一個問題是:ES6 和 TypeScript 并沒有包括 CoffeeScript 的所有特性,比如說沒有? 和?. 運算符。

          起初,我們以為會遺漏這些:但當采用了 TypeScript2.0 的 --strictNullChecks 后,這就不是問題了??蛇x鏈運算符主要用來處理 undefined 或 null 之類的不確定性,而 TypeScript 幫助我們消除了這種不確定性。

          有趣的是,optional chaining 和 nulllish coallescing 最近都被重新添加到 vanilla Java 腳本中,并以類型腳本語言顯示,盡管有一些小的語法變化與原始 CoffeeScript 變量之間略有差異。

          優(yōu)先級競爭

          2016 年下半年,公司成立了一個并行團隊,用 React 重新設計和重構我們的網(wǎng)站。他們的目標是:到 2017 年第一季度末(時間接近最初的 M4 里程碑)發(fā)布新網(wǎng)站。該項目稱為“Maestro”,優(yōu)先級比將他們負責的部分遷移到 TypeScript 的工作更高。此外其他一些團隊也會參與其中。

          經(jīng)過討價還價,Maestro 團隊最終承諾在第二季度完成遷移工作。前面他們就用 React 和 TypeScript 重寫了很多功能,剩下的文件則在第二季度遷移完畢。

          遷移過程中用到“highly edited ”這個工具,強烈鼓勵社區(qū)轉換它們??上?100 個文件好像太多了,這個里程碑沒有按時交付。

          這樣來看,刪除 CoffeeScript 編譯器的計劃也得推遲了。除了這 100 個熱門文件,后面還有 2000 多個雖然沒那么常用,但也時不時用得上的 CoffeeScript 老文件呢。

          推遲 M5

          M5 里程碑在組織中引起了很多混亂,通常把它總結為“去除 CoffeeScript 編譯器”。

          公司內(nèi)卻出現(xiàn)了另一種解釋。許多人認為,雖然無法在截止日期之后編寫 CoffeeScript,但產(chǎn)品團隊可以編輯本應該只讀的代碼,甚至可以編輯 CoffeeScript,然后檢查新的編譯后的代碼。

          可如果只 check in 已編譯的代碼,那么大部分代碼就不會有 i18n 與 linting 支持了;不想追加投資的話,應假設代碼沒變才能找回這些支持。

          此外,從平臺的角度來看,這個里程碑意義不大。去除編譯器主要是為了有一個單語言的代碼庫,并讓注意力集中在 TypeScript 工具鏈上。

          不知道“只讀 JavaScript”是否比保留為 CoffeeScript 文件更好,用 Bazel 重新實現(xiàn)構建系統(tǒng)的工作即將完成,并已對 CoffeeScript 和 TypeScript 編譯器都提供了支持。

          因此在 6 月,TypeScript 的遷移工作被無限期推遲,完成時間沒有 ETA。

          事后看來這一決定似乎是不可避免的。假設每個工程日(包括測試和代碼審查)大約要轉換 1000 行代碼,那么一位工程師要花一年的時間才能完成遷移。這個速度實際上是非常樂觀的,因為實際報告的進度每天大約是 100 行,指望一兩個月就完成根本做不到。

          至于之前承諾的“20%的時間用于基礎工作”,我們也沒有達成共識。有的人知道這是用來滿足基礎架構需求的時間,有的人則認為這些時間可以用來償還自己的技術債。而且 20% 這個限制也形同虛設,沒人真的遵守它。

          2017 年后,我們再做遷移時就不再開這種空頭支票了。

          使用 decaffeinate 的新方案

          對 decaffeinate 的早期測試

          早在 2017 年 1 月,一些工程師就曾使用 decaffeinate 來簡化代碼轉換工作,甚至開始圍繞它構建一些工具來處理 AMD,并通過一些開源代碼來清理 React 樣式。

          不幸的是,我們首次嘗試 decaffeinate 時出現(xiàn)了嚴重的故障。我們轉換了 i18n 庫,然后審查,測試并交付生產(chǎn),結果發(fā)現(xiàn) decaffeinate 誤轉換了未測試的,可識別語言環(huán)境的排序函數(shù)。只有一個頁面用了這個函數(shù),但在 Safari 中這個頁面完全錯亂了。之后我們查看了 decaffeinate 的錯誤積壓,結果發(fā)現(xiàn)了幾十個類似問題。我們也不知道需要花多久才能真正信任 decaffeinate,所以當時沒打算用這種方法。

          不過一些工程師還是決定使用它來手動轉換代碼,我們在文檔中將其記為一種可行的工作流程?;?decaffeinate 的腳本通常會生成明顯無效的代碼,這沒什么大不了的,因為 TypeScript 在編譯時會報告它們。真正的問題是潛在的 bug,它們改變了代碼的語義,編譯器卻發(fā)現(xiàn)不了。

          六個月后

          2017 年夏天,decaffeinate 聲明自己做到了無 bug。于是我們開始重新考慮這一選項,經(jīng)過研究發(fā)現(xiàn):

          • decaffeinate 的聲明應該是可信的
          • 更令人信服的是,我們的內(nèi)部開發(fā)人員報告說,使用基于 decaffeinate 的腳本比手動轉換的結果更加可靠。

          于是我們制定了新計劃:將剩余的遷移工作自動化。

          現(xiàn)在對于 decaffeinate 無法提供類型的情況,可以添加為 any,直到 TypeScript 滿意為止。這種方法有以下優(yōu)點:

          • 工程師(尤其是新員工)不必再學習閱讀(或編輯)CoffeeScript
          • Web 平臺無需再支持 CoffeeScript linting、國際化和編譯器
          • codemod 或靜態(tài)分析之類工具的改進只需應對一種語言

          遷移結束后,團隊可以按自己的進度修復代碼中的類型;無需再維護指向未轉換的 CoffeeScript 的聲明文件。

          此時,產(chǎn)品團隊的空閑時間不多了,遷移得不到代碼所屬團隊的大量支持。而且要完成目標就要盡量減少引入的錯誤,有超過 2000 個文件要遷移,但錯誤超過一打就可能讓項目延遲或取消。這意味著我們必須在保持保持現(xiàn)有代碼語義的同時進行轉換。

          兩階段計劃

          需要針對所有文件創(chuàng)建一個多步流水線方法來完成遷移。

          首先,運行 decaffeinate 以生成有效的 ES6。該代碼沒有類型,甚至包括了 pre-JSX React。然后我們用一個自制的 ES6 到 TypeScript 轉換器處理這段 ES6 代碼。

          全面 decaffeinate

          decaffeinate 有一些選項可以生成更漂亮的代碼,代價是降低代碼的正確率。這些選項以 --loose 開頭。最初包括以下選項:

          • –loose-for-expressions
          • –loose-for-includes
          • –loose-includes

          這樣就無需用 Array.from() 包裝代碼的大部分內(nèi)容。但嘗試并測試后,我們發(fā)現(xiàn)了很多足以讓我們對這些選項失去信心的錯誤——它們很可能引入了回歸。

          而下面這些選項引發(fā)錯誤為數(shù)不多,因此最終使用了它們:

          • –prefer-const
          • –loose-default-params
          • –disable-babel 構造方法

          decaffeinate 會留下有關潛在樣式問題的注釋,例如,

          復制代碼

          /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */

          此后,我們使用了幾個 codemod 來清理生成的代碼。首先,使用 JavaScript-codemod 轉換函數(shù),例如 function() {}.bind(this) 轉換為箭頭函數(shù):() => {}。接下來,對于導入了 React 的文件,使用 react-codemod 更新了舊的 React.createElement 調(diào)用,并將 React.createClass 的實例轉換為 class MyComponent extends React.Component。

          這一過程生成了可運行的 Javascript,但仍使用 AMD 模塊格式。就算修復了這個問題,它也沒有使用我們的設置進行類型檢查。我們希望最終的 TypeScript 代碼使用與其余代碼相同的標志,尤其是 noImplicitAny 和 strictNullChecks。

          我們必須編寫自己的自定義轉換才能進行類型檢查。

          構建一個 ES6 到 TypeScript 轉換器

          自制轉換器有很多工作要做:通過迭代便能解決影響文件的所有問題,為此需要編寫一種工具來自動處理以下問題。

          為了開發(fā)這些工具,我們主要使用 https://astexplorer.net/ 來探索在構建原型轉換時將要使用的抽象語法樹。

          將 AMD 轉換為 ES6 模塊格式

          首先,需要將 AMD import 更新為 ES6 import。

          下面的代碼:

          復制代碼

          define(['library1', 'library2'], function(lib1, lib2) {})

          會變成:

          復制代碼

          import * as lib1 from 'library1'; import * as lib2 from 'library2';

          在 CoffeeScript 中,銷毀 import 是一種常見的模式,與 named import 關系很近。因此我們將:

          復制代碼

          define(['m1', 'm2'], function(M1, {somethingFromM2}) {  var tmp = M1(somethingFromM2);});

          轉換為:

          復制代碼

          import * as M1 from 'm1';import {somethingFromM2} from 'm2'; var tmp = M1(somethingFromM2);

          對導出進行轉換。如下代碼:

          復制代碼

          define(function() {  return {hello: 1}}

          變?yōu)椋?/p>

          復制代碼

          export {1 as hello}

          當無法轉換為 named export 時,便回退到使用 export = 。例如:

          復制代碼

          define([], function() {  let Something;  return Something = (function() {    Something = class Something {    }    return Something;  })();});

          變?yōu)椋?/p>

          復制代碼

          let Something; Something = (function() {   Something = class Something {   }   return Something; })(); export = Something;

          對于未用到的導入,之后會再做清理,以避免某些模塊會產(chǎn)生全局副作用。因此我們改為將其轉換為 import “x”; 樣式,并注釋說這可能是沒必要的。

          類型簽名

          接下來,我們必須將每個函數(shù)參數(shù)和 var 聲明注解為 any 類型。例如,function(hello) {} 變?yōu)?function(hello: any) {} 。

          我們還需要為在類內(nèi)部分配給 this 的每個屬性添加一個類屬性。例如:

          復制代碼

          class Hello {  constructor() {    this.hi = 1;  }   someFunc() {    this.sup = 1;  }}

          會轉換為:

          復制代碼

          class Hello {  hi: any;  sup: any;  ...

          為 React 添加類型

          另外,需要使用帶有類型的 React.Component 對 React 類組件進行注解。這些更改消除了許多 TypeScript 錯誤。

          為轉換編寫文檔

          因為不想丟失任何給定文件的版本控制歷史,所以我們自動在每個文件的頂部添加了一條消息,說明如何查找原始 coffeescript 版本。

          復制代碼

          //// NOTE This file was converted from a Coffeescript file.// The original content is available through git with the command:// git show 21e537318b56:metaserver/static/js/legacy_js/widgets/bubble.coffee//

          修復類型錯誤

          我們不想添加不必要的 any;但就算經(jīng)過上述管道處理,仍然會遇到數(shù)千種類型錯誤。因此,轉換管道中的最后一步是一個腳本,其運行類型檢查,解析類型檢查輸出,然后根據(jù)每個錯誤代碼嘗試在關聯(lián)的 AST 節(jié)點上插入適當?shù)?any 用法。

          一開始,我們在腳本里使用了 node-falafel,但發(fā)現(xiàn)用它時需要解析 TypeScript,所以我們 fork 了 falafel,進而使用 tslint-eslint-parser 來替代它;這樣我們只需重寫需要更改的代碼即可。

          保持專注

          我們的目標不是要做出最優(yōu)秀的轉換工具,而是要轉換代碼庫。首先,從小的內(nèi)部功能入手來測試工具,用它們來捕獲轉換工具中的崩潰以及讀取輸出時發(fā)現(xiàn)的明顯錯誤,當不再出現(xiàn)轉換崩潰之后,便開始在隨機的代碼庫子集中查看數(shù)據(jù)類型錯誤。這暴露出一些非常常見的問題,例如無效變量和復雜表達式中的類型錯誤,這些問題都不難解決:可以直接刪除無效變量,盡管在默認狀態(tài)下,保留它們的初始化器,以防表達式會產(chǎn)生其它副作用 - 將類似這樣的復雜表達式封裝成:(this as any).foo 。但是:這種方法變得越來越低效,所以后來我們開始改變策略。

          當將整個代碼庫可靠地轉換為 TypeScript 后,便開始在整個代碼庫上試運行,并對結果進行類型檢查。我們將類型錯誤按代碼分組 (例如?!癟S7030”),并統(tǒng)計了發(fā)生的情況。這樣就可以專心針對最常見的錯誤開發(fā)修復程序,避免浪費時間和精力了。

          這是一個重大轉折點。在此之前,我們一直在不停地編寫修補程序,以修復我們決定手動測試的各個文件中不時出現(xiàn)的各種錯誤。即便這樣,我們還是不能確定能否得到一個成熟的工具。通過對每個錯誤代碼的出現(xiàn)情況進行分組和計數(shù),我們能夠了解到還有多少工作要做,并且能夠集中精力處理發(fā)生了十幾次以上的類型錯誤。

          對于那些發(fā)生頻次比較少或至少頻次少到不足以需要費力去通過工具修復的類型錯誤,我們計劃稍后再手動進行修復。有一個令人難忘的例子是,在我們更改策略之前我們發(fā)現(xiàn)的一個問題:ES6 類構造器在調(diào)用 super() 之前無法執(zhí)行任何操作。在 CoffeeScript 類構造器中隨時調(diào)用 super() 都是合法的,因此當將它們轉換為 ES6 類時 TypeScript 會報錯。下面這種 CoffeeScript 代碼最容易出這種問題:

          復制代碼

          class Foo extends Bar  constructor: (@bar, @baz) ->    super()

          decaffeinate 后變成:

          復制代碼

          class Foo extends Bar {  constructor(bar, baz) {    this.bar = bar;    this.baz = baz;    super(); // illegal: must come first  }}

          在幾乎每個這樣的實例中,在作業(yè)之前調(diào)用 super() 都是有效的,但是需要幾分鐘讀取超類構造器以對此進行檢查。我們發(fā)現(xiàn)的 super() 函數(shù)的誤調(diào)用只有一兩次真正存在問題, 這種情況對于自動更新代碼庫過程中發(fā)生的錯誤來說,錯誤次數(shù)不算太多(大約有 20 多次),所以手工對它們修復的難度不是太大。將容易修復的代碼單列出來,安全地進行重新排序,對于那些較為復雜的情況,需要人工反復檢查,不值得花時間重寫。

          轉換完成時,我們的類型錯誤率約為:每個轉換的文件有 0.5–1 個類型檢查錯誤,需要手動修復。

          因工具提升了信心

          在編寫工具的后期階段,我們更關注如何安全地部署轉換后的代碼。只對轉換后的代碼進行類型檢查是不夠的,特別是考慮到我們要自動添加很多 any。

          因此,在代碼通過管道之前和之后,都會對代碼運行的所有單元測試。這樣就可以找出更多的錯誤,主要是隱藏的 CoffeeScript 錯誤代碼,轉換為 ts 后就會報錯。每當發(fā)現(xiàn)一個錯誤,都會在整個代碼庫中搜索類似的模式來修復它。這種辦法不行的時候,我們會在轉換工具中添加一個斷言,讓它們在遇到可疑代碼時迅速失效。

          談談一個有趣的錯誤

          這個錯誤是意外覆蓋了導出的函數(shù)。

          CoffeeScript 與大多數(shù)語言的不同之處在于:它沒有變量陰影的概念。例如在 Javascript 中,如果你運行:

          復制代碼

          let myVar = "top-level";function testMyVar() {  let myVar = "shadowed";  console.log(myVar);} testMyVar();console.log(myVar);

          它會打印出來:

          復制代碼

          shadowedtop-level

          盡管它們共享相同的名稱,但在 testMyVar 中創(chuàng)建的 myVar 與頂級 myVar 是不同的。這在 CoffeeScript 中是不可能做到的。等效代碼如下所示:

          復制代碼

          myVar = "top-level"testMyVar ->  myVar = "shadowed"  console.log(myVar)    testMyVar()console.log(myVar)

          打印出來:

          復制代碼

          shadowedshadowed

          在代碼中找到一個實例,如下所示:

          復制代碼

          define(() ->  sortedEntries = (...) ->    ...    sortedEntries = entries.sortBy(getSortKey, cmpSortKey)    ...   return {    sortedEntries  }

          sortedEntries 被聲明為一個函數(shù),但其自身的函數(shù)主體被一個實體數(shù)組覆蓋。第一次調(diào)用該模塊后,對模塊內(nèi)部 sortedEntries 的任何調(diào)用都將失敗;但由于 sortedEntries 函數(shù)導出的是副本,因此我們從未發(fā)現(xiàn)此問題。該代碼翻譯為:

          復制代碼

          let sortedEntries = function() {  ...  sortedEntries = entries.sortBy(getSortKey, cmpSortKey)} export { sortedEntries };

          由于 TypeScript 代碼使用的是 ES6 模塊而不是 AMD 模塊,因此 sortedEntries 將作為引用而不是副本導出。這意味著當另一個模塊導入 sortedEntries 并調(diào)用它時,sortedEntries 成為了一個數(shù)組,隨后對其進行的任何調(diào)用均將無效。

          遇到過一次這個錯誤后,我們在翻譯代碼中添加了一個 assert ,如果發(fā)現(xiàn)導出的函數(shù)被重新分配時就能解決問題。

          降低從稀松模式轉換為嚴格模式的風險

          在構建這些工具的過程中,我們意識到從 AMD 轉換為 ES6 模塊的副作用是:將有史以來第一次為絕大多數(shù)代碼啟用嚴格模式。

          乍聽起來,這似乎很可怕;為此我們通讀了 嚴格模式的 MDN 文檔,并制作了可預期行為的更改清單,然后逐一瀏覽清單,并找出減輕它們影響的方法。

          對于大多數(shù)更改,我們發(fā)現(xiàn) TypeScript 解析器或類型檢查器就能處理了 -——TypeScript 會正常抱怨新的語法錯誤。有些更改則可以通過我們的代碼搜索工具輕松驗證。還有些更改則不是問題,因為 CoffeeScript 實際上在其代碼生成中并未使用有問題的結構。

          關于 eval、.caller 和.callee 的更改:我們在代碼庫中很少使用 eval,在 CoffeeScript 中都沒有使用。并且我們沒有使用.caller 和.callee,因此不必擔心它們。

          剩下的最后一類:只能通過運行代碼來驗證的更改。其中,與 eval 有關的更改是無關緊要的,而 arguments 很少用,很容易處理。這下需要擔心的行為更改只剩下 3 種:

          1、給不可寫屬性、getter-only 屬性以及非擴展對象的屬性的分配時會報錯。向由 Object.freeze 凍結的對象寫入屬性是我們最有可能遇到的形式。

          2、刪除不可刪除的屬性現(xiàn)在會報錯。

          3、對 this 行為的更改——不再有 boxing,也不再有隱式 this=window 行為。

          我們實際上無法提前知道這三個更改是否會帶來問題,但現(xiàn)在這份簡短的清單使我們更容易管理風險了。

          還值得一提的是,代碼庫中最古老的部分是在引入 AMD 和 RequireJS 之前就以非模塊化代碼編寫的內(nèi)容,其中我們最擔心的是非嚴格模式的行為可能是代碼正常運行所必需的。

          我們發(fā)現(xiàn)可以將代碼轉換為 TypeScript,而無需將其轉換為 ES6 模塊。這樣一來便可以保持稀松模式。雖然這意味著我們在這部分代碼中基本上沒有跨模塊的類型檢查,但我們認為這是可以接受的折衷方案。

          第一次轉換后的特征

          我們首先對 Jasmine 測試套件開始了大規(guī)模轉換(后來我們遷移到了 Jest),這樣一來,便可以確保以后的遷移不會同時更改測試和代碼,于是更有信心不引入靜默錯誤。轉換了 Jasmine 測試之后,我們開始尋找生產(chǎn)代碼中第一個轉換的候選者。

          在 Dropbox,我們有一種在發(fā)布功能之前進行 bug 修復的文化:QA 和團隊的許多工程師會坐在一起,嘗試手動找出功能的 bug。與 QA 和許多團隊討論之后,我們決定首先轉換內(nèi)部工具和共享鏈接頁面的評論 UI。

          然后開始轉換內(nèi)部崩潰報告、功能 gating 和電子郵件發(fā)送工具,接著開始大批量開始轉換其余面向用戶的代碼庫。

          附帶說明:因為我們最近投資采用了 Bazel 作為構建工具,并且以此工具作為我們開發(fā)和集成測試框架的基礎,所以很容易確定一個 bug 是否是由更改引起的。由于我們使用 Bazel 和自己的 itest 工具提供服務,我們可以輕松查看之前的版本,并對其運行 itest。通過在代碼的確切版本上重建和啟動 dev 服務的副本,很容易看到錯誤是否是由更改引入的。Dropbox 工程師本杰明·彼得森(Benjamin Peterson)在 2017 年 Bazel 大會上發(fā)表的關于集成測試的演講中談到了 itest 是如何運行的。

          從這里開始轉換內(nèi)部崩潰報告、功能門控和電子郵件發(fā)送工具,然后開始批量轉換其余面向用戶的代碼庫。

          嚴謹?shù)囊饬x

          編寫代碼轉換器時我們學到的一條經(jīng)驗是:你必須嚴謹,涵蓋每個角落才行。明確指出哪些內(nèi)容沒有覆蓋是非常重要的,因為錯過的任何場景都可能會出錯。如果要編寫自己的轉換工具,請參考以下提示:

          • 每當你為一個 node 類型添加轉換時,請在文檔中查看需要覆蓋的所有情況。
          • 如果你認為某個 node 類型不太可能出現(xiàn)并且不值得覆蓋,請拋出一個錯誤;這樣一來,如果它確實出現(xiàn)在代碼中,你就不會感到驚訝了。為此,我們高度依賴 ESTree 規(guī)范 和 ts-estree 源代碼。
          • 每當你發(fā)現(xiàn)錯誤時,請搜索你的代碼庫以查找該錯誤模式的其他實例并修復它們。否則,你會在生產(chǎn)中不停遇到類似的錯誤,結果焦頭爛額。

          尾聲

          在項目的最后幾周,我們一次轉換大約 100-200 個文件。通過改進工具,讓這種規(guī)模的轉換可以在幾個小時的工程時間內(nèi)完成。這意味著可以在一兩天內(nèi)就從零開始集成到主分支中,盡量降低重新部署的開銷。大部分時間都花在類型檢查和調(diào)整上了,因為在前期驗證工作中已經(jīng)解決了 Jasmine 和 Selenium 測試的大多數(shù)問題。

          我們的一個技巧是在代碼庫上運行 tsc --noEmit --watch 快速迭代,這樣就可以在大約 10 秒內(nèi)獲得增量類型檢查結果。之所以能這么快,部分是因為在遷移過程中從 TypeScript 2.5 升級到了 2.6,后者大幅提升了 --watch 的速度。

          為了保持專注,我們還在團隊區(qū)的白板上寫上了剩余的 CoffeeScript 文件的計數(shù),并在每次將代碼合并到 master 分支時更新數(shù)據(jù)。

          轉換完最后的 CoffeeScript 之后,我們與內(nèi)部客戶一起暢飲咖啡,歡送 CoffeeScript。

          只有兩個錯誤

          我們一開始就知道,如果引發(fā)了太多錯誤,整個項目最后都會報銷。結果,我只記得有兩個錯誤進入了生產(chǎn)環(huán)境。大多數(shù)潛在錯誤是在手動修復類型檢查錯誤時引入的,盡管我們的測試覆蓋率不高,但它們并沒有闖過我們 Jasmine 和 Selenium 測試的考驗。

          因此,大多數(shù)團隊除了意識到他們的代碼現(xiàn)在是 TypeScript 之外,并沒有感到有什么變化。雖然他們需要重做一些工作,但他們很滿意新的 TypeScript 環(huán)境,因此我們沒有收到太多抱怨。

          我們最后才轉換那些最擔心出問題的團隊的代碼,這樣就能用之前零錯誤的表現(xiàn)說服他們了。但有一個團隊還是不放心,于是我們承諾說:即便出現(xiàn)了重大錯誤,我們也會 24 小時快速響應并修復(只要他們告訴我們?nèi)绾沃噩F(xiàn)),還會在一個工作日內(nèi)解決次要錯誤。

          之所以做出這一承諾,是因為我們對轉換腳本充滿信心。結果他們并沒有遇到重大錯誤,唯一一個小錯誤我們也是在異常報告中發(fā)現(xiàn)的,在他們第二天上班之前就解決掉了。

          還有一些錯誤一開始他們說是我們的轉換造成的,但最后都被我們證明來自于其他原因。

          回顧

          最終,自動遷移過程僅花費了大約兩個月時間,有三名工程師參與,花費了大約 19 個工程師周。當然,遷移輸出的不是大多數(shù)人最初想要的理想的 TypeScript,而是一些雜亂無章,遍布 any 的 TypeScript。

          這一代價是值得的。它讓我們更快地擺脫了 CoffeeScript,這樣就不用繼續(xù)支持 CoffeeScript,也不用讓新員工學習這種語言??梢栽谒械胤绞褂?TypeScript,同時逐步改進代碼樣式和類型安全。

          在整個過程中我們吸取了很多技術教訓,其中可能最重要的教訓是:應該將政治和組織資源省下來,用在不能為所有人自動化的那些任務上。盡管沒有人特別喜歡 CoffeeScript,而且有些團隊可能已經(jīng)自愿將代碼轉換為 TypeScript,但讓其他人在一年時間里手動轉換到 TypeScript 的要求太不切實際了。

          事后看來,我們應該盡量自動化那些重復性的勞動,遇到無法自動化,真正需要專業(yè)編程知識的問題時才去動用寶貴的人力資源。

          現(xiàn)今

          后記:快進到 2020 年,Dropbox 已經(jīng)有了 200 萬行 TypeScript 代碼。我們的整個代碼庫都是靜態(tài)類型的,并且內(nèi)部有一個繁榮的 TypeScript 社區(qū)。TypeScript 使我們能夠擴展工程組織,使各個團隊可以獨立工作,同時在整個代碼庫中保持清晰的聯(lián)系。

          TypeScript 這種語言已迅速普及,我們很幸運能成為最早遷移的大公司之一。因此我們得以發(fā)展這一領域的專業(yè)知識并與外界分享。我們的 JS 公會定期分享 TypeScript 的技巧和竅門,我們的工程師喜歡他們使用的語言。一位工程師甚至撰寫了一份案例研究,總結 TypeScript 不是 JavaScript 嚴格超集的那些情況。

          仍然有少數(shù)文件帶有“此文件從 coffeescript 遷移過來”的注釋,但這些文件僅占代碼庫的一小部分。我們現(xiàn)在的代碼有良好的類型,并且一般會 push back 那些 any。最近,我們將所有代碼庫都升級到了 TypeScript 3.8?!狹atthew Gerstman

          關注我并轉發(fā)此篇文章,私信我“領取資料”,即可免費獲得InfoQ價值4999元迷你書!


          檔描述

          本文是關注微信小程序的開發(fā)和面試問題,

          由基礎到困難循序漸進,

          適合面試和開發(fā)小程序。

          并有熱點框架(vue react node.js 全棧)前端資源以及后端視頻資源和源碼

          并基于前端進階和面試的需求 總結了常用插件和js算法

          以及html/css 和js熱點面試題

          并總結了熱點React/ES6/Vue面試題

          Vue面試題

          生命周期函數(shù)面試題

          1.什么是 vue 生命周期

          2.vue生命周期的作用是什么

          3.第一次頁面加載會觸發(fā)哪幾個鉤子

          4.簡述每個周期具體適合哪些場景

          5.created和mounted的區(qū)別

          6.vue獲取數(shù)據(jù)在哪個周期函數(shù)

          7.請詳細說下你對vue生命周期的理解?

          vue路由面試題

          1.mvvm 框架是什么?

          2.vue-router 是什么?它有哪些組件

          3.active-class 是哪個組件的屬性?

          4.怎么定義 vue-router 的動態(tài)路由? 怎么獲取傳過來的值

          5.vue-router 有哪幾種導航鉤子?

          6.$route 和 $router 的區(qū)別

          7.vue-router響應路由參數(shù)的變化

          8.vue-router傳參

          9.vue-router的兩種模式

          10.vue-router實現(xiàn)路由懶加載( 動態(tài)加載路由 )

          vue常見面試題

          1.vue優(yōu)點

          2.vue父組件向子組件傳遞數(shù)據(jù)?

          3.子組件像父組件傳遞事件

          4.v-show和v-if指令的共同點和不同點

          5.如何讓CSS只在當前組件中起作用

          6.<keep-alive></keep-alive>的作用是什么?

          7.如何獲取dom

          8.說出幾種vue當中的指令和它的用法?

          9. vue-loader是什么?使用它的用途有哪些?

          10.為什么使用key

          11.axios及安裝

          12.axios解決跨域

          13.v-modal的使用

          14.scss的安裝以及使用

          15. 請說出vue.cli項目中src目錄每個文件夾和文件的用法?

          16.分別簡述computed和watch的使用場景

          17.v-on可以監(jiān)聽多個方法嗎

          18.$nextTick的使用

          19.vue組件中data為什么必須是一個函數(shù)

          20.vue事件對象的使用

          21 組件間的通信

          22.漸進式框架的理解

          23.Vue中雙向數(shù)據(jù)綁定是如何實現(xiàn)的

          24.單頁面應用和多頁面應用區(qū)別及優(yōu)缺點

          25.vue中過濾器有什么作用及詳解

          26.v-if和v-for的優(yōu)先級

          27.assets和static的區(qū)別

          28.列舉常用的指令

          29.vue常用的修飾符

          30.數(shù)組更新檢測

          31.Vue.set視圖更新

          32.自定義指令詳解

          33.vue的兩個核心點

          34.vue和jQuery的區(qū)別

          35 引進組件的步驟

          36.Vue-cli打包命令是什么?打包后悔導致路徑問題,應該在哪里修改

          37.三大框架的對比

          38. 跨組件雙向數(shù)據(jù)綁定

          39.delete和Vue.delete刪除數(shù)組的區(qū)別

          40.SPA首屏加載慢如何解決

          41.Vue-router跳轉和location.href有什么區(qū)別

          42. vue slot

          43.你們vue項目是打包了一個js文件,一個css文件,還是有多個文件?

          44.vue遇到的坑,如何解決的?

          45.Vue里面router-link在電腦上有用,在安卓上沒反應怎么解決?

          46.Vue2中注冊在router-link上事件無效解決方法

          47.RouterLink在IE和Firefox中不起作用(路由不跳轉)的問題

          48.axios的特點有哪些

          49.請說下封裝 vue 組件的過程?

          50.vue 各種組件通信方法(父子 子父 兄弟 爺孫 毫無關系的組件)

          51.params和query的區(qū)別

          52. vue mock數(shù)據(jù)

          53 vue封裝通用組件

          54.vue初始化頁面閃動問題

          55.vue禁止彈窗后的屏幕滾動

          56.vue更新數(shù)組時觸發(fā)視圖更新的方法

          57.vue常用的UI組件庫

          58. vue如何引進本地背景圖片

          59. vue如何引進sass

          60.vue修改打包后靜態(tài)資源路徑的修改

          vuex常見面試題

          1.vuex是什么?怎么使用?哪種功能場景使用它?

          2.vuex有哪幾種屬性

          3.不使用Vuex會帶來什么問題

          4.Vue.js中ajax請求代碼應該寫在組件的methods中還是vuex的actions中?

          5.vuex一個例子方法

          6.Vuex中如何異步修改狀態(tài)

          7.Vuex中actions和mutations的區(qū)別

          vue項目實戰(zhàn)

          1.頂部懸停效果

          2.電話本列表效果( 右邊字母分類 上下滑動 旁邊字母顯示高亮)

          3.vue做代理

          4.Vue路由切換時的左滑和右滑效果示例

          ES6面試題

          ES6新增方法面試題

          1.let const var比較

          2.反引號(`)標識

          3.函數(shù)默認參數(shù)

          4.箭頭函數(shù)

          5.屬性簡寫

          6.方法簡寫

          7.Object.keys()方法,獲取對象的所有屬性名或方法名

          8.Object.assign ()原對象的屬性和方法都合并到了目標對象

          9.for...of 循環(huán)

          10.import和export

          11.Promise對象

          12.解構賦值

          13.set數(shù)據(jù)結構(可用于快速去重)

          14.Spread Operator 展開運算符(...)

          15.字符串新增方法

          ES6數(shù)組面試題

          1.forEach()

          2.map()

          3.filter()

          4.reduce()

          5.some()

          6.every()

          7.all()方法

          ES6編程題

          1.使用解構,實現(xiàn)兩個變量的值的交換

          2.利用數(shù)組推導,計算出數(shù)組 [1,2,3,4] 每一個元素的平方并組成新的數(shù)組。

          3.使用ES6改下面的模板

          4.把以下代碼使用兩種方法,來依次輸出0到9?

          react面試題

          react生命周期面試題

          1.react 生命周期函數(shù)

          2.react生命周期中,最適合與服務端進行數(shù)據(jù)交互的是哪個函數(shù)

          3.運行階段生命周期調(diào)用順序

          4.shouldComponentUpdate 是做什么的,(react 性能優(yōu)化是哪個周期函數(shù)?)

          5.指出(組件)生命周期方法的不同

          react 基礎面試題

          1.React 中 keys 的作用是什么?

          2.React 中 refs 的作用是什么?

          3.React 中有三種構建組件的方式

          4.調(diào)用 setState 之后發(fā)生了什么?

          5.react diff 原理(???,大廠必考)

          6.為什么建議傳遞給 setState 的參數(shù)是一個 callback 而不是一個對象

          7.除了在構造函數(shù)中綁定 this,還有其它方式嗎

          8.setState第二個參數(shù)的作用

          9.(在構造函數(shù)中)調(diào)用 super(props) 的目的是什么

          10.簡述 flux 思想

          11.在 React 當中 Element 和 Component 有何區(qū)別?

          12.描述事件在 React 中的處理方式。

          13.createElement 和 cloneElement 有什么區(qū)別?

          14.如何告訴 React 它應該編譯生產(chǎn)環(huán)境版本?

          15.Controlled Component 與 Uncontrolled Component 之間的區(qū)別是什么?

          react組件面試題

          1.展示組件(Presentational component)和容器組件(Container component)之間有何不同

          2.類組件(Class component)和函數(shù)式組件(Functional component)之間有何不同

          3.(組件的)狀態(tài)(state)和屬性(props)之間有何不同

          4.何為受控組件(controlled component)

          5.何為高階組件(higher order component)

          6.應該在 React 組件的何處發(fā)起 Ajax 請求

          7.react中組件傳值

          8.什么時候在功能組件( Class Component )上使用類組件( Functional Component )?

          9.受控組件( controlled component )與不受控制的組件( uncontrolled component )有什么區(qū)別?

          10.react 組件的劃分業(yè)務組件技術組件?

          redux面試題

          1.redux中間件

          2.redux有什么缺點

          3.了解 redux 么,說一下 redux 把

          react性能比較面試題

          1.vue和react的區(qū)別

          2.react性能優(yōu)化的方案

          3.React 項目用過什么腳手架

          4.介紹一下webpack webpack

          5.如果你創(chuàng)建了類似于下面的 Twitter 元素,那么它相關的類定義是啥樣子的?

          6.為什么我們需要使用 React 提供的 Children API 而不是 JavaScript 的 map?

          js面試題

          1.簡述同步和異步的區(qū)別

          2.怎么添加、移除、復制、創(chuàng)建、和查找節(jié)點

          3.實現(xiàn)一個函數(shù)clone 可以對Javascript中的五種主要數(shù)據(jù)類型(Number、string、Object、Array、Boolean)進行復制

          4.如何消除一個數(shù)組里面重復的元素

          5.寫一個返回閉包的函數(shù)

          6.使用遞歸完成1到100的累加

          7.Javascript有哪幾種數(shù)據(jù)類型

          8.如何判斷數(shù)據(jù)類型

          9.console.log(1+'2')和console.log(1-'2')的打印結果

          10.Js的事件委托是什么,原理是什么

          11.如何改變函數(shù)內(nèi)部的this指針的指向

          12.列舉幾種解決跨域問題的方式,且說明原理

          13.談談垃圾回收機制的方式及內(nèi)存管理

          14.寫一個function ,清除字符串前后的空格

          15.js實現(xiàn)繼承的方法有哪些

          16.判斷一個變量是否是數(shù)組,有哪些辦法

          17.let ,const ,var 有什么區(qū)別

          18.箭頭函數(shù)與普通函數(shù)有什么區(qū)別

          19.隨機取1-10之間的整數(shù)

          20.new操作符具體干了什么

          21.Ajax原理

          22.模塊化開發(fā)怎么做

          23.異步加載Js的方式有哪些

          24.xml和 json的區(qū)別

          25.webpack如何實現(xiàn)打包的

          26.常見web安全及防護原理

          27.用過哪些設計模式

          28.為什么要同源限制

          29.offsetWidth/offsetHeight,clientWidth/clientHeight與scrollWidth/scrollHeight的區(qū)別

          30.javascript有哪些方法定義對象

          31.說說你對promise的了解

          32.談談你對AMD、CMD的理解

          33.web開發(fā)中會話跟蹤的方法有哪些

          34.介紹js有哪些內(nèi)置對象?

          35.說幾條寫JavaScript的基本規(guī)范?

          36.javascript創(chuàng)建對象的幾種方式?

          37.eval是做什么的?

          38.null,undefined 的區(qū)別?

          39.[“1”, “2”, “3”].map(parseInt) 答案是多少?

          40.javascript 代碼中的”use strict”;是什么意思 ? 使用它區(qū)別是什么?

          41.js延遲加載的方式有哪些?

          42.defer和async

          43.說說嚴格模式的限制

          44.attribute和property的區(qū)別是什么?

          45.ECMAScript6 怎么寫class么,為什么會出現(xiàn)class這種東西?

          46.常見兼容性問題

          47.函數(shù)防抖節(jié)流的原理

          48.原始類型有哪幾種?null是對象嗎?

          49.為什么console.log(0.2+0.1==0.3) //false

          50.說一下JS中類型轉換的規(guī)則?

          51.深拷貝和淺拷貝的區(qū)別?如何實現(xiàn)

          52.如何判斷this?箭頭函數(shù)的this是什么

          53.== 和 ===的區(qū)別

          54.什么是閉包

          55.JavaScript原型,原型鏈 ? 有什么特點?

          56.typeof()和instanceof()的用法區(qū)別

          57.什么是變量提升

          58.all、apply以及bind函數(shù)內(nèi)部實現(xiàn)是怎么樣的

          59.為什么會出現(xiàn)setTimeout倒計時誤差?如何減少

          60.談談你對JS執(zhí)行上下文棧和作用域鏈的理解

          61.new的原理是什么?通過new的方式創(chuàng)建對象和通過字面量創(chuàng)建有什么區(qū)別?

          62.prototype 和 proto 區(qū)別是什么?

          63.使用ES5實現(xiàn)一個繼承?

          64.取數(shù)組的最大值(ES5、ES6)

          65.ES6新的特性有哪些?

          66.promise 有幾種狀態(tài), Promise 有什么優(yōu)缺點 ?

          67.Promise構造函數(shù)是同步還是異步執(zhí)行,then呢 ?promise如何實現(xiàn)then處理 ?

          68.Promise和setTimeout的區(qū)別 ?

          69.如何實現(xiàn) Promise.all ?

          70.如何實現(xiàn) Promise.finally ?

          71.如何判斷img加載完成

          72.如何阻止冒泡?

          73.如何阻止默認事件?

          74.ajax請求時,如何解釋json數(shù)據(jù)

          75.json和jsonp的區(qū)別?

          76.如何用原生js給一個按鈕綁定兩個onclick事件?

          77.拖拽會用到哪些事件

          78.document.write和innerHTML的區(qū)別

          79.jQuery的事件委托方法bind 、live、delegate、on之間有什么區(qū)別?

          80.瀏覽器是如何渲染頁面的?

          81.$(document).ready()方法和window.onload有什么區(qū)別?

          82. jquery中$.get()提交和$.post()提交有區(qū)別嗎?

          83.對前端路由的理解?前后端路由的區(qū)別?

          84.手寫一個類的繼承

          85.XMLHttpRequest:XMLHttpRequest.readyState;狀態(tài)碼的意思

          正則表達式常見面試題

          1.給一個連字符串例如:get-element-by-id轉化成駝峰形式。

          2.匹配二進制數(shù)字

          3.非零的十進制數(shù)字 (有至少一位數(shù)字, 但是不能以0開頭)

          4.匹配一年中的12個月

          5.匹配qq號最長為13為

          6.匹配常見的固定電話號碼

          7.匹配ip地址

          8.匹配用尖括號括起來的以a開頭的字符串

          9.分割數(shù)字每三個以一個逗號劃分

          10.判斷字符串是否包含數(shù)字

          11.判斷電話號碼

          12.判斷是否符合指定格式

          13.判斷是否符合USD格式

          14.JS實現(xiàn)千位分隔符

          15.獲取 url 參數(shù)

          16.驗證郵箱

          17.驗證身份證號碼

          18.匹配漢字

          19.去除首尾的'/'

          20.判斷日期格式是否符合 '2017-05-11'的形式,簡單判斷,只判斷格式

          21.判斷日期格式是否符合 '2017-05-11'的形式,嚴格判斷(比較復雜)

          22.IPv4地址正則

          23.十六進制顏色正則

          24.車牌號正則

          25.過濾HTML標簽

          26.密碼強度正則,最少6位,包括至少1個大寫字母,1個小寫字母,1個數(shù)字,1個特殊字符

          27.URL正則

          28.匹配浮點數(shù)

          瀏覽器/html/css面試題

          1.什么是盒模型

          2.行內(nèi)元素有哪些?塊級元素有哪些? 空(void)元素有那些?行內(nèi)元素和塊級元素有什么區(qū)別?

          3.簡述src和href的區(qū)別

          4.什么是css Hack

          5.什么叫優(yōu)雅降級和漸進增強

          6.px和em的區(qū)別

          7.HTML5 為什么只寫

          8.Http的狀態(tài)碼有哪些

          9.一次完整的HTTP事務是怎么一個過程

          10.HTTPS是如何實現(xiàn)加密

          11.瀏覽器是如何渲染頁面的

          12.瀏覽器的內(nèi)核有哪些?分別有什么代表的瀏覽器

          13.頁面導入時,使用link和@import有什么區(qū)別

          14.如何優(yōu)化圖像,圖像格式的區(qū)別

          15.列舉你了解Html5. Css3 新特性

          16.可以通過哪些方法優(yōu)化css3 animation渲染

          17.列舉幾個前端性能方面的優(yōu)化

          18.如何實現(xiàn)同一個瀏覽器多個標簽頁之間的通信

          19.瀏覽器的存儲技術有哪些

          20.css定位方式

          21.盡可能多的寫出瀏覽器兼容性問題

          22.垂直上下居中的方法

          23.響應式布局原理

          25.清除浮動的方法

          26.http協(xié)議和tcp協(xié)議

          27.刷新頁面,js請求一般會有哪些地方有緩存處理

          28.如何對網(wǎng)站的文件和資源進行優(yōu)化

          29.你對網(wǎng)頁標準和W3C重要性的理解

          30.Http和https的區(qū)別

          31.data-屬性的作用

          32.如何讓Chrome瀏覽器顯示小于12px的文字

          33.哪些操作會引起頁面回流(Reflow)

          34.CSS預處理器的比較less sass

          35.如何實現(xiàn)頁面每次打開時清除本頁緩存

          36.什么是Virtual DOM,為何要用Virtual DOM

          37.偽元素和偽類的區(qū)別

          38.http的幾種請求方法和區(qū)別

          39.前端需要注意哪些SEO

          40.的title和alt有什么區(qū)別

          41.從瀏覽器地址欄輸入url到顯示頁面的步驟

          42.如何進行網(wǎng)站性能優(yōu)化

          43.語義化的理解

          44.HTML5的離線儲存怎么使用,工作原理能不能解釋一下?

          45.瀏覽器是怎么對HTML5的離線儲存資源進行管理和加載的呢

          46.iframe有那些缺點?

          47.WEB標準以及W3C標準是什么?

          48.Doctype作用? 嚴格模式與混雜模式如何區(qū)分?它們有何意義?

          49.HTML全局屬性(global attribute)有哪些

          50.Canvas和SVG有什么區(qū)別?

          51.如何在頁面上實現(xiàn)一個圓形的可點擊區(qū)域?

          52.網(wǎng)頁驗證碼是干嘛的,是為了解決什么安全問題

          53.請描述一下 cookies,sessionStorage 和 localStorage 的區(qū)別?

          54. CSS選擇器有哪些?哪些屬性可以繼承?

          55.CSS優(yōu)先級算法如何計算?

          56.CSS3有哪些新特性?

          57.請解釋一下CSS3的flexbox(彈性盒布局模型),以及適用場景?

          58.用純CSS創(chuàng)建一個三角形的原理是什么?

          59.常見的兼容性問題?

          60.為什么要初始化CSS樣式

          61.absolute的containing block計算方式跟正常流有什么不同?

          62.CSS里的visibility屬性有個collapse屬性值?在不同瀏覽器下以后什么區(qū)別?

          63.display:none與visibility:hidden的區(qū)別?

          64.position跟display、overflow、float這些特性相互疊加后會怎么樣?

          65.對BFC規(guī)范(塊級格式化上下文:block formatting context)的理解?

          66.為什么會出現(xiàn)浮動和什么時候需要清除浮動?清除浮動的方式?

          67.上下margin重合的問題

          68. 設置元素浮動后,該元素的display值是多少?

          69.移動端的布局用過媒體查詢嗎?

          70.CSS優(yōu)化、提高性能的方法有哪些?

          71.瀏覽器是怎樣解析CSS選擇器的?

          72.在網(wǎng)頁中的應該使用奇數(shù)還是偶數(shù)的字體?為什么呢?

          73.margin和padding分別適合什么場景使用?

          74.元素豎向的百分比設定是相對于容器的高度嗎?

          75.全屏滾動的原理是什么?用到了CSS的哪些屬性?

          76.什么是響應式設計?響應式設計的基本原理是什么?如何兼容低版本的IE?

          77. 視差滾動效果?

          78.::before 和 :after中雙冒號和單冒號有什么區(qū)別?解釋一下這2個偽元素的作用

          79.讓頁面里的字體變清晰,變細用CSS怎么做?

          80. position:fixed;在android下無效怎么處理?

          81.如果需要手動寫動畫,你認為最小時間間隔是多久,為什么?

          82.li與li之間有看不見的空白間隔是什么原因引起的?有什么解決辦法?

          83.display:inline-block 什么時候會顯示間隙?

          84. 有一個高度自適應的div,里面有兩個div,一個高度100px,希望另一個填滿剩下的高度

          85.png、jpg、gif 這些圖片格式解釋一下,分別什么時候用。有沒有了解過webp?

          86.style標簽寫在body后與body前有什么區(qū)別?

          87.CSS屬性overflow屬性定義溢出元素內(nèi)容區(qū)的內(nèi)容會如何處理?

          88.闡述一下CSS Sprites

          89. 一行或多行文本超出隱藏

          微信小程序開發(fā)(持續(xù)更新)

          ?

          初識小程序

          1.注冊小程序

          2.微信開發(fā)者工具

          3.小程序與普通網(wǎng)頁開發(fā)的區(qū)別

          4.小程序尺寸單位rpx

          5.樣式導入(WeUI for)

          6.選擇器

          7.小程序image高度自適應及裁剪問題

          8.微信小程序長按識別二維碼

          9.給頁面加背景色

          10.微信小程序獲取用戶信息

          11.代碼審核和發(fā)布

          12.小程序微信認證

          13.小程序申請微信支付

          14.小程序的目錄解構及四種文件類型

          15.小程序文件的作用域

          16.小程序常用組件

          1.view

          2.scroll-view

          3.swiper組件

          4.movable-view

          5.cover-view

          6.cover-image

          小程序基礎

          17.授權得到用戶信息

          18.數(shù)據(jù)綁定

          19.列表渲染

          20.條件渲染

          21.公共模板建立

          22.事件及事件綁定

          23.引用

          24.頁面跳轉

          1.wx.switchTab

          2.wx.reLaunch

          3.wx.redirectTo

          4.wx.navigateTo

          5.wx.navigateBack

          25.設置tabBar

          26.頁面生命周期

          27.轉發(fā)分享

          小程序高級

          28.request請求后臺接口

          29.http-promise 封裝

          30.webview

          31.獲取用戶收貨地址

          32.獲取地里位置

          33.自定義組件

          34.微信小程序支付問題

          小程序項目實戰(zhàn)

          35.微信小程序本地數(shù)據(jù)緩存

          36.下拉刷新和下拉加載

          37.列表頁向詳情頁跳轉(動態(tài)修改title)

          38.客服電話

          39.星級評分組件

          40.小程序插槽的使用slot

          41.模糊查詢

          42.wxs過濾

          43.小程序動畫

          44.列表根據(jù)索引值渲染

          45.小程序動態(tài)修改class

          46.小程序常用框架

          47.參數(shù)傳值的方法

          48.提高小程序的應用速度

          49.微信小程序的優(yōu)劣勢

          50.小程序的雙向綁定和vue的區(qū)別

          51.微信小程序給按鈕添加動畫

          52.微信小程序的tab按鈕的轉換

          53.微信小程序引進echarts

          54.APP打開小程序流程

          55.小程序解析富文本編輯器

          小程序常見bug

          1.域名必須是HTTPS

          2. input組件placeholder字體顏色

          3. wx.navigateTo無法跳轉到帶tabbar的頁面

          4. tabbar在切換時頁面數(shù)據(jù)無法刷新

          5.如何去掉自定義button灰色的圓角邊框

          6.input textarea是APP的原生組件,z-index層級最高

          7.一段文字如何換行

          8.設置最外層標簽的margin-bottom在IOS下不生效

          9.小程序中canvas的圖片不支持base64格式

          10.回到頁面頂部

          11.wx.setStorageSync和wx.getStorageSync報錯問題

          12.如何獲取微信群名稱?

          13.new Date跨平臺兼容性問題

          14.wx.getSystemInfoSync獲取windowHeight不準確

          15.圖片本地資源名稱,盡量使用小寫命名

          移動端熱點問題

          1. 1px border問題

          2.2X圖 3X圖適配

          3.圖片在安卓上,有些設備模糊問題

          4.固定定位布局 鍵盤擋住輸入框內(nèi)容

          5.click的300ms延遲問題和點擊穿透問題

          6.phone及ipad下輸入框默認內(nèi)陰影

          7.防止手機中頁面放大和縮小

          8.flex布局

          9.px、em、rem、%、vw、vh、vm這些單位的區(qū)別

          10. 移動端適配- dpr淺析

          11.移動端擴展點擊區(qū)域

          12 上下拉動滾動條時卡頓、慢

          13 長時間按住頁面出現(xiàn)閃退

          14. ios和android下觸摸元素時出現(xiàn)半透明灰色遮罩

          15. active兼容處理 即 偽類:active失效

          16.webkit mask兼容處理

          17. pc端與移動端字體大小的問題

          18. transiton閃屏

          19.圓角bug

          20.如何解決禁用表單后移動端樣式不統(tǒng)一問題?

          js常用插件

          輪播圖插件

          二級城市插件

          三級城市插件

          文字滑動效果

          手風琴效果

          視頻播放插件

          彈層插件

          百度編輯器

          ACE編輯器(輕巧)

          上傳圖片(裁剪)

          頁面加載效果

          全選反選各種效果

          京東樓層效果

          懶加載

          快速建站(全棧)

          dedecms(文章累)

          discuz(論壇)

          ecshop(電商)

          PHPEMS(考試)


          主站蜘蛛池模板: 国模一区二区三区| 国产精品一区二区av| 日韩精品无码视频一区二区蜜桃| 波多野结衣中文字幕一区二区三区| 亚洲sm另类一区二区三区| 精品一区二区三区在线播放视频| 国产自产对白一区| 精品一区二区91| 少妇激情av一区二区| 在线电影一区二区| 国产在线aaa片一区二区99| 精品国产乱子伦一区二区三区 | 国产成人高清亚洲一区久久| 一级毛片完整版免费播放一区| av无码人妻一区二区三区牛牛 | 无码人妻av一区二区三区蜜臀| 国产凸凹视频一区二区| 国产一区二区精品| 国产麻豆媒一区一区二区三区| 国精产品一区一区三区免费视频| 日本午夜精品一区二区三区电影| 精品国产天堂综合一区在线| 熟女性饥渴一区二区三区| 无码人妻aⅴ一区二区三区有奶水| 国产亚洲一区二区三区在线不卡| 日韩精品一区二区三区老鸭窝| 无码日韩人妻AV一区二区三区| 亚洲午夜精品一区二区公牛电影院 | 日韩免费无码一区二区视频| 日本免费一区二区久久人人澡| 国产成人一区二区动漫精品| 精品无码人妻一区二区三区| 变态拳头交视频一区二区| 麻豆一区二区免费播放网站| 国精产品一区一区三区| 色欲AV无码一区二区三区| 久久精品国产AV一区二区三区| 国产另类ts人妖一区二区三区| 成人精品一区二区激情| 久久久久人妻一区精品色| 不卡一区二区在线|