[有贊社招-前端面試經歷分享] 電話面+技術面+hr面

前提摘要

通過朋友介紹,經過了有讚的內部推薦,算是經歷了完整的面試流程,寫在掘金上分享一下,本人大概狀況:掘金小透明,前端技術廢,歡迎留言拍磚,分享記得署名轉載地址。若是對我技術感興趣的話,歡迎發來邀請,期待與你共事。javascript

第一次在掘金髮文,若是文章格式不規範或者文章中存在形成歧義的地方,先行道歉,請您告知我,配圖大多來源於網絡,形成侵權的話會當即刪除,期待你的修改建議。php


電話面試

有讚的面試流程是內推流程過了後,會有電話面試的人跟你約你方便的時間,約好時間就會在當天收到電話面試。css

如下是一些問題,時間不分前後。
1.http協議中301和302的區別
http協議中,301表明資源的永久重定向,302表明資源的臨時重定向,當時還舉了一個Restful的例子,觀察到不少的第三方受權,受權事後的回跳地址常常會使用301形式,改變瀏覽器的回跳地址。html

2.介紹下Restful
當時被問到這個問題感受太籠統了,就介紹了下Restful的集中請求格式,GET從服務器取出資源,POST在服務器新建一個資源,PUT在服務器更新資源,PATCH在服務器部分更新資源,DELETE從服務器刪除資源。前端

3.描述如下POST和PUT的區別
POST經常使用於提交數據至服務端,新建資源時使用。PUT用於修改更新已存在的資源時使用。多說了如下關於GET和POST的區別,GET請求多數採用查詢數據時使用,不推薦對資源的更新及新建,容易形成服務器數據泄漏,或者XSS或者CSRF攻擊。vue

4.XSS攻擊的場景能描述一個麼?
表單提交過程當中,須要對提交的數據進行引號,尖括號,斜槓進行轉義,防止標籤或者是eval()的惡意代碼注入。java

5.介紹下304過程。
a.瀏覽器請求資源時首先命中資源的Expires 和 Cache-Control,Expires 受限於本地時間,若是修改了本地時間,可能會形成緩存失效,能夠經過Cache-control: max-age指定最大生命週期,狀態仍然返回200,但不會請求數據,在瀏覽器中能明顯看到from cache字樣
b.強緩存失效,進入協商緩存階段,首先驗證ETagETag能夠保證每個資源是惟一的,資源變化都會致使ETag變化。服務器根據客戶端上送的If-None-Match值來判斷是否命中緩存。
c.協商緩存Last-Modify/If-Modify-Since階段,客戶端第一次請求資源時,服務服返回的header中會加上Last-Modify,Last-modify是一個時間標識該資源的最後修改時間。再次請求該資源時,request的請求頭中會包含If-Modify-Since,該值爲緩存以前返回的Last-Modify。服務器收到If-Modify-Since後,根據資源的最後修改時間判斷是否命中緩存。node

6.說一下瀏覽器中的事件機制。
剛被問的時候有點懵,確認了下是否是問關於事件冒泡和捕獲方面的知識。
我舉了一個點擊事件傳遞的例子,從root往事件觸發處傳播,遇到註冊的捕獲事件會觸發,傳播到事件觸發處時觸發註冊的事件,從事件觸發處往root傳播,遇到註冊的冒泡事件會觸發,若是給一個目標節點(觸發節點)同時註冊冒泡和捕獲事件,事件觸發會按照註冊的順序執行。python

[fix 1.0.2]感謝評論區一隻小生對上邊表述的校驗。
當同一控件即綁定冒泡又綁定捕獲事件時,事件觸發會按照綁定的順序執行
修改成若是給一個目標節點(觸發節點)同時註冊冒泡和捕獲事件,事件觸發會按照註冊的順序執行webpack

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Demo</title>
</head>
<body>
    <div id="root">root
        <p id="parent">parent
            <span id="child">child</span>
        </p>
    </div>
    <script> let parentNode = document.getElementById('parent') // 由於觸發標籤不一樣,致使輸出順序不一樣 // 點擊parent會輸出冒泡,捕獲,由於目標節點按照綁定順序輸出 // 點擊child會輸出捕獲,冒泡,由於非目標節點正常按照瀏覽器事件機制執行 parentNode.addEventListener( 'click', event => { console.log('冒泡') }, false ) parentNode.addEventListener( 'click', event => { console.log('捕獲 ') }, true ) </script>
