这是在拉钩上面投的一家公司, 早上九点左右收到面试邀请, 注册了一个网站, 然后开始做题, 前端的问题没有细问, 比较注重编程逻辑. 下面放一下面试题
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 命令生疏. 继续加油叭!!
来源: https://www.cnblogs.com/spoem/p/12815212.html