作为半路出家转前端开发零基础的我,在经历了几年工作后再次面试前端所获得的一些经验,我想在这给大家分享一下(也是写给多年后的自己),
面试之前的小故事
精心准备的我,不停刷面试题,整夜整夜的看着HTML/JS/CSS知识点,还有那些最新的、时髦的技术,看看到时候能不能唬住面试官;而有些人对自己胸有成竹,这么多年的前端经验了,啥项目没有经历过,不就一个面试,怕啥呢。
很快或者很慢的来到那天。我打扮的清清爽爽漂漂亮亮的,打扮的好会有加分不,没错,第一印象也是挺重要的。途中有些人可能会还一直想着面试官会问啥题目呢,那啥**属性是什么来着呢,再次拿出手机默默的看起资料;有些人可能就会想着公司不知道环境和福利不知道咋样,最好别碰到傻逼一样的面试官哎,不然这以后咋相处好呢。
来到公司,大小公司大家都见多了嘛,也是得看发展是吧,我也不是肤浅的人,见到前台妹妹,领进会议室里,让稍等一下,她去通知面试官,过了一会儿,不是面试官进来,而是前台妹妹给我送来一杯水。面试官踱步向前,咦~,我是继续坐着呢,还是站着呢,还是站起来显礼貌一些嗯。
给面试的一般会是Team Leader或者非常资深的工程师。首先会让你自我介绍下,然后巴拉巴拉介绍自己,途中或者聊到面试官喜欢的部分那就会中断问几个问题吧,介绍完自己,就进入正式的战斗了吧,一般会有2-3轮的回合。
普通型
面试中问题会比较的零碎,html/js/css肯定都会有涉及。知识点不会有太大的规律,可能几个公司面试下来你遇到的问题一个都不带重复的。哎,前端的知识点就是乍一看深似海,仔细一看深似黑洞啊。问题好的话,一方面考察了面试人对前端接触的广度,深度的话也可以从中接触到一些。因为面试的时间有限,其实也非常考验面试官对一个人的洞察能力。
进阶型
除了基本的问题,面试中会有一些明显设计过的题目。针对某几个知识点,或让你手写代码,或让你提供算法或思路。如果之前没有遇到过这类问题的话其实一下子真的挺难回答,或者直接懵逼了,或者回答不出面试官满意的答案。这其实对工程师的要求也是比较的高,不能只是单纯的切切页面,用用插件,需要对某一类问题或者模式或者算法有深入的了解,对问题的解决思路有很好的把握。
算法可能不是前端工程师的长项,但作为优秀的工程师,对算法的了解应该会只深不浅。
依稀记得的面试题
1、实现一个左右两栏的布局,左边宽度固定为220px,右边宽带为自使用,使用三种以上的方式来实现。
2、设计一个dialog组件,列出设计思路。
3、设计一个页面全局的进度条,谈谈你的思路。
4、在浏览器里输入一个url,一直到页面呈现出来,这之间都发生了一些什么事?
5、实现浏览器的缓存有哪些方式?
6、js的闭包和模块化有什么关系?模块化如何管理? 它的优势是什么?
7、webpack的工作原理?
8、你熟悉的一种流行web框架是什么?他的有什么特点以及工作原理?
9、前端都有哪些攻击方式以及如何防范?
10、js构造函数的原型和原型链之间有什么区别?
11、es6的新语法有哪些?并说出他们的作用。
12、如何实现前后端分离?
13、node.js的多进程之间如何通信?底层是基于什么来实现数据传递?
14、使用nodejs如何做mysql的查询处理?
15、 gulp webpack的区别以及原理?
16、diff算法原理?
17、v8引擎?
18、写一段同步休眠的代码?
19、git flow的工作原理?
20、作者写h5的思想是什么?
21、node.js与浏览器环境javascript有那些区别
22、node.js作为web服务中间层可以做那些事情
23、redux原理
24、对作用域 原型的了解
Babel是如何读懂JS代码的
Babel的功能:以字符串的形式将源代码传给编译器,编译器就会返回一段新的代码字符串,输入语言是ES6+,编译目标语言是ES5。
分为三个阶段:
1、解析:将代码字符串解析成抽象语法树
2、变换:对抽象语法树进行变换操作
3、再建:根据变换后的抽象语法树再生成代码字符串
webpack承担了哪些工作?原理?功能?
1、依赖管理:方便引用第三方模块、让模块更容易复用、避免全局注入导致的冲突、避免重复加载或加载不需要的模块。
2、合并代码:把各个分散的模块集中打包成大文件,减少HTTP的请求链接数,配合UglifyJS可以减少、优化代码的体积。
3、各路插件:babel把ES6+转译成ES5-,eslint可以检查编译期的错误……
原理:最简单地说,就是分析代码,找到require、exports、define等“关键词”,并替换成对应模块的“引用”……
webpack主要就是模块化、处理依赖 和 打包-
举例来说。。我有个index.html
上面要引用一大堆JS/CSS文件,main.css、other.css、entry.js、a.js、b.js、c.js…
|
|
webpack与gulp
webpack是一个打包工具
gulp是构建工具
MVC
- View 传送指令到 Controller
- Controller 完成业务逻辑后,要求 Model 改变状态
- Model 将新的数据发送到 View,用户得到反馈
MVVM (model - View - ViewModle)分离视图和模型
- ViewModel,注意这里的“Model”指的是View的Model,跟上面那个Model不是一回事。所谓View的Model就是包含View的一些数据属性和操作的这么一个东东,这种模式的关键技术就是数据绑定(data binding),View的变化会直接影响ViewModel,ViewModel的变化或者内容也会直接体现在View上。这种模式实际上是框架替应用开发者做了一些工作,开发者只需要较少的代码就能实现比较复杂的交互。
布局less
|
|
SASS
|
|
安全问题
|
|
es6 新特性
箭头操作符
类的支持
|
|
字符串模板
|
|
解构
|
|
let与const 关键字
|
|
Promises
Promises是处理异步操作的一种模式,之前在很多三方库中有实现,比如jQuery的deferred 对象。当你发起一个异步请求,并绑定了.when(), .done()等事件处理程序时,其实就是在应用promise模式。
1、js的数据类型?
基本数据类型:String、boolean、Number、undefined、null
引用数据类型:Object、Array、Date、RegExp、Function
拓展:如何判断数组数据类型?
1、通过专有方法判断如:push(),pop(); //可自己给变量定义该方法,有时失效
2、obj instanceof Array 返回值判断;
3、es5和jquery都有方法Array.isArray()。
4、toString.call(param) 判断;返回格式 [object Undefined]
5、obj.constructor === Function 返回值判断
2、获取所有的checkbox?
|
|
//(for效率更高)在测试五百多个不同input中,while:for = 3~2ms:1~0ms,显然for效率更高
3、数组:
|
|
4、随机取10个10-100数?
|
|
5、闭包的使用?闭包可以简单理解成“定义在一个函数内部的函数“。
|
|
//也可以设置私有属性;
6、双等号的类型转换?
|
|
分析:undefined与null 但不全等(===)
当为number与string时,会将string转换为number;
number和boolean时,会将boolean转换为number
number或string与Object,会将Object转换成number或string
(附:js中的数据类型转换?)
函数转换:parseInt()、parseFloat()、toString()
强类型转换:Boolean()、Number()、String()
弱类型转换:“==”、“-”、“+”、if()
(拓展:for循环中的效率问题?)
第三种效率更高!
在大数据下:
第三种方式比第一种执行速度快3~4倍;
至于第三种比第三种快100多倍开外(详细数据:http://www.111cn.net/wy/js-ajax/39368.htm)
前端开发中会遇到哪些问题需要考虑
|
|
在浏览器中输入域名 按下回车键后会发生哪些事情?
步骤1:需要查找域名的IP地址,DNS查找过程:
(1)浏览器缓存 – 浏览器的缓存DNS记录一段时间。
(2)系统缓存 – 如果在浏览器缓存里没有找到需要的记录,浏览器会做一个系统调用(windows里是gethostbyname)这样便可获得系统缓存中的记录。
(3)路由器缓存 – 接着,前面的查询请求发向路由器,它一般会有自己的DNS缓存。
(4)ISP DNS 缓存 – 接下来要check的就是ISP缓存DNS的服务器。在这一般都能找到相应的缓存记录。
(5)递归搜索 – 你的ISP的DNS服务器从跟域名服务器开始进行递归搜索,从.com顶级域名服务器到Facebook的域名服务器。一般DNS服务器的缓存中会有.com域名服务器中的域名,所以到顶级服务器的匹配过程不是那么必要了。
步骤2:浏览器给web服务器发送一个HTTP请求。请求中也包含浏览器存储的该域名的cookies。可能你已经知道,在不同页面请求当中,cookies是与跟踪一个网站状态相匹配的键值。这样cookies会存储登录用户名,服务器分配的密码和一些用户设置等。Cookies会以文本文档形式存储在客户机里,每次请求时发送给服务器。
步骤3:服务的永久重定向响应
步骤4:浏览器跟踪重定向地址
步骤5:服务器“处理”请求
步骤6:服务器发回一个HTML响应
步骤7:浏览器开始显示HTML
步骤8:浏览器发送获取嵌入在HTML中的对象
|
|
|
|
chunkhash 是文件的 hash 码,这里只使用前五位。
添加首页
|
|
按需加载之后,我们需要让路由动态加载组件,需要将 component 换成 getComponent。首先将路由拆出来(因为路由庞大之后全部写在一起会很难看),创建一个根路由 rootRoute:
history 不变,在 Router 中添加 routes 属性,将创建的路由传递进去。
这里有四个属性:
1. path
将匹配的路由,也就是以前的 path。
2. getComponent
对应于以前的 component 属性,但是这个方法是异步的,也就是当路由匹配时,才会调用这个方法。
这里面有个 require.ensure 方法
这是 webpack 提供的方法,这也是按需加载的核心方法。第一个参数是依赖,第二个是回调函数,第三个就是上面提到的 chunkName,用来指定这个 chunk file 的 name。
3.indexRoute
用来设置主页,对应于以前的
4.childRoutes
这里面放置的就是子路由的配置,对应于以前的子路由们。我们将以前的 /baidu、/404 和 * 都拆了出来,接下来将分别为他们创建路由配置。
路由控制 上面的childRoutes 里面,我们 require 了三个子路由,在目录下创建 routes 目录,将这三个路由放置进去。
|
|
和 rootRoute 类似,里面的每个 index.js 都是一个路由对象:
/404/index.js
|
|
/baidu/index.js
|
|
bind()–也是改变函数体内this的指向;
bind会创建一个新函数,当调用这个函数的时候,绑定函数会以创建它时传入bind()方法的第一个参数作为this,传入bind()方法的第二个及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数
bind与apply、call最大的区别就是:bind不会立即调用,其他两个会立即调用
都是用来改变函数的this对象的指向的;
第一个参数都是this要指向的对象;
都可以利用后续参数传参;
bind是返回对应函数,便于稍后调用,apply、call是立即调用;
JavaScript模块化:使用requireJS按需加载
通过模块加载器可以有效的解决这些问题:
JS文件的依赖关系。
通过异步加载优化script标签引起的阻塞问题
可以简单的以文件为单位将功能模块化并实现复用