</body>
</html>
複製代碼

7.簡述一下防抖和截流,並口述一下防抖模擬的大體流程
防抖動是將屢次執行變爲最後一次執行,節流是將屢次執行變成每隔一段時間執行。
設置定時器,並判斷當前函數是否須要當即執行,若是須要則當即執行。不然進入正常的防抖邏輯,設置setTimeout定時器,同時緩存這個定時器,在定時器倒計時階段,判斷timer是否爲null,若是不爲空緩存當前執行上下文,重複調用則重複更新,直到保存到執行的那一刻。若是爲空,則開始下一輪的防抖計時。

8.簡述下瀏覽器的Event loop
javascript是非阻塞單線程語言,瀏覽器的javascript運行環境將js分紅兩種任務,分別爲宏任務和微任務,一個正常的Event loop執行順序大概是:

  1. 執行同步代碼,這屬於宏任務
  2. 執行棧爲空,查詢是否有微任務須要執行
  3. 執行全部微任務
  4. 必要的話渲染 UI
  5. 而後開始下一輪 Event loop,執行宏任務中的異步代碼
    其中宏任務包括:同步代碼 , setTimeout ,setInterval ,setImmediate ,I/O ,UI渲任務
    微任務包括:promise ,Object.observe
    這個博文寫的超級好了,不理解的看兩遍確定能理解的,酷家樂的ssssyoki前輩寫的 這一次,完全弄懂 JavaScript 執行機制

9.請簡述==機制
這個問題涉及到對象的類型若轉換,其實判斷對象相等實際上調用的是對象的toPrimitive方法,就是對象轉基本類型,展開說一下Symbol.toPrimitive方法,其中包含三種判斷,分別是轉化成數字型、字符串型以及默認轉換。

let obj = {
  [Symbol.toPrimitive](hint) {
    switch (hint) {
      case 'number':
        return 123;
      case 'string':
        return 'str';
      case 'default':
        return 'default';
      default:
        throw new Error();
     }
   }
};

// [防爬蟲標識-沙海聽雨]

2 * obj // 246
3 + obj // '3default'
obj == 'default' // true
String(obj) // 'str'
複製代碼

而後又舉了[] == ![]這個經典的例子,大體的轉化過程以下:

[] == ![]
[] == false
[] == ToNumber(false)
[] == 0
ToPrimitive([]) == 0
'' == 0
0 == 0 // -> true
複製代碼

10.請簡述js中的this指針綁定
這個幾乎是常問到的知識點,我在看《你不知道的javascript》書中有過很詳細的描述。js中的this指針綁定總結下包含四種形式:默認綁定,隱式綁定,顯式綁定,new綁定,優先級從小到大,有分別闡述了四種形式的代碼。

// 默認綁定
function foo(){
  console.info(this.a)
}
var a = 'hello'
foo()

// 隱式綁定
// 調用位置是否有上下文對象
function foo() {
  console.info(this.a)
}
var obj = {
  a: 1,
  foo: foo
}
obj.foo()

// 顯式綁定
// 對應apply call bind
// 其中bind又叫硬綁定
// bind(..) 會返回一個硬編碼的新函數,它會把參數設置爲this 的上下文並調用原始函數。

// [防爬蟲標識-沙海聽雨]

// new綁定
// 使用new 來調用函數,或者說發生構造函數調用時,會自動執行下面的操做。
// 1. 建立(或者說構造)一個全新的對象。
// 2. 這個新對象會被執行[[ 原型]] 鏈接。
// 3. 這個新對象會綁定到函數調用的this。
// 4. 若是函數沒有返回其餘對象,那麼new 表達式中的函數調用會自動返回這個新對象。
複製代碼

11.請簡述原型鏈 這個問題,每一個人都有本身心理的原型鏈,一圖勝千言,我就不詳細描述,下圖是跟我同組的人員作的一些討論。基本達成了共識:

