key的作用
-
v-if
通过使用 key 来唯一的标识一个元素,这个情况下,使用 key 的元素不会被复用。这个时候 key 的作用是用来标识一个独立的元素。
-
v-for
通过为每个列表项提供一个 key 值 ,以便Vue跟踪元素的身份,从而高效的更新渲染虚拟DOM
为什么不建议用index作为key的值
如果使用index,不管数组怎么变化下标都是0,1,2,导致vue会复用错误的旧子节点
插槽的作用
slot作用主要是可以实现内容分发,组件标签内嵌套内容,可通过来定义占位的内容
分为具名的slot和匿名的slot和作用域插槽
组件通信的方式
第一种:父传子:主要通过props来实现的
具体实现:父组件通过import引入子组件,并注册,在子组件标签上添加要传递的属性,子组件通过props接收,接收有两种形式一是通过数组形式[‘要接收的属性’ ],二是通过对象形式{ }来接收,对象形式可以设置要传递的数据类型和默认值,而数组只是简单的接收
第二种:子传父:主要通过$emit来实现
具体实现:子组件通过通过绑定事件触发函数,在其中设置this.emit中有两个参数一是要派发的自定义事件,第二个参数是要传递的值
然后父组件中,在这个子组件身上@派发的自定义事件,绑定事件触发的methods中的方法接受的默认值,就是传递过来的参数
第三种:兄弟之间传值有两种方法:
方法一:通过event bus实现
具体实现:创建一个空的vue并暴露出去,这个作为公共的bus,即当作两个组件的桥梁,在两个兄弟组件中分别引入刚才创建的bus,在组件A中通过bus.on(‘自定义事件名‘,function(v) { //v即为要接收的值 })接收数据
方法二:通过vuex实现
具体实现:vuex是一个状态管理工具,主要解决大中型复杂项目的数据共享问题,主要包括state,actions,mutations,getters和modules 5个要素,主要流程:组件通过dispatch到 actions,actions是异步操作,再actions中通过commit到mutations,mutations再通过逻辑操作改变state,从而同步到组件,更新其数据状态
路由的传参方式:
直接通过$router.push路径中携带参数 路由配置路径中需要预留参数位置 可以通过设置路由中的 "props:true" 让子组件通过props获取参数
<div class="examine" @click="insurance(2)">查看详情</div>
methods:{
insurance(id) {
//直接调用$router.push 实现携带参数的跳转
this.$router.push({
path: `/particulars/${id}`,
})
}
// 路由配置
{
path: '/particulars/:id',
name: 'particulars',
component: particulars
}
query传参 通过path来引入 query对象携带参数 传递的参数会显示在url后面 通过this.$route.query获取参数
methods:{
insurance(id) {
this.$router.push({
path: '/particulars',
query: {
id: id
}
})
}
// 路由
{
path: '/particulars',
name: 'particulars',
component: particulars
}
params传参 通过name引入 params对象携带参数 通过this.$route.params 获取参数
methods:{
insurance(id) {
this.$router.push({
name: 'particulars',
params: {
id: id
}
})
}
// 路由配置
{
path: '/particulars',
name: 'particulars',
component: particulars
}
什么是 mixin
提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能
相当于扩展了父组件的对象与方法,可以理解为形成了一个新的组件
可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的,值的修改在组件中不会相互影响
对SSR的理解:
SSR就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html页面返回给客户端
优点:
更好的SEO
首屏加载速度更快
缺点:
开发条件会受到限制
更多的服务端负载
服务端渲染(SSR)和预渲染(Prerendering)有什么区别
服务端渲染:
- 服务端渲染是指将客户端渲染的过程放到了服务端
- 服务端渲染过程: 解析执行JS => 构建HTML页面 => 输出给浏览器
预渲染:
- 直接输出HTML页面给浏览器 比服务端渲染少了解析js的步骤
Vue的性能优化
-
编码阶段
减少data中的数据,data中的数据都会增加getter和setter
v-if v-for不能连用
如果需要使用v-for给每项元素绑定事件时使用事件代理
SPA 页面采用keep-alive缓存组件
在更多的情况下,使用v-show替代v-if
key保证唯一
使用路由懒加载、异步组件
长列表滚动到可视区域动态加载
防抖、节流
第三方模块按需导入
图片懒加载
-
SEO优化
预渲染
服务端渲染SSR
-
打包优化
压缩代码
使用cdn加载第三方模块
多线程打包happypack
-
用户体验
PWA渐进式网页应用
在内容还没有出现之前的页面使用骨架屏填充,以免留白
防抖节流的区别
-
防抖
在事件触发n秒之后执行回调,如果在n秒内再次触发事件则重新计时
运用场景:输入框输入时
-
节流
在单位时间内多次触发只执行一次
运用场景:鼠标多次点击时
vue初始化页面闪动问题
在css上添加[v-cloak] { display: none;}
methods、watch、computed的区别:
methods: 适合用于业务逻辑处理, 数据不能缓存, 每次使用都会重新调用
watch: 当想要执行异步或者昂贵的操作以响应不断的变化时使用watch, 支持异步监听, 也可以监听路由变化, 不支持缓存, 数据变化时, 就会触发相应的操作
使用场景:当一条数据的更改影响到多条数据的时候---------搜索框
computed: 适合计算属性, 不支持异步, 可以缓存数据, 只有在相关依赖发生变化时才会重新求值
使用场景:当一个值受多个属性影响的时候------------购物车商品结算
如何实现路由懒加载:
- 使用箭头函数 + import动态加载
const List = () => import('@/components/list.vue')
const router = new VueRouter({
routes: [
{ path: '/list', component: List }
]
})
- 使用箭头函数 + require动态加载
const router = new Router({
routes: [
{
path: '/list',
component: resolve => require(['@/components/list'], resolve)
}
]
})
- 使用webpack的require.ensure技术
route的区别
$route是”信息路由对象”,包含path、params、query、name等路由信息参数
$router是”路由实例”对象包括了路由的跳转方法、钩子函数等
hash和history的区别
-
hash
hash模式是开发中默认的模式,它的URL带着一个#
hash值会出现在URL里面,但是不会出现在HTTP请求中,对后端完全没有影响
-
history
使用的是传统的路由分发模式
history模式需要后台配置支持
说一下vue路由或前端路由实现原理
答:前端路由实现原理主要通过以下两种技术实现的
第一种:利用H5的history API实现
主要通过history.pushState 和 history.replaceState来实现,不同之处在于,pushState会增加一条新的历史记录,而replaceState则会替换当前的历史记录[发布项目时,需要配置下apache]
第二种:利用url的hash实现
我们经常在 url 中看到 #,这个 # 有两种情况,一个是我们所谓的锚点,路由里的 # 不叫锚点,我们称之为 hash,我们说的就是hash,主要利用监听哈希值的变化来触发事件 —— hashchange 事件来做页面局部更新
总结:hash 方案兼容性好,而H5的history主要针对高级浏览器。
什么是路由导航守卫
路由守卫分为 全局的、 单个路由独享的 、组件级的
主要用来通过跳转或取消的方式守卫导航
- 全局前置/钩子:beforeEach、beforeResolve、afterEach
- 路由独享的守卫:beforeEnter
- 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
权限路由的实现
在定义路由规则时,在路由上标记响应的权限信息,当要跳转路由时,判断用户是否有权限访问,没有权限则跳到事先定义好的界面
两种方法:
-
通过router.beforeEach() 路由拦截的方式实现
-
通过vue-router 官方提供的addRoutes()来进行动态路由注入
只需要配置静态的路由表,登录、注册页,登录成功后根据后台返回的权限动态注入路由
嵌套路由
app:
<div id="app">
<router-view></router-view>
</div>
home组件中又提供了用来嵌套其他组件:
const Home = {
template: `
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view></router-view>
</div>
`
}
要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children 配置:
const router = new VueRouter({
routes: [
{
path: '/home/:id',
component: Home,
children: [
{
// 当 /home/:id/profile 匹配成功,
// UserProfile 会被渲染在 home 的 <router-view> 中
path: '/user',
component: User
},
{
// 当 /home/:id/posts 匹配成功
// UserPosts 会被渲染在 home 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]
})
按钮权限控制
当前组件路由携带可使用的按钮权限,存入数组中,通过v-if来判断是否显示
登录时,单独获取整个系统的按钮权限,将获取到的所有按钮 存入一个数组中,放入全局中,然后,通过 v-if 来判断是否显示
vue自定义指令实现权限按钮功能
登录验证:用户登录--> 验证成功--> 服务器返回token--> 将token存储至本地--> 前端根据token调用后端接口获取(用户权限,用户信息)
权限验证:通过token获取对应的role--> 使用自定义指令判断role是否在路由meta属性里btnPermissions数组里面--> 不在就删除该按钮DOM
如何保存页面当前状态
在组件即将销毁的声命周期中,将当前组件的状态存储在LocalStorage/SessionStorage中
单页面渲染 要切换的组件作为子组件全屏渲染,父组件中正常储存页面状态
用keep-alive缓存组件
什么是keep-alive
keep-alive用来缓存组件,避免多次加载相应的组件,减少性能消耗
如果需要在组件切换的时候,保存一些组件的状态防止多次渲染,可以用keep-alive组件包裹需要保存的组件
当组件在 < keep-alive > 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。而不会执行created和mounted的钩子函数。 所以要将需要更新的数据写在activated 的钩子函数里
$nextTick原理
本质是对JavaScript执行原理EventLoop的应用
nextTick的核心是利用了Promise、MutationObserver、setImmediate、setTimeout的原生js方法来模拟微/宏任务的实现
keep-alive 只对第一个组件有效
$nextTick()方法的作用:当页面上的元素被重新渲染后,才会执行回调函数中的代码。
什么情况使用nextTick
在数据变化后执行的某个操作,需要使用随数据变化而变化的DOM结构时,就需要将这个操作放在nextTick的回调函数中
在creatd()钩子进行DOM操作,一定要放在nextTick()回调函数中
Vue data中某一个属性值发生变化后,视图会立即同步执行重新渲染吗?
不会立即同步执行重新渲染
Vue更新DOM时是异步执行的,只要侦听到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更
如果watcher被多次触发,只会被推入队列一次,在下一个事件循环tick中,Vue刷新队列并执行已去重的工作
Vue SPA与MPA的区别
-
概念
SPA单页面应用,只有一个主页面的应用,只需要加载一次js、css等相关资源,所有内容都在主页面,单页面应用跳转,就是切换相关组件,仅刷新局部资源, 相对服务器压力小 , 前后端职责分离,架构清晰
MPA多页面应用,拥有多个独立页面的应用,每个页面需要重复加载js、css相关资源,多页面应用跳转,需要刷新整页资源
-
区别
SPA只有一个主页面和许多模块的组件 MPA有多个完整页面
SPA页面切换快 MPA页面切换慢
SPA只需加载一次公用资源 MPA每个页面都需加载自己的公用资源
SPA不利于SEO(搜索引擎优化) MPA适用于SEO要求较高的应用
Vue在哪个生命周期执行异步操作
可以在created和beforeMount、mounted中执行 ,因为data此时已经创建,可以将服务端返回的数据进行赋值
但是推荐在created中执行异步操作,获取数据快,用户体验好,服务器渲染不支持beforeMount、mounted
什么时候需要使用beforeDestory
此时DOM还没有销毁
1、当前页面使用了$on方法,需要在组件解绑前销毁
2、清除自己定义的定时器
3、解除事件的绑定
什么时候使用destoryed
移除监听事件
移除对dom的操作
销毁VueX中存储的数据,否则页面不刷新,在页面刚渲染时,一直展示的是上次的数据
如何解决vue首屏加载慢或白屏?
1.路由懒加载
2.开启Gzip压缩
3.使用webpack的externals属性把不需要打包的库文件分离出去,减少打包后文件的大小
- 使用vue的服务端渲染(SSR)
什么是Vuex
vuex是一种全局状态管理模式 每个vuex都有一个核心store(仓库) vuex的状态存储是响应式的
vuex的五大核心
state: 存储数据,存储状态
getter: 可以认为是store的计算属性,它的返回值会根据它的依赖缓存起来
mutation: 提交更改数据的方法 只能进行同步操作
action: 像一个装饰器 包裹mutations 使之可以异步
module: 模块化Vuex
mutation和action的区别
mutation中的操作是一系列同步函数,用于修改state中的变量的状态
action中可以包含任意异步操作 action提交的是mutation,而不是直接修改状态
vuex和localStorage的区别
vuex:
- 存储在内存当中 页面刷新就存储的值消失
- 用于组件传值
- vuex存储值是响应式的
localStorage:
- 存储在本地,永久保存
- 用于页面之间传值
loacalStorage和sessionStorage的区别
localStorage存储的值是永久的
sessionStorage存储的值在当前窗口关闭后就会消失
相同浏览器的不同页面间可以共享相同的 localStorage
不同页面或标签页间无法共享sessionStorage的信息
Vue3.0的更新
消除了Vue2中Object.defineProperty的很多限制
带来了基于代理Proxy的observer实现
检测属性的添加和删除
支持Map、Set、WeakMap 和 WeakSet
3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易
3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能
有哪些常见的Loader?他们是解决什么问题的?
file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
uni-app的bug
无法覆盖uni-app提供的组件的样式 直接重写不会生效
ios真机下键盘遮挡住弹框底部部分内容
取消了顶部导航栏,出现页面和手机基本信息(信号,时间等)重合
input框被输入键盘覆盖 自身有一个属性设置键盘到输入框的距离
- 使用vue-cli创建的uni-app的静态资源必须存放在static文件夹下
- vue父子组件数据单向流的原则
- 使用静态资源图片名称不允许包含中文
- uniapp使用v-show在微信小程序端不能使用list.length没有效果
- 微信小程序pages.json里面的tabbar两个状态的文件一定要文件存在,否者小程序端会编译失败
- 组件内引入图片要使用绝对路径
- 用tap事件代替click事件
项目中遇到的难点
1、mounted钩子函数中请求数据导致页面闪屏问题
解决:其实就是加载时机问题,放在created里会比mounted触发早一点,如果在页面挂载完之前请求完成的话就不会看到闪屏了
2、IE9中template标签使用问题
解决:之前在tr标签里面用template标签包裹td标签,出现了比较严重的UI错乱,所以。。IE9不能在tr标签中使用template标签
3、el-table用v-if隐藏显示列和预期不符问题
解决:给el-table-column加一个key属性,:key="Math.random()"或者其他的,确保每列的key值不同就可以了
4、在使用el-table的时候有的时候需要对表格中的数据做处理,需要用到filter,虽然官方也有提供过滤的方法(filter-method),但是还是用自定义列,然后用filter复用性好一些
5、在element中使用el-input实现点击显示输入框,失去焦点时生成新的tag标签,出现两行数据下的输入框会同时修改的bug,因此要为他们单独设置自己的false和输入框的值
工作中最容易碰到的问题:
1.适配问题
rem flex 响应式
2.ie9下v-for 在option渲染数据,字符不显示的问题
通过虚拟DOm 从新编写select的样式
项目中遇到的问题:
3.ios 键盘遮挡问题
scrollIntoView(alignWithTop): 滚动浏览器窗口或容器元素,以便在当前视窗的可见范围看见当前元素
alignWithTop = true 或 空 窗口滚动之后会让调用元素的顶部与视口顶部尽可能平齐 (元素向上滚动)
alignWithTop = false 调用元素会尽可能全部出现在视口中,可能的话,调用元素的底部会与视口顶部平齐,不过顶部不一定平齐。(元素不会滚动)
常见浏览器:IE、Chrome、Firefox、Safari和Opera。 都支持
let _this = this
setTimeOut(function(){ //每100毫秒 滚动1次
_this.scrollIntoView(true)
},100)
面试的时候 要说一下
当input 得到焦点的时候 出发方法,方法作用 从新计算 元素到顶部的距离,元素向上移动的距离=软键盘的高度
ios手机型号太多,滚动数值需要多次获取
webpack常用的loader
样式:style-loader、css-loader、less-loader、sass-loader等
文件:raw-loader、file-loader 、url-loader等
编译:babel-loader、coffee-loader 、ts-loader等
校验测试:mocha-loader、jshint-loader 、eslint-loader等
说一下vue开发环境和线上环境如何切换
答:主要通过检测process.env.NODE_ENV===”production”和process.env.NODE_ENV===”development”环境,来设置线上和线下环境地址,从而实现线上和线下环境地址的切换
说一下vue如何实现局部样式的或者说如何实现组件之间样式不冲突的和实现原理是什么?
答:css没有局部样式的概念,vue脚手架通过实现了,即在style标签上添加scoped
scoped的实现原理:vue通过postcss给每个dom元素添加一个以data-开头的随机自定义属性实现的
(1) 说一下vue第三方ui样式库如何实现样式穿透的* (ui库和less/sass穿透问题) >>> /deep/*
微信小程序
登录授权
- 小程序端调用wx.login(),获取登录凭证code,并wx.request提交code给己方服务器
- 服务器提交Appid + appSecret + code到微信方服务器,获取session_key & openid
- 服务器根据session_key & openid生成3rd_session,并返回3rd_session到小程序端
- 小程序端wx.setStorage存储3rd_session在后续用户操作需要凭证时,附带该参数
- 小程序端wx.getUserInfo获取用户信息 + wx.getStorage获取3rd_session数据后,一并wx.request提交给己方服务器
- 服务器SQL用户数据信息更新
- www.cnblogs.com/dashucoding…
React
什么react
react是一个构建用户界面的JavaScript库
React的生命周期
组件挂载阶段:
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
组件更新阶段:
- shouldComponentUpdate
- getSnapshotBeforeUpdate
- componentDidUpdate
组件卸载阶段:
- componentWillUnmount()
有状态组件和无状态组件
有状态组件
- 是类组件
- 有继承
- 可以使用this
- 可以是有react的生命周期
- 使用较多,会频发触发声明周期钩函数,影响性能
- 内部使用state,维护自身变化,根据外部组件传入的 props 和自身的 state进行渲染
无状态组件
- 不依赖自身的state
- 可以是类组件或函数组件
- 完全可以避免this关键字
- 有更高的性能
- 内部不维护state,只根据外部传入的props进行渲染,props改变时,组件重新渲染
组件通信的方式
父传子: 父组件通过props向子组件传递信息
子传父: props+回调函数的方式
非父子组件传递:
- 使用props,每一层组件都要上传一个props
- 使用context,context相当于一个容器,将要通信的内容放入context中,别的组件可以随意取用
全局状态管理⼯具: 借助Redux或者Mobx等全局状态管理工具进行通信
PureComponent和Component的区别是什么
PureComponent会自动执行shouldComponentUpdate函数,通过shallowEqual的浅对比,实现react性能优化
Component必须通过自己调用shouldComponentUpdate来实现react组件的优化
JAVASCRIPT
什么是函数
将特定功能的代码抽取出来,使之成为程序中的一个独立实体
怎么判断一个对象是不是空对象
1.通过对象的键长度 Object.keys(obj).length===0
2.通过for...in循环,能循环不到子元素的话就为空对象
3.直接转字符串 JSON.Stringify(obj)==='{}'
箭头函数和普通函数的区别
箭头函数使用箭头定义,普通函数没有
箭头函数比普通函数更简洁
箭头函数的参数可以设置默认值
箭头函数不绑定arguments,取而代之用rest参数...解决
箭头函数没有自己的this,它的this是捕获上下文的this当做自己的this,它的this指向不能改变
跨域的解决方案目前有三种主流解决方案:
跨域的情况有:不同协议,不同域名,不同端口以及域名和ip地址的访问都会产生跨域。
跨域是浏览器做出的限制,和后端没关系
一、 是jsonp
jsonp实现原理:主要是利用动态创建script标签请求后端接口地址,然后传递callback参数,后端接收callback,后端经过数据处理,返回callback函数调用的形式,callback中的参数就是json
二、 是代理(前端代理和后端代理)
前端代理我在vue中主要是通过vue脚手架中的config中的index文件来配置的,其中有个proxyTable来配置跨域的
三、 是CORS
CORS全称叫跨域资源共享,主要是后台工程师设置后端代码来达到前端跨域请求的
注:现在主流框架都是用代理和CORS跨域实现的
说一下JS数组常用方法
push,pop,unshift,shift,splice,join,concat,forEach,filter,map,sort,some,every好多,不过都是平时开发中很常用的方法,大家可以补充一点儿es6的
什么是事件循环:
同步和异步任务分别进入不同的执行环境,同步进入主线程,异步进入任务队列,主线程任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行.这个过程不断重复就是事件循环
-
宏任务:
宏任务主要包含script、setTimeout、setlnterval、I/O、UI交互事件、setImmediate(Node.js环境)
-
微任务:
微任务只要包含Promise、MutationObserver、process.nextTick(Node.js环境)
继承的方式:
寄生组合继承
原型链继承
组合继承
es6中class类的extends关键字继承
回调函数、Promise面试七连:
-
什么是回调函数:
一个函数把另一个函数当做参数使用,调用的同时传递数据
-
回调函数使用场景:
一般用于ajax请求,或者不能立即获取数据
-
回调函数的缺陷:
多层嵌套会产生回调地狱,不利于代码的维护
-
如何解决回调地狱:
使用es6中的Promise
-
Promise的特性:
Promise是一个对象也是一个构造函数,需要被实例化
Promise有三种状态: pending(进行中) fulfilled(已成功) rejected(已失败)
Promise需要传递一个箭头函数,函数中有两个参数reslove,rejected
resolve执行成功,rejected执行失败
Promise的原型有then方法、catch方法、finally方法、all方法、rise方法
finally方法不管Promise状态如何都会执行
-
Promise的缺陷:
代码量较多
-
如何解决Promise缺陷:
使用es7的async await
使用async await可以使异步像同步一样执行
async返回的是一个promise对象
如何中断Promise的链式编程
方式1: 条件成立后,通过throw抛出异常中断
方式2: 条件成立后,通过Promise.reject()中断
get请求与post请求的区别
get请求只能进行url编码,post请求支持多种编码方式
get请求会产生历史记录,post请求不会
get请求更快,post请求更安全
get请求参数通过url传递,post请求放在Request body中
get请求传递参数有长度限制,post没有
get请求只接受字符串,post请求没有限制
http协议的特点
支持客户端/服务器模式
简单快速: 客户向服务器请求服务时,只需传送请求方法和路径
灵活: HTTP允许传输任意类型的数据对象
无连接: 限制每次连接只处理一个请求,服务器处理完客户请求并得到响应后,即断开连接
无状态: 无状态是值协议对事务处理没有记忆能力
es6的新增
-
字符串扩展
新增字符串模板
-
块级作用域
let、const
let const 不存在变量提升
const声明的是一个常量,值不能被修改,const声明时必须赋值
const和let不允许重复声明变量
-
函数扩展
新增箭头函数
参数可以设置默认值
-
数组扩展
Array.from() 将伪数组变成数组
Array.of() 将一组值转换成数组
find() 找出第一个符合条件的数组成员
findIndex() 找出第一个符合条件的数组成员的下标
for...of 数组遍历
reduce 让数组的前后两项进行某种计算,返回最终操作的结果
-
扩展运算符
可以将一个数组转为用逗号分隔的参数序列 复制数组 合并数组 扩展运算符和解构赋值结合,用于生成数组 将字符串转为真正的数组
-
对象扩展
属性名表达式
解构赋值
super关键字 指向当前对象的原型对象
-
支持class语法
-
Promise
数组去重的方法
双层循环,外层循环元素,内层循环时比较值 如果有相同的值则跳过,不相同则push进新的数组
双层循环,外层循环元素,内层循环时比较值 值相同时,则删去这个值 删除元素之后 需要将数组的长度也减1
利用es6的set成员的值都是唯一的特性 利用Array.from将Set转换成数组
利用indexOf以及forEach
数组递归去重
利用对象的属性不能相同的特点进行去重
暂时性死区
在let、const命令声明变量之前,该变量都是不可用的,该变量是不可用的
new操作符做了什么
创建一个对象
将构造函数的作用域赋给新对象
构造函数的this指向该对象,执行构造函数
返回新对象
对rest参数的理解:
以"..."开头是一个真正的数组
它可以把一个分离的参数序列整合成一个数组
function mutiple(...args) {
console.log(args)
}
mutiple(1, 2, 3, 4) // [1, 2, 3, 4]
rest参数的引入减少了样式代码
rest参数可以被解构
原型
当使用构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针被称为对象的原型。
原型链
原型链就是一种查找的过程,通过指针不断往上一层的原型对象查找的过程,就叫做原型链.如果一直往上找没有就会找到null
Ajax
是一种创建交互式网页应用的网页开发技术,是一种能够实现局部网页刷新功能的技术
JSONP和JSON的区别
JSONP是一种非官方的跨域解决方案,利用了script的src不受限制的访问外部资源,结合callback回调函数拿到数据
JSON是一种轻量级的数据结构,能跨平台进行网络传输,能做配置文件
什么是oop
oop是一种编程思想,又叫做面向对象编程
三大特性:
-
继承 子类拥有父类的属性和方法
-
封装 将相同的属性和方法提取成一个类
-
多态
- 重写 子类重写父类的组件和方法
- 重载 在同一个类中,同名不同参,js没有重载
对闭包的理解
闭包就是函数嵌套函数,内部函数可以引用外部函数的参数和变 量,参数和变量不会被垃圾回收机制所回收
-
优点:
使变量长期驻扎在内存当中,实现缓存
避免全局变量污染
在函数外部能够访问到函数内部的变量
-
缺点:
由于闭包会使函数的变量长期驻扎在内存当中,会导致内存消耗过大,影响浏览器的性能,在ie中会导致内存泄漏
垃圾回收机制
-
标记清除:
js会对变量做一个yes或no的标记,供js引擎处理,当变量在某个环境使用时标记为yes,超出该环境时标记为no,js会在一定时间内来扫描,对标记为no的变量进行释放
-
引用计数:
对于引用类型的变量,采用引用计数的回收机制,当一个引用类型的变量赋值给另一个变量时,引用计数+1,当其中有一个变量不再等于值时,引用计数-1,如果引用计数为0,js引擎会将其释放
什么是递归
函数自己调用自己,有一个临界点,就是结束条件
递归的使用场景
快速排序使用递归
nodejs磁盘文件的遍历
管理系统的权限菜单栏
对象的深拷贝
对象的深拷贝和浅拷贝
浅拷贝:
- 浅拷贝只会将对象的各个属性进行依次复制,并不会进行递归复制
- 如果拷贝后的对象发生变化,原对象也会发生变化
深拷贝:
- 不仅将原对象的各个属性逐个复制,而且将原对象各个属性所包含的对象也依次采用深拷贝的方法递归复制到新对象上
- 拷贝后的对象不会影响原来的对象
深拷贝方法
-
如果拷贝的对象是json格式的数据可以使用JSON.stringify()和JSON.parse()
缺点:
- 如果不是json格式会报错
- 不能拷贝对象属性为函数的
- 不能拷贝对象属性值为undefine
- 不能拷贝正则
- 不能实现对对象的循环引用
-
使用递归的方式遍历对象把它复制到一个新的对象,改变它的key和value,用一个崭新的对象替代它
浅拷贝方法
- object.assign
- es6扩展运算符
什么是http协议
超文本传输协议HyperText Transfer Protocol
就是客户端和服务端进行数据传输的一种规则
http协议的五大特点
支持客户/服务器模式
通信速度快
http允许传输任意类型的数据对象
无连接 限制每次只处理一个请求
无状态 对事务处理没有记忆能力
浏览器输入url后的流程
将地址发送到DNS服务器
DNS进行域名解析
获取域名所对应的web服务器地址
建立TCP连接
浏览器发送http请求
服务器处理请求并响应结果
浏览器解析HTML
关闭TCP连接
浏览器布局渲染
浏览器渲染页面的原理及流程
根据html文件构建DOM树和CSS规则树
附着合成构建渲染树
页面渲染完成后显示页面
关于浏览器预检(options)请求
在非简单请求且跨域的情况下,浏览器会发起options预检请求
常见的复杂请求
- 请求方法为PUT或DELETE
- Content-Type字段类型为application/json
- 添加额外的http header 比如access_token
在跨域的情况下,非简单请求会先发起一次空body的options请求,称为"预检"请求,用于向服务器请求权限信息,等预检请求被成功响应后,才发起真正的http请求
http1.0和http2.0的区别
-
http1.0
无状态、无连接
浏览器每次请求都需要与服务器建立一个TCP连接,服务器处理完成后立即断开TCP连接
-
http2.0
二进制分帧
- HTTP/2引入二进制数据帧和流的概念,其中针对数据进行顺序标识
多路复用(或连接共享)
- 所有的HTTP2.0通信都在一个TCP连接上完成,这个连接可以承载任意数量的双向数据流
- 一个request对应一个id,这样一个连接可以有多个request,服务器可以根据请求的id进行处理
头部压缩
-
HTTP2.0使用encoder来减少需要传输的header大小
- 避免了重复header的传输
服务器推送
- 服务器除了对最初请求的响应外,服务器还可以额外的向客户端推送资源,而无需客户端明确的请求
对this对象的理解
this 是执行上下文中的一个属性,它指向最后一次调用这个方法的对象。在实际开发中,this 的指向可以通过四种调用模式来判断。
- 第一种是函数调用模式,当一个函数不是一个对象的属性时,直接作为函数来调用时,this 指向全局对象。
- 第二种是方法调用模式,如果一个函数作为一个对象的方法来调用时,this 指向这个对象。
- 第三种是构造器调用模式,如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象。
- 第四种是 apply 、 call 和 bind 调用模式,这三个方法都可以显示的指定调用函数的 this 指向。其中 apply 方法接收两个参数:一个是 this 绑定的对象,一个是参数数组。call 方法接收的参数,第一个是 this 绑定的对象,后面的其余参数是传入函数执行的参数。也就是说,在使用 call() 方法时,传递给函数的参数必须逐个列举出来。bind 方法通过传入一个对象,返回一个 this 绑定了传入对象的新函数。这个函数的 this 指向除了使用 new 时会被改变,其他情况下都不会改变。
这四种方式,使用构造器调用模式的优先级最高,然后是 apply、call 和 bind 调用模式,然后是方法调用模式,然后是函数调用模式。
diff算法
说一下call,apply,bind区别
答:call,apply,bind主要作用都是改变this指向的,但使用上略有区别,说一下区别:
call和apply的主要区别是在传递参数上不同, call后面传递的参数是以逗号的形式分开的,apply传递的参数是数组形式 [Apply是以A开头的,所以应该是跟Array(数组)形式的参数]
bind返回的是一个函数形式,如果要执行,则后面要再加一个小括号 例如:bind(obj,参数1,参数2,)(),bind只能以逗号分隔形式,不能是数组形式
如何实现0.1+0.2=0.3
一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。
对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON
属性,而它的值就是2-52,只要判断0.1+0.2-0.3
是否小于Number.EPSILON
,如果小于,就可以判断为0.1+0.2 ===0.3
for...in和for...of的区别
-
for…of 遍历获取的是对象的键值,for…in 获取的是对象的键名;
-
for… in 会遍历对象的整个原型链,性能非常差不推荐使用,而 for … of 只遍历当前对象不会遍历原型链;
-
对于数组的遍历,for…in 会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for…of 只返回数组的下标对应的属性值
总结: for...in 循环主要是为了遍历对象而生,不适用于遍历数组;for...of 循环可以用来遍历数组、类数组对象,字符串、Set、Map 以及 Generator 对象。
什么是 DOM 和 BOM?
- DOM:文档对象模型,它指的是把文档当做一个对象,这个对象主要定义了处理网页内容的方法和接口。
- BOM:浏览器对象模型,它指的是把浏览器当做一个对象来对待,这个对象主要定义了与浏览器进行交互的法和接口。
- 并且 DOM 的最根本的对象 document 对象是 BOM 的 window 对象的子对象。
ES6模块与CommonJS模块的异同
判断一个对象是否属于某个类
- instanceof
- constructor
- Object.prototype.toString()
null是什么类型的
console.log(typeof null); // object
判断数据类型的方法 他们的区别
-
(1)typeof:判断基本类型
console.log(typeof 2); // number console.log(typeof true); // boolean console.log(typeof 'str'); // string console.log(typeof []); // object console.log(typeof function(){}); // function console.log(typeof {}); // object console.log(typeof undefined); // undefined console.log(typeof null); // object // 其中数组、对象、null都会被判断为object,其他判断都正确。
-
(2)instanceof:判断引用类型
instanceof
可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型。console.log(2 instanceof Number); // false console.log(true instanceof Boolean); // false console.log('str' instanceof String); // false console.log([] instanceof Array); // true console.log(function(){} instanceof Function); // true console.log({} instanceof Object); // true
-
(3) constructor:
constructor
有两个作用,一是判断数据的类型,二是对象实例通过constrcutor
对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor
就不能用来判断数据类型了 -
(4)Object.prototype.toString.call() :
使用 Object 对象的原型方法 toString 来判断数据类型
CSS
什么是BFC
块级格式化上下文
BFC是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定规则进行物品摆放,并且不会影响其它环境中的物品
怎么创建BFC
使用浮动布局 绝对定位
overflow不为visible
盒模型的理解
盒模型都是由四个部分组成的,分别是margin、border、padding和content
标准盒模型的width和height属性的范围只包含了content
IE盒模型的width和height属性的范围包含了border、padding和content
css3新增特性
圆角border-radius
@font-size加载字体样式
文字渲染
多列布局column-count
渐变效果gradient
阴影效果图
多背景图片
动画效果animation
两栏式布局
左边一栏宽度固定,右边一栏宽度自适应
三栏式布局
左右两栏宽度固定,中间自适应
定位
relative:元素的定位相对于元素自身位置,不会影响其他元素,不脱离文档流
fixed:元素的定位相对于window边界,会导致其他元素位置的变化
absolute:脱离文档流
absolute和fixed的区别
共同点:
改变行内元素的呈现方式(inline-block)
是元素脱离普通文档流,不占据空间
覆盖非定位文档元素
不同点:
absolute与fixed的根元素不同,absolute根元素可以设置,fixed的根元素为浏览器
在有滚动条的页面中,absolute会跟着父元素进行移动,fixed固定在页面的具体位置
css优化
-
加载性能
将写好的css进行打包压缩
减少使用@import,尽量用link 后者在页面加载时一起加载,前者是等待页面加载完成之后再进行加载
-
选择器性能
避免使用通配规则
尽量少用后代选择器
-
渲染性能
慎重使用 定位 浮动
减少页面的重绘、重排
去除空规则
属性值为0.几时可以去掉0
-
可维护性、健壮性
将有相同属性的样式抽离,通过类名使用
样式与内容分离 将css代码定义在外部文件中
如何解决1px问题
1、直接写0.5px
2、伪元素先放大后缩小
3、viewport缩放
设置小于12px的字体
谷歌浏览器:加样式前缀-webkite-
css3:-webkit-transform:scale(0.5)
使用图片
高度塌陷
-
兄弟之间
两个margin值中取最大的
只给一个盒子添加margin值
-
父子之间
当子元素有浮动并且父元素没有高度的情况下,父元素会出现高度为零的情况。
方法一:给父元素写固定高度
方法二:给外部的父盒子也添加浮动,让其也脱离标准文档流
方法三:给父元素添加声明overflow:hidden;(触发一个BFC)
方法四:在浮动元素下方添加空div,并给该元素设置以下属性:
.空div的类名{
clear:both;
height:0;
overflow:hidden;
}
方法五: 给父元素添加display:table;
方法六:万能清除浮动法(推荐使用!!!)
在父元素中内容的最后添加一个伪元素,具体设置样式如下:
.box:after{
content:"";
clear: both;
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}
rfc
react中创建组件的方式之一
ES5 原生方式 React.createClass // RFC
React.createClass会自绑定函数方法,导致不必要的性能开销,增加代码过时的可能性。
兼容性相关:
(1) pc端:
a) 一般是IE兼容的问题,例如:利用css hack来解决 * ,_,等
b) JS有特性匹配来解决某个JS方法是否存在
(2) 手机端:主要遇到过移动端300ms延迟和点透问题,可以通过fastclick插件解决
性能优化相关:
答:性能优化是一个很大的一个话题:优化的方面有很多,1是网络加载方面的优化:例如:减少http请求(合并文件,css雪碧图,图片懒加载),减少dom操作(dom缓存),代码封装,第三方库用cdn加载,gzip压缩等
移动端适配方案
答:前端做适配没有最好的方法,只有适合的方法,目前前端主要做适配的方法有:百分比,em,rem,媒体查询(即media query),flex布局(即弹性盒),vw,vh等
目前我在项目中用的多的是rem,flex布局,有时会用到媒体查询,在做pc响应式布局时用
主要是用了一个手淘的js库flexible.js,在页面变化时,检测页面宽度,除以10份,动态的赋值给font-size.属性.;而页面的布局我是通过rem来进行布局的,所以就可以适配所有的移动端设备了
解决媒体查询的问题
用rem方案
%
做一个三角形
- 上三角形
div {
width: 0;
height: 0;
border-top: 50px solid red;
border-right: 50px solid transparent;
border-left: 50px solid transparent;
}
-
下三角形
div { width: 0; height: 0; border-bottom: 50px solid red; border-right: 50px solid transparent; border-left: 50px solid transparent; }
-
左三角形
div { width: 0; height: 0; border-left: 50px solid red; border-top: 50px solid transparent; border-bottom: 50px solid transparent; }
- 右三角形
div {
width: 0;
height: 0;
border-right: 50px solid red;
border-top: 50px solid transparent;
border-bottom: 50px solid transparent;
}
如何实现一个div垂直居中(至少3种方法)
答:其实实现水平垂直剧中方法有很多:
第一种:定位:
第一种思路:通过给div设置绝对定位,并且left,right,top,bottom设置为0,margin:auto即可以水平垂直居中
第二种思路:通过给div设置绝对定位,left为50%,top为50%,再给div设置距左是自身的一半即:margin-left:自身宽度/2,margin-top:自身高度/2。
第三种思路:通过给div设置绝对定位,left为50%,top为50%,再给div设置跨左和跟上是自身的一半:transform:translate3d(-50%,-50%,0)
第四种:flex布局:
display:flex;
justify-content:center;
align-items:center;
HTML5
html5的新增特性
语义化标签
表单类型
表单属性
媒体标签
进度条、度量器
DOM查询操作
web存储
git相关:
(1) 你们公司项目是如何管理的?
答:主要通过git来进行项目版本控制的
(2) 说几个git常用命令?
答:我工作中常用的有git add ,git status,git commit –m,git push,git pull等
(3) 说一下多人操作同一个文件,如果出现冲突该如何解决?
答:当遇到多人协作修改同一个文件时出现冲突,我先将远程文件先git pull下来,手动修改冲突代码后,再git add ,git commit,git push再上传到远程仓库。如果pull也pull不下来提示冲突的话,可以先通过git stash暂存下来,然后再pull拉取,然后git stash pop,取出原来写的,手动修改,然后提交