讓渡居涼經
這是在拉鉤上面投的一家公司,早上九點左右收到面試邀請,註冊了一個網站,然後開始做題,前端的問題沒有細問,比較注重編程邏輯。下面放一下面試題
1.從事前端開發多久了(這個問題沒什麼好說的,根據自己實際情況答就可以了)
2.對原生js感覺如何
題目分析:實際上希望你回答出,在框架橫行的時代,原生js有哪些優缺點
回答如下:
優點: 性能高——由於JavaScript運行在客戶端,節省了web服務器的請求時間和帶寬輕量級的腳本語言,運行結果和處理相對比較快。
針對性強——代碼完全由自己的業務決定,不會產生多餘的代碼
缺點: 安全性差——由於JavaScript在客戶端運行,可能被黑客利用
兼容性差、擴展能力低——在不同瀏覽器中的處理結果可能不同,代碼抽象的層次較低。
當然並不是說原生開發怎麼怎麼不好,使用原生js可以鍛煉基本功,對於博主這種前端小白來說再適合不過了。再說了萬物皆可原生( ̄_, ̄ )
3.git merge和git rebase的區別
這個是考git命令,沒什麼好說的,直接上答案,此外博主找到了一篇總結git知識點的文章,有興趣的可以看看(//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關鍵字,使用直接賦值方式聲明的是全局變量(全局對象屬性)。
還不懂的小夥伴可以看一下這個網址(//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命令生疏。繼續加油叭!!