其中問號處的是一個頗有意思的雞生蛋蛋生雞的問題,感興趣的話,能夠閱讀下github上邊的一些文章,寫的很深入。這裏推薦一篇stackoverflow的問答 why typeof(Function.prototype) is function

12.說說你理解的閉包
這個問題幾乎前端的面試都會有所涉及,只不過問法不一樣,個人答案:函數嵌套保護內部函數不會被外部函數干擾而造成的一個隔離。

比較經常使用的閉包,能夠舉出隨處可見的數據請求,同時也能說出使用匿名函數回調函數形成的this指針丟失問題。

// 以axios舉例

// 外部this指針暫存
var _self = this
this.$http.get(`/xxx`).then(function (res) {
  // 此處this指針丟失,須要使用暫存的_self
  if (res.data.rc === 0) {
    // 操做
  } else {
    // 異常處理
  }
}).catch(error => {
  console.info(error)
})

// 使用箭頭函數則this指針仍然可用
this.$http.get(`/xxx`).then(res => {
  // 箭頭函數內部的this指針指向外層this
  if (res.data.rc === 0) {
    // 操做
  } else {
    // 異常處理
  }
}).catch(error => {
  console.info(error)
})
複製代碼

另外,有一個特別經典的保護內部變量的問題是Vue框架下,爲何data必須是一個函數,這個問題是當時酷家樂電話面試問的,真是問了個措手不及,反思了下,知識點不能學死板了,靈活串起來容易記憶,傳送門data 必須是一個函數

13.箭頭函數
箭頭函數算是一個特殊的函數,常常看書可能會答得模模糊糊的,其實箭頭函數沒有this指針,它的this指向了外層不是箭頭函數的this。

function foo () {
  // this
  () = > {
      () => {
          // ...
          // [防爬蟲標識-掘金-沙海聽雨]
          // 無論嵌套幾層,一直往上找到不是箭頭函數的位置,箭頭函數內部的this就指向它
      }
  }
}
複製代碼

14.ES5繼承實現
口述實現了一下定義一個MyData類的過程

function MyData() {}
MyData.prototype.test = function () {
  return this.getTime()
}
let d = new Date()
Object.setPrototypeOf(d, MyData.prototype)
Object.setPrototypeOf(MyData.prototype, Date.prototype)
複製代碼
  1. 先建立父類實例
  2. 改變實例原先的 proto_ 轉而鏈接到子類的 prototype
  3. 子類的 prototype 的 proto 改成父類的 prototype 但上邊的繼承方式存在一個問題,就是若是須要再次繼承的話,會致使代碼結構複雜化,語意晦澀難懂。

15.說一下virtual Dom中key的做用
實際的標籤中可能存在兩個如出一轍的兩個節點,可是在virtual Dom中沒法體現這個區別,另外一方面爲了加快diff算法的速度,一個區別節點的變量的需求變得很是必要。
virtual Dom中須要給每一個節點一個標識,做爲判斷是同一個節點的依據。因此這也是 Vue 和 React 中官方推薦列表裏的節點使用惟一的 key 來保證性能。
其中在diff算法中,大量使用了利用tagName和key組合判斷節點之間差別的邏輯代碼。

16.Vue 3.0有沒有過了解
關於Vue 3.0有幸看過尤大的關於3.0版本的RFC Vue Function-based API RFC。 大體說了三個點,第一個是關於提出的新API setup()函數,第二個說了對於Typescript的支持,最後說了關於替換Object.defineProperty爲Proxy的支持。
詳細說了下關於Proxy代替帶來的性能上的提高,由於傳統的原型鏈攔截的方法,沒法檢測對象及數組的一些更新操做,但使用Proxy又帶來了瀏覽器兼容問題。

17.Electron
問了下關於這個的使用經驗,這個我看過好多的文章,詳細的使用過程我沒有具體說,最近也在嘗試這個解決方案。就說了下原理,由於大學在實驗室作了3年的C#,對瀏覽器內核嵌入客戶端程序有過一些實踐經驗,這種將B/S程序編譯成C/S程序大體相同,原理是Electron經過將Chromium和Node.js合併到同一個運行時環境中,並將其打包爲Mac,Windows和Linux系統下可運行的客戶端程序。

