這是在拉鉤上面投的一家公司,早上九點左右收到面試邀請,註冊了一個網站,然後開始做題,前端的問題沒有細問,比較注重程式設計邏輯。下面放一下面試題
1.從事前端開發多久了(這個問題沒什麼好說的,根據自己實際情況答就可以了)
2.對原生js感覺如何
題目分析:實際上希望你回答出,在框架橫行的時代,原生js有哪些優缺點
回答如下:
優點: 效能高——由於JavaScript執行在客戶端,節省了web伺服器的請求時間和頻寬輕量級的指令碼語言,執行結果和處理相對比較快。
針對性強——程式碼完全由自己的業務決定,不會產生多餘的程式碼
缺點: 安全性差——由於JavaScript在客戶端執行,可能被黑客利用
相容性差、擴充套件能力低——在不同瀏覽器中的處理結果可能不同,程式碼抽象的層次較低。
當然並不是說原生開發怎麼怎麼不好,使用原生js可以鍛鍊基本功,對於博主這種前端小白來說再適合不過了。再說了萬物皆可原生( ̄_, ̄ )
3.git merge和git rebase的區別
這個是考git命令,沒什麼好說的,直接上答案,此外博主找到了一篇總結git知識點的文章,有興趣的可以看看(https://www.cnblogs.com/codingdevops/p/11447815.html)
回答如下:
git merge:將兩個分支,合併提交為一個新提交,並且新提交有2個parent。
git rebase:會取消分支中的每個提交,並把他們臨時存放,然後把當前分支更新到最新的origin分支,最後再把所有提交應用到分支上。
4.如何找到在特定提交中已更改的檔案列表
題目分析:一開始我以為是在問我實際開發場景中如何處理這個問題,後來一想好像不對,再一看好像也是git方面的知識點,因為博主在公司主要都是用SVN,git有所遺忘了,所以那瞬間很尬QAQ
回答如下:
方案1:git diff-tree -r {hash},給定提交雜湊值,這個命令將列出在該提交中更改或新增的所有檔案。-r 標誌會讓命令列出各個檔案,而不是僅將它們摺疊到根目錄名稱中。
方案2:輸出還將包含一些額外資訊,可以通過以下兩個標誌輕鬆去掉:git diff-tree -no-commit-id -name-only -r {hash},這裡 -no-commit-id 將禁止提交雜湊值出現在輸出中,而 -name-only 只會列印檔名而不是它們的路徑。
5.如何恢復已經推送並公開的提交的過程
題目分析:還是在考git的知識點,話不多說,上答案
回答如下:
方案1:在新提交中刪除或修復錯誤檔案,並將其推送到遠端儲存庫。這是修復錯誤最自然的方式。對檔案進行必要的更改後,將其提交到遠端儲存庫,使用命令:git commit -m“commit message”
方案2:建立一個新的提交,撤消在錯誤提交中所做的所有更改,使用命令:git revert
6.以下程式碼輸出什麼
for (var i = 0; i < 3; i++) { setTimeout(function() { alert(i); }, 1000 + i); }
題目分析:程式碼中是一個for迴圈裡面有一個setTimeout函式,每隔(1000+i)ms輸出i。首先要注意的是setTimeout是一個非同步函式,每隔(1000+i)ms往任務佇列裡新增一個任務,只有當主線上的任務全部執行完,才會執行。所以當for迴圈這個主線執行完成之後i的值是3,於是應該輸出的是3次3。
提問:如果這裡的var變成了let,結果又是什麼?
回答:for迴圈頭部的let不僅將i繫結到for迴圈塊中, 它也將其重新繫結到for迴圈體的每一次迭代中,確保上一次迭代結束的值重新被賦值。 setTimeout裡面的function()屬於一個新的域, 通過 var 定義的變數是無法傳入到這個函式執行域中的, 而通過使用 let 來宣告塊變數,這時候變數就能作用於這個塊, 所以 function就能使用 i 這個變數,所以結果是輸出0,1,2
7.以下程式碼輸出什麼
(function() { var a = b = 5; })();
console.log(a);
console.log(b);
題目分析:var a = b = 5;可以拆分為b=3;var a=b;原因是js是具有右結合性的,也就是從右邊往左邊賦值。拆分完成後,題目中的函式是一個立即執行函式,在函式中b被賦值為5,注意!b是一個全域性變數(下面會解釋)。然後a是立即執行函式裡面的變數,當函式執行完時a被釋放,在外部列印的時候就會報錯:a is undefined,而b會列印出5。
補充:為什麼b是全域性變數?因為在函式中使用var關鍵字進行顯式宣告的變數是做為區域性變數,在全域性範圍內宣告的變數為全域性變數;而沒有用var關鍵字,使用直接賦值方式宣告的是全域性變數(全域性物件屬性)。
還不懂的小夥伴可以看一下這個網址(https://www.jb51.net/article/155045.htm),解釋的很詳細
8.最近的較小值
讓函式NearestSmallerValues(arr)獲取儲存在arr中的整數陣列,併為列表中的每個元素搜尋所有先前值,以查詢小於當前元素的最近元素,並從這些數字建立一個新列表。如果在某個較小位置之前沒有元素,請輸入-1。
例如:如果arr為[ 5、2、8、3、9、12 ],則最接近的較小值列表為[-1,-1、2、2、3、9]。邏輯如下:對於5,沒有較小的先前值,因此到目前為止的列表為[-1]。對於2,也沒有較小的先前值,因此列表現在為[-1,-1]。對於8,最接近的較小值為2,因此列表現在為[-1,-1、2]。對於3,最近的較小值也是2,因此列表現在為[-1,-1、2、2]。這繼續產生上面的答案。您的程式應使用此最終列表,並以空格分隔的字串形式返回元素:-1 -1 2 2 3 9
例子:輸入:[5、3、1、9、7、3、4、1] 輸出:-1 -1 -1 -1 1 1 3 1
輸入:[2,4,5,1,7] 輸出:-1 2 4 -1 1
解題思路: 陣列中的第一個數前面肯定沒有比他小的數,所以第一個值直接給-1。然後從第二個數開始遍歷陣列,查詢小於當前元素的最近元素,則直接從前元素向前查詢,找到的第一個小於當前元素的就是符合要求的。
我的程式碼(如果有更好的解法請各位指教)
function NearestSmallerValues(arr) { var temp; //標誌變數,用於確認是否找到符合條件的元素 var list=[]; list.push(-1); for(var i=1;i<arr.length;i++){ for(var j=i-1;j>=0;j--){ //從當前元素向前查詢,一直找到陣列第一個元素 if(arr[j]<=arr[i]){ //找到小於當前元素的數字,就把數字新增進list,並且跳出當前迴圈 list.push(arr[j]) break; } if(j==0){temp= true} //判定j是否0,是則代表到陣列第一個元素也沒有找到,將標誌變數置為true } if(temp){ //如果沒找到就新增-1,並且把標誌變數置為false list.push(-1) temp =false } } str=list.join(' ') return str; }
9.分詞
讓函式WordSplit(strArr)讀取儲存在strArr中的字串陣列,該陣列將包含2個元素:第一個元素將是一個字元序列,第二個元素將是一個由逗號分隔的長字串,按字母順序排列,表示任意長度的字典。例如:strArr可以是:[“ hellocat”,“ apple,bat,cat,再見,hello,黃色,為什麼”]。您的目標是確定輸入中的第一個元素是否可以分為兩個詞,其中兩個詞都存在於第二個輸入中提供的字典中。在此示例中,第一個元素可以分為兩個詞:hello和cat因為這兩個詞都在字典中。您的程式應返回字典中存在的兩個單詞,並用逗號分隔。因此,對於上面的示例,您的程式應返回hello,cat。只有一種正確的方法將字元的第一個元素分成兩個單詞。如果無法將字串分成字典中存在的兩個單詞,則不可能返回該字串。第一個元素本身永遠不會在字典中作為真實單詞存在。
例子: 輸入:[“ baseball”,“ a,all,b,ball,bas,base,cat,code,d,e,quit,z”] 輸出:base,ball
輸入:[“ abcgefd”,“ a,ab,abc,abcg,b,c,dog,e,efd,zzzz”] 輸出:abcg,efd
這個題我用了一個很笨的辦法去做,然後失敗了(沒臉貼程式碼),暫時沒有比較好的解決辦法,後面想出來之後會貼到這裡,希望有思路的大神能指點一下
10.萬用字元
讓函式Wildcards(str)讀取str ,其中將包含兩個由空格分隔的字串。第一個字串將由以下字符集組成:+,*,$和{N},這是可選的。加號(+)表示單個字母字元,($)字元表示1-9之間的數字,星號(*)表示長度為3的相同字元的序列,除非後面跟{N}表示在序列中應該出現多少個字元,其中N至少應為1。您的目標是確定第二個字串是否與輸入中第一個字串的模式完全匹配。例如:if str是“ ++ * {5} jtggggg”,那麼在這種情況下,第二個字串與模式匹配,因此您的程式應返回字串true。如果第二個字串與模式不匹配,則程式應返回字串false。
例子: 輸入:“ +++++ * abcdehhhhhh” 輸出:false
輸入:“ $ ** + * {2} 9mmmrrrkbb” 輸出:true
(沒臉貼程式碼),求指點
11.反應電話簿
我們提供了一些簡單的React模板程式碼。您的目標是在頂部建立一個簡單的表單,該表單允許使用者輸入名字,姓氏和電話號碼,並且應該有一個提交按鈕。按下提交按鈕後,該資訊應與之前輸入的所有資訊一起顯示在下面的列表中(自動按姓氏排序)。這樣,應用程式可以用作簡單的電話簿。使用一些基本的CSS樣式在表中顯示所有資訊。
題目分析:考查react中父子元件通訊方式,因為我對react不是特別熟悉,所以選擇了子-父-子 props的方式,當然還有React Context、redux也可以實現,我就不舉例了
import React from 'react'; import ReactDOM from 'react-dom'; const style = { table: { borderCollapse: 'collapse' }, tableCell: { border: '1px solid gray', margin: 0, padding: '5px 10px', width: 'max-content', minWidth: '150px' }, form: { container: { padding: '20px', border: '1px solid #F0F8FF', borderRadius: '15px', width: 'max-content', marginBottom: '40px' }, inputs: { marginBottom: '5px' }, submitBtn: { marginTop: '10px', padding: '10px 15px', border:'none', backgroundColor: 'lightseagreen', fontSize: '14px', borderRadius: '5px' } } } function PhoneBookForm({ addEntryToPhoneBook }) { return ( <form onSubmit={e => { e.preventDefault() }} style={style.form.container}> <label>First name:</label> <br /> <input style={style.form.inputs} className='userFirstname' name='userFirstname' type='text' /> <br/> <label>Last name:</label> <br /> <input style={style.form.inputs} className='userLastname' name='userLastname' type='text' /> <br /> <label>Phone:</label> <br /> <input style={style.form.inputs} className='userPhone' name='userPhone' type='text' /> <br/> <input style={style.form.submitBtn} className='submitButton' type='submit' value='Add User' /> </form> ) } function InformationTable(props) { return ( <table style={style.table} className='informationTable'> <thead> <tr> <th style={style.tableCell}>First name</th> <th style={style.tableCell}>Last name</th> <th style={style.tableCell}>Phone</th> </tr> </thead> </table> ); } function Application(props) { return ( <section> <PhoneBookForm /> <InformationTable /> </section> ); } ReactDOM.render( <Application />, document.getElementById('root') );
12.總結
以上面試題暴露出的問題:演算法部分較為薄弱、關於react元件多種通訊方式不熟、git命令生疏。繼續加油叭!!