最近这段时间面试了几次,其实很多都问的不是很深,根据记忆,总结了下其中一些之前没涉及或了解不深的有记录价值的东西。
1. Jquery
$().on(‘click’)和$.click()的区别
其实这个是知道的,不过了解不是特别深,换个问法就有点懵了
之前的问题是jquery里点击事件什么情况下会失效---就是这种情况,如果是动态添加的元素,用$().click(fn)这种就会失效,需要用$().on(‘click’),并且前面的元素需要是页面已经存在的元素才行
$().click(fn)是只针对页面已经存在的选择器
$().on(‘click’)用于对动态添加的元素绑定点击事件
2.js深拷贝和浅拷贝的区别以及如何实现深拷贝
了解这个首先要了解js值类型(基本类型)和引用类型的区别,可参见:https://www.cnblogs.com/leiting/p/8081413.html
由于引用类型复制之后,浅拷贝--复制之后他们指向同一个地址,更改任何一个,都会影响到另外一个
var a={s:1} var b=a b.s=2 console.log(a===b) // true
而深拷贝是复制对象的所有属性,改变之后,不会影响到被复制的对象
有种简单方法可以实现对象的深拷贝JSON.stringify()和JSON.parse()
var a={s:1} var b=JSON.parse(JSON.stringify(a)) b.s=2 console.log(a===b) // false
这种方法虽然简便,但有它的局限性。
1、如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;
2、如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象;
3、如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
5、JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
6、如果对象中存在循环引用的情况也无法正确实现深拷贝;
参考:https://www.jianshu.com/p/b084dfaad501
当然还可以利用遍历递归实现深拷贝(封装一个递归函数)
function deepCopy(obj){ var a = obj instanceof Array?[]:{} // 判断传入的参数是数组还是对象 for(var key in obj){ if(obj.hasOwnProperty(key)){ // 判断是不是自身属性 if(obj[key]&&typeof obj[key]==='object'){ // 判断是不是引用类型,如果是引用类型递归复制所有属性 a[key]=deepCopy(obj[key]); }else{ a[key]=obj[key]; } } }
return a; } var a={s:1} var b=deepCopy(a) b.s=2 console.log(a===b) // false
3. Vue
Vuex 简单用法
用法:state存储全局变量
getters获取state数据的方法
actions 提供后台接口交互的方法(dispatch触发actions方法)
mutations 提供存储state数据的方法(commit触发mutations方法)
多人维护store要怎么做?
可以进行模块拆分modules
Vuex自己去实现状态管理(实现原理)?
可以new一个实例,然后挂载到vue根实例下
参见:https://www.jb51.net/article/134842.htm
Vue和React的区别(原理):https://github.com/lihongxun945/myblog/issues/21
什么是虚拟dom?和真实dom相比有什么好处?
虚拟dom是对真实dom的模拟,构建一颗虚拟树,将数据操作应用到虚拟树上,然后再将对虚拟的树的修改应用到真实的DOM结构上。
应用虚拟dom的好处:(1)减少对dom的操作,减少重绘重排,提升性能;
(2)使用虚拟dom,可以节省内存;
(3)虚拟dom不依赖浏览器环境,可以在node环境实现,可以使用虚拟dom生成html字符串,实现ssr(服务端渲染)
4. Webpack 打包拆包,压缩
(1)去掉不必要的插件
(2)提取第三方库
{ entry: { bundle: 'app' vendor: ['react'] } plugins: { new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js') } }
(3)引用外部文件的方式引入第三方库
{ externals: { 'react': 'React' } }
(4)代码压缩--webpack自带插件 UglifyJsPlugin,只需要在配置文件中引入即可
{ plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ] }
(5)代码分割:Code Splitting
其实就是个按需加载的过程。code splitting
就是将文件分割成块(chunk)
, 我们可以定义一些分割点(split point)
, 根据这些分割点对文件进行分块, 并实现按需加载。Webpack支持定义分割点, 通过require.ensure
进行按需加载。
上面那个第三方类库单独打包的就是code splitting...
一般加载一个网页都会把全部的 js 代码都加载下来,这样一来SPA页面的首屏加载就会相对来说比较慢,而且SPA还有个问题就是不利于SEO。
代码分割实现按需加载,减少首次加载时间。
SEO优化的话,还可以用服务器端渲染(ssr),服务端渲染可以用node来做个中间层,客户端就写样式和事件,node中间层负责渲染多个页面路由,后端只负责提供接口
5. Jsbridge实现原理 webview底层
初始化一个iframe实现webview的跳转
6. Css 布局写法,左固定右自适应,清浮动
虽然经常写,但记忆不够精确,特别是对于具体的写法和很多属性,
由于都是利用伪类来写的,所以清浮动这个和移动端1px解决方案记混了
清浮动:
.clearfix{zoom:1}//兼容ie,触发haslayout .clearfix:after{content:’’;display:block;clear:both;}
移动端底部1px边框
.border1px {position: relative;} .border1px:after{content:””;position:absolute;left:0;bottom:0;width:100%;height:1px;background:#d8d8d8;transform:scaleY(0.5);-webkit-transform: scaleY(0.5);}
7. Nodejs运行挂掉怎么办
了解过node.js的一些基本写法和用法,知道try catch,其他了解就不是特别深了
这个问题主要也是想说程序的容错性,健壮性,不能一直去重启服务,在服务挂掉之后就一定要有提示,要有日志记录,以便查找原因,快速定位问题,解决问题,在写程序的时候一定要考虑多种情况,并对这些可能出现的情况进行处理,这样才会是好的代码。
(1)使用uncaughtException捕获error
(2)Try catch保证线程的安全
(3)为nodejs应用添加守护进程,让NodeJS遭遇异常崩溃以后能马上复活。 另外,还应该把这些产生的异常记录到日志中,并让异常永远不再发生。
8. 我封装过的一些组件有哪些
日期选择、城市选择、组织架构树、表格树、列表筛选、头部导航条、菜单栏、提示弹层、确认弹层、上拉加载下拉刷新、图表绘制、上传图片、下拉选择等等,其实根据业务需求去封装复用组件并不是很难的一件事,但就实践经验来看,要怎么样去封装一个可用性强,复用性高的优质组件,考虑到尽可能多的可能性的同时又不让组件用起来太麻烦,这还是需要思考和精进的一件事。
9. Cookie有失效时间的设置,但localStorage没有,只能手动清缓存才能清掉,sessionStorage是关掉窗口就会清掉
10. 小程序渲染一段html
目前因为没有实践过太多小程序相关的项目,也都是根据官方文档去写程序,写并不复杂的业务代码,所以对这块的研究不是很深
难点,关键点:小程序的标签是<view></view>和html的标签不同
wxParse库,把HTML代码解析成树结构的数据,再通过小程序的模板把该数据渲染出来
小程序刚上线那会儿,是无法直接渲染HTML内容的,于是就诞生了一个叫做「 wxParse 」的库。它的原理就是把HTML代码解析成树结构的数据,再通过小程序的模板把该数据渲染出来。
后来,小程序增加了「rich-text」组件用于展示富文本内容。然而,这个组件存在一个极大的限制: 组件内屏蔽了所有节点的事件 。也就是说,在该组件内,连「预览图片」这样一个简单的功能都无法实现。
再后来,小程序允许通过「web-view」组件嵌套网页,通过网页展示HTML内容是兼容性最好的解决方案了。然而,因为要多加载一个页面,性能是较差的。
11. for in 和for of遍历的区别
简单来说,for in 是用来遍历键名key,for of 是用来遍历键值value
var arr = ['aa','bb'] var obj = {a:'cc',b:'dd'} for(key in arr){console.log(key)} // 0,1 for(key in obj){console.log(key)} // a,b for(value of arr){console.log(value)} // aa,bb for(value of obj){console.log(value)} // 报错:obj is not iterable 对象不可用for of迭代
这些是最近遇到的一些了解不够深入或是知道但记不住技术细节的一些问题,觉得有记录价值记录下来,很多工作一两年的前端可能也大都是用框架还算熟练,而对其中的一些底层实现不熟悉。多了解一些底层的东西,打好基础,喜欢技术,就是因为技术没有什么捷径,积累和内化知识才是从菜鸟通往大牛的必经之路。接下来,主要任务是提高技术精度,建立知识体系~