18.看了下個人簡歷(聽到翻紙的聲音),問了下React和Node有實際項目經驗
這個是個人弱勢吧,以前公司不大,敏捷開發爲主,Vue仍是自學的,源碼啃的亂七八糟的。React和node我跟技術總監申請了無數回嘗試計劃,礙於實施成本無限次pass,有點無奈。
就簡單說了下,我作React和node計劃申請的計劃,node的話,以前籌備了移動端首屏頁面的服務器渲染和SEO方案,以及微服務框架下利用node作中間層的一些嘗試,打算用在實際的項目中使用。
React的話也是沒有過實際的項目經驗,練手的應該不能算經驗吧,以前一直想把公司的一個老項目微頁重構了,老項目的性能和維護成本愈來愈大了,可是公司小一些的話,能用爲主,有點無奈吧。
這種問題這個問題答得很差,其餘同窗引覺得戒吧,多說說本身的亮點和優點啊,加分問題被我答成了減分問題。

19.項目經驗
這個聊了七七八八吧,大概就是最後簡述說一下項目的一些事情,摸一下底,我給上家公司招聘過程當中也發現好多培訓出來的孩子太會面試了,實際操做和經驗年限有些許的水分,我是不排斥培訓出來的人,可是但願面試者都實實在在的吧,這個摸底是必須的吧,問的越詳細越好,至少別等入職以後耽誤了項目進度再從新招人,如今互聯網行業工期都太緊張了。

20.有什麼想問的
這個問題我基本都問關於面試過程當中的感覺,面試官說了一些,簡述的話就是基礎尚可,框架經驗單一,可是電話面試仍是比較喜歡基礎好一些的候選人,跟我想的差很少,就結束了本次電話面試,總體過程仍是挺好的。


後記

有一些比較細碎的問題我記得不是太清楚了,若是能記起來我會再補充一下。
電話面試2-3天左右很快就有了答覆,告訴我經過了,約了複試,電話面試的小哥很負責,陸陸續續打了2個電話反覆溝通。


技術面(現場面試)

1.非覆蓋式發佈
這個問題我回答了很久,一邊回憶一邊說,由於當時配置好以後就全權交給運維去作了,後期維護的一些改變運維方面我沒有及時去看,一直在看產出的報告,致使這個問題我答得磕磕巴巴的,面試以前千萬千萬要回顧並熟知每個細節,不然就是給本身挖坑,下面是我面試時+面試後從新梳理。

首先簡單介紹了覆蓋發佈和非覆蓋發佈的區別

  • 覆蓋發佈: 前端項目打包後每次產生相同的文件名,發佈至服務器時,同名文件直接替換,新文件添加。
  • 非覆蓋式發佈: 採用更新文件名的形式,好比採用webpack的[id].[chunkhash].js的形式,這樣更新文件後,新文件不會影響舊文件的存在。

覆蓋式發佈的缺點:

  • 先更新頁面再更新靜態資源
    新頁面里加載舊的資源,頁面和資源對應不上,會有頁面混亂,還有執行會報錯。
  • 先更新靜態資源再更新頁面
    在靜態資源更新完成,頁面沒有被更新過程當中,有緩存的用戶是正常的。這個時候讀本地的緩存,可是若是沒有緩存的用戶會怎樣?依然是會頁面混亂和執行錯誤,由於在舊的頁面加載新資源

不管如何,覆蓋式發佈都是能被用戶感知到的,因此部分公司的發佈是晚上上線。其中若是使用vue-cli直接生成webpack配置打包的話,直接發佈dist文件夾下資源就會產生這種特殊的替換問題,由於在build.js文件中存在這麼一行代碼,初衷應該是防止dist文件夾愈來愈大,可是rimraf模塊會遞歸刪除目錄全部文件,沒有詳細瞭解過vue-cli生成編譯環境的人,就默認的採用了這種舊資源刪除新資源生成。

// build.js
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
    ...
})
複製代碼

接下來說了下,我更新的發佈模式。

更新了nginx的靜態文件緩存策略

  1. 靜態資源html不使用緩存,每次加載均從服務器中拉取最新的html文件
  2. 靜態資源js/css/圖片資源,採起強緩存策略,這個時間能夠儘量的長一些,由於是非覆蓋式發佈,因此若是html中加載資源URI更新,那麼資源也會統一的更新

nginx能夠對不一樣文件進行不一樣的緩存策略,大體配置以下(須要注意location匹配的優先級):

location ~ .*\.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$
{
    expires      7d;
}

location ~ .*\.(?:js|css)$
{
    expires      7d;
}

location ~ .*\.(?:htm|html)$
{
    add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
}
複製代碼

而後發佈的時候先將除html文件移動至發佈路徑,同名文件默認跳過,新生成的文件會產生新的hash,新舊文件不會衝突,共存在發佈路徑。

html文件的更新當時作了兩種方案

  1. html徹底由前端管理,前端發佈的時候會有html文件,webpack打包時自動在html裏寫文件名;
  2. html由後端管理(服務器渲染),前端只負責發佈js、css等資源文件。在前端發佈以後,後端修改版本號再發布;

由於node經驗匱乏,當時第二種方案用了python寫了一個服務,配置manifest.[chunkhash].jsvendor.[chunkhash].js,若是項目中存在首頁骨架屏,那麼還須要替換html文件body中的內容,用戶服務進來後直接加載這個渲染後的頁面。

最後的最後,被一個問題弄的有些頭大,面試個人TL反覆對我第一種在html中寫文件名的方法提出質疑,我當時是真的有點記不清那個plugin的名字了,回到家review了一下項目,那個plugin的名稱是html-webpack-plugin,這個問題大概卡了接近10分鐘,不知道爲何須要追問這個點,也是本身有點差勁,細節沒記得那麼清楚。

2.python發佈
我就知道我提到了python就會被問這個問題,但沒有問服務器渲染的問題,而是問了我django發佈的問題,我上一個django項目是兩年前的事情了,也多是第一個問題耗掉了好多經歷,思緒有些切換不過來了,表述的很差。

當時只記得是wsgi+apache進行配置的,可能面試個人TL對python瞭解也很少,又問我這種發佈模式不會形成異常中斷,說python是即時編譯型的語言,這種發佈會不會形成異常致使服務所有宕機。我說不會的,這種模式的咱們當初採用的定時任務偶爾會掛掉,可是主服務不會的。

我可能有點被TL的思路繞進去了,表述的很差,回來總結事後有了些印象。

3.cdn
答很差什麼就會一直往下問,面試若是發現狀態不對的話,儘可能別被牽着鼻子走吧,這個問題我中間說錯了一個環節,致使有點崩,我當時說了我當時部署的項目一部分文件是不走cdn的,可能耐心值達到紅色線了,這個是答得是有歧義的。

分場景的話:

  1. 服務器渲染,那麼除html文件均分發一份在cdn上,保證服務器負載
  2. 頻繁更新的配置,好比某些項目是插槽模式嵌入功能的,就須要後端接口生成相應的配置文件,以接口的形式發給前端進行解析。

cdn的配置經驗我比較少,公司的業務場景暫時沒有提供cdn功能,全部的圖片走的是七牛雲的cdn,而服務器的css/js文件方面的cdn部署,沒有相關的使用經驗,面試回到家後一直在找相關的解決方案,若是你有比較好的科普性質的博文,歡迎在評論區留言。

4.項目經驗,我的角色
可能前面的問題答得有些失誤,爲了緩和睦氛問了這個問題。由於我以前一直作公司的web前端負責人,因此這個問題聊的比較迅速。我以前的公司是剛開始是沒有前端的,我算是半路出家,公司從30人發展到500人,前端團隊由2我的發展到接近10我的。而後說了下我主要負責的項目,以及一些團隊協做,風險評估,需求評審,代碼質量保證的一些事情,可能我作的工做有點low,TL的表情反饋有些平靜。

5.gzip編碼協議
這個看過一些,大概就是和緩存策略同樣,須要在服務器進行配置,同時須要瀏覽器的支持。

http {
    ...
    gzip on; // 開啓gzip
    gzip_min_length 1k; // 最小1k的文件才使用gzip
    gzip_buffers 4 8k; // 表明以8k爲單位,按照原始數據大小以8k爲單位的4倍申請內存
    gzip_comp_level 5; // 1 壓縮比最小處理速度最快,9 壓縮比最大但處理最慢(傳輸快但比較消耗cpu)
    gzip_types application/javascript text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; // 支持的文件類型
    gzip_disable "MSIE [1-6]\."; // IE6一下 Gzip支持的很差,故不實用gzip
    ...
}
複製代碼

服務器配置以後,會在瀏覽器請求接口後的response header的Content-Encoding字段看到gzip。

客戶端請求數據時,請求頭中有個Accept-Encoding聲明瀏覽器支持的壓縮方式,當客戶端請求到服務端的時候,服務器解析請求頭,若是客戶端支持gzip壓縮,響應時對請求的資源進行壓縮並返回給客戶端,瀏覽器按照本身的方式解析。

而後拓展問了下,若是傳輸的數據但願後端壓縮,可是算法沒有聲明如何啓用後端算法。我就模擬了下這個流程,客戶端利用header頭部的自定義字段將能夠容忍的壓縮算法告訴服務端,服務端配置容許發送這個自定義header,逐個匹配服務器上當前的算法,匹配到則發送成功結果,沒法匹配則告知客服端數據沒法進行壓縮,等待接下來的操做。

6.用javascript的知識介紹C++的指針
應該是看了我剛畢業的工做是嵌入式方向提出這個問題,這個問題是有點不是好類比的,由於javascript的設計緣由,跟傳統的編譯型語言有很大的不一樣。我用的是原型鏈的知識解釋的C++指針尋址過程,其中二級指針及三級指針的解釋真的須要對兩種語言理解很深刻才能回答上來。原型鏈的東西已經在電話一章節闡述,此處相似,再也不闡述,對C++有興趣的話,推薦多看一下大學課本相似的書籍,乾貨不少。

7.高精度計時器
算是一個解決方案的問題,面試官列舉了一個有贊整點搶單的業務場景,如何同步全部客戶端的時間。因爲setTimeout相似的計時器沒法高精度還原時間,我提出的想法是利用socket保持和服務器的長連接,利用推送的模式,按期給客戶端發送當前服務器時間做爲校驗基準,可是因爲HTTP傳輸的時間沒法保證,因此也只能儘量的同步兩端的時間。

面試官又問了這個服務器推送的頻率你認爲大概須要多少,由於沒有相關業務經驗,只能按照邏輯推理,這個個人描述是當前服務器時間 = 服務器系統返回時間 + 網絡傳輸時間 + 前端渲染時間 + 校準常量(可選),因此這個推送的頻率採用變頻的思路,就是離活動時間有一段時間,那麼推送頻率大概1分鐘2次左右,立刻快開始就須要頻繁推送了,socket性能問題須要經過不斷的矯正才能達到最好的效果,可是若是想100%實現高級度的計時器,以我目前的知識面看,仍是存在不少問題的。

其實這個問題我在C++中就時間過,若是想測試超高級度的定時器,須要中間沒有阻塞線程或者進程,以及防止計算機優先級較高的任務中斷,這個知識涉及到操做系統的好多知識,大概就說到這。

對於這個問題我仍是很感興趣的,由於我面試後發現不少這種活動都有這個時間偏差的問題,或大或小。若是你有過相關的業務場景,歡迎留言區分享你的思路。

8.提取最長有效數字
技術面試過程的最後感受本身可能沒戲了,沒想到還被問了一個現場編碼的題目,大體題意以下:
Input:

  1. '1024word'
  2. ' -1024word'
  3. 'word1024'
  4. '10word24'

Output:

  1. 1024
  2. -1024
  3. 0
  4. 10

程序大概寫了不到5分鐘吧,印象不是太深入了,代碼寫的有點多,能夠更簡單,歡迎在評論區寫出你耳目一新的代碼段。

function parseInt (value) {
    // 輸入值校驗合法性
    if (!value) { return 0; }
    // 本需求對於空格須要剔除
    let temp = value.toString().trim();
    // 攔截全空字符串問題
    if (temp.length === 0) {
        return 0;
    }
    // 收集符號位
    let result = temp[0] === '+' || temp[0] === '-' ? temp[0] : '';
    // 設置開始索引
    let i = result.length > 0 ? 1 : 0;
    // 遍歷,此處使用for循環爲了方便中斷遍歷減小時間複雜度
    for (;i < temp.length; i++) {
        if (temp[i] >= '0' && temp[i] <= '9') {
            result += temp[i]
        } else {
            break;
        }
    }
    // [防爬蟲標識-掘金-沙海聽雨]
    // 判斷存在result爲符號位形成Number('+')輸出NaN問題
    return result && (result === '+' || result === '-') ? 0 : Number(result)
}
複製代碼

問了能不能換種方法實現,我想了一下,說正則提取能夠作到,可是當時就給了10分鐘不到的時間,就沒再繼續了,實際上是以前的問題把思路打亂了,一直在回憶以前沒答好的問題。

[補充1.0.1]
根據評論區Akihi09大佬的正則表達式啓發,想出了一個正則表達式寫法

function parseInt (val) {
  if (typeof val !== 'string') { return 0; }
  let match = val.toString().trim().match(/[+|-]{0,1}[0-9]*/g)[0];
  if (!match) {
    return 0;
  }
  return Number(match)
}
複製代碼

[補充1.0.3]
附錄評論區liuyu322的正則表達式,

function parseInt (val) {
  if (!val || typeof val !== 'string') { return 0; }
  return +val.toString().replace(/^\s*([-+]?\d+)?.*$/, ($0, $1) => $1 || 0)
}
複製代碼

這個表達是裏面用到的概念有點多,一直沒有時間更新,其中幾個關鍵點,在此處分析一下。

^以什麼爲開始
\s匹配任意的空白符
*只匹配出現 0 次及以上 * 前的字符
()分組 []匹配方括號內的任意字符
?以前字符可選
\d匹配數字
+只匹配出現 1 次及以上 + 前的字符 .匹配任意字符除了換行符和回車符(貪婪匹配)

瞭解這個概念應該就對上邊的公式有所瞭解,附上一篇我認爲比較好的正則匹配文章多是最好的正則表達式的教程筆記了吧

9.最後聊了一會骨架屏
好文推薦:餓了麼的 PWA 升級實踐

聊天內容大可能是根據這篇文章我進行的一些嘗試,可是沒有脫離文章的中心。

10.面試的反饋
前端方面接觸面過於窄,告訴我能夠多拓展一下好比React和Node的一些實踐經歷,其餘還有一些關於職業發展的方向,比較瑣碎。


後記

原本感受結束了,總體單方面被虐,沒想到TL說等一下,讓hr來找我聊聊,有點意外,等了大概10分鐘吧,hr小姐姐就過來進行人事面。


hr面

這個面試流程我就基本精煉一下:

  1. 詢問了公司經歷,就是爲何入職爲何離職
  2. 因爲我作技術比較雜,城市也比較多,聊了很久一陣子,多是怕我簡歷有水分吧
    我大學時期作ASP.Net,大學畢業第一份工做是C/C++嵌入式,後來又作了近一年的Django開發,最近兩年纔開始專注從事前端,因此這個聊的比較多,我以爲一我的能快速適應各類語言,算是一個優點吧,能側面反應計算機基礎,但另外一方面廣度過於寬會致使深度不夠,這個我開始逐漸調整,因爲掌握的語言比較多,因此上手不少技術仍是很快的。
  3. 詢問了我的發展規劃
    個人期許就是待趕上匹配的上時間成本,最重要的是想在一家規模比較大的企業作的久一些,沉澱一下業務能力和技術視野,大公司遇到的場景、併發、極端交互仍是很令我向往的。
  4. 聊了下期許的薪資
    我大概說了個數字,反正很誠心吧,有很大談的餘地,由於真的想跳出目前一直在小公司怪圈。
  5. 聊了整個面試流程感受如何
  6. 說了合適的話會打電話溝通,不合適的話會發郵件通知緣由

後記

hr面試讓我內心有些釋懷,一掃以前技術面的緊張感,出門的時候如釋重負吧,算是一個小階段的結束,爲了這個面試大概準備了1個多月,後來可能太緊張又是杭州梅雨季,回到家有些低燒,都是小插曲了。

最後的最後,等了大概一週多吧,仍是沒有消息,我對面試仍是特別有誠意的,想等到結果再進行下一步,就問了內推個人朋友,得知面試被淘汰了,沒接到正式婉拒通知有點小意外,可能各類緣由,當個經歷繼續前行吧。


準備

javascript基礎

看了yck大大總結的前端知識點小結,在掘金應該是有掘金小冊,有條件的話能夠購買,我平時看成javascript基礎的概括總結大綱查缺補漏,有好多點都有被問到。
yuchengkai.cn/docs/fronte…

還有一本書挺好的,《你不知道的javascript》一共分3冊,有些點描述的挺深入的,是個常讀常新的好書。

其餘就是多看多總結,每一個開發者都有個本身的小知識庫吧,我大多都是寫在雲筆記裏面了,最近打算整理一下不按期發佈出來。

css

這方面的話沒有過多的準備,基本都是平時移動端+PC端開發過程當中實際編碼的經驗,但有一些點不是太好鑽進去,在這裏簡單說下。

css動畫效果,這個徹底看本身平時的業務場景,也可能看一些源碼庫,推薦animate.css這個開源庫,很經典代碼結構也很清晰
github.com/daneden/ani…

關於webGL這方面的知識,這個真的隨緣,有過相關業務的話,面試過程應該不至於冷場想要突擊的話,不是太適合。

另外css3有本書也不錯,《css揭祕》,可能當字典看。特別基礎的css知識,推薦MDN或者一些寫的比較好的文檔了。

框架相關

看源碼,看開源社區,有不少優質的文章值得花費時間去閱讀。

這裏寫一個個人一個小技巧吧,由於以前寫後段比較多,並且調試的經驗也超級多,一直想能不能前端代碼調整也能那麼智能一些,還真被我找到了一個小技巧。

WebStrom對Karma單體測試支持特別好,能夠看到臨時變量以及代碼段步入,對框架源碼某處不懂,寫一個小的測試用例提升測試覆蓋率,就能很容易的理解源碼中晦澀難懂的一些代碼段了,上一張截圖,用了都說好。

// 首先定義一個xxx.spec.js
// [防爬蟲標識-掘金-沙海聽雨]
import Vue from 'vue'

describe('dom render', () => {
  it('render a easy template', () => {
    const el = document.createElement('div')
    el.setAttribute('id', 'app')
    el.innerHTML = '<span>{{message}}</span>'
    document.body.appendChild(el)
    const vm = new Vue({
      data: { message: 'Hello Vue!' },
      el: '#app',
      template: `<div id="app">{{ message }}</div>`
    })
  })
})
複製代碼

前端工程化

這方面總結的東西比較多,推薦從本身的簡歷經驗上多提煉一下,在掘金上看到一篇文章比較好,大型項目前端架構淺談能夠在裏面找到一些啓發,並從你的項目經歷中提煉出一些關鍵點。

總結

經歷了完整的大企業面試算是對本身的一個自我認知的過程,雖然中間經歷仍是比較曲折的,可是算是成長吧,今年逆形式找工做仍是有些吃力的,可是仍是期待大公司的工做機會吧。

若是你以爲本文對你有些許的幫助,或者能博您深思,別忘點個贊加個關注或是留下你的見解和看法。

同時期待能與您共事,歡迎並期待從新出發的機會,簡歷的話歡迎留下您的郵箱索取。

辛苦閱讀本文
以上
沙海聽雨(Wordsworth)

參考文章:
[1] InterviewMap-yck yuchengkai.cn/docs/fronte…
[2] HTTP強緩存和協商緩存-puhongru segmentfault.com/a/119000000…

相關文章
相關標籤/搜索