前端知识点目录
- 前言
- CSS部分
- javascript部分
- Vue部分
- 一、简述MVVM
- 二、Vue的生命周期
- 三、对keep-alive的了解
- 四、v-for和v-if的优先级
- 五、scoped原理
- 六、样式穿透
- 七、组件间传值通信(父传子、子传父、兄弟组件传值)
- 八、computed、methods、watch有什么区别
- 九、props和data的优先级谁高?
- 十、$nextTick的使用
- 十一、vue组件中data为什么必须是一个函数?
- 十二、渐进式框架的理解
- 十二、Vuex有哪些属性?
- 十三、mutations和actions的区别
- 十四、vuex持久化
- 十五、vue路由模式及区别
- 十六、SPA是什么?
- 十七、
- 插槽
- Vuex 模块化 命名空间后, 如何调用其余模块
- promise - 6.promise.all源码实现
- 为什么使用key?
- vue-loader是什么?使用它的用途有哪些?
- 网络安全、HTTP协议
- 前端性能优化
前言
结合高频面试题对前端各知识点做个汇总,并对部分知识点单独详解
有试题答案,
因为是根据面试题来做的所以知识点会有点乱没有先后顺序
就当看面试题吧!
CSS部分
一、回流和重绘
回流必将引起重绘,而重绘不一定会引起回流。
1.回流
当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流
(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的,因为要构建render tree。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。
2.重绘
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘
。
javascript部分
一、闭包
闭包
就是打通函数外部访问函数内部变量的一条通道
表象判断是不是闭包的话可以看他是不是函数嵌套函数,内层函数被return,然后内层函数调用外层函数的局部变量;
优点
:可以隔离作用域,避免造成全局污染;
缺点
:由于闭包长期驻留内存,导致内存泄漏;
解决方法
:将暴露外部的闭包变量重置为null;
适用场景
:在性能优化的过程中,节流、防抖函数的使用;封装组件时,for循环和定时器的结合使用,for循环和dom事件的结合使用;
二、栈内存和堆内存
栈内存:
存储基本的数据类型,由操作系统自动分配,调用完毕之后立刻释放。
堆内存:
存储引用类型,存放引用地址,由程序员分配和释放,若没有手动释放则由垃圾回收算法自动释放。
三、原型对象、原型链、作用域链
JS原型对象、原型链及其优缺点,以及原型链与作用域链的区别 详解
原型对象:
在js中,每个对象都有一个与他关联的对象,这个对象就叫做原型对象(实例对象的[[Prototype]]
、构造函数的prototype
),他可以使多个对象共享一个或者多个方法。
原型链:
js在每次获取对象属性或方法时会在自有属性中找,如果找不到不到就会去原型对象中找,如果原型对象中还找不到,就会去原型对象的原型对象中找,直到找到或找至最顶端的Object,这查找的路线就被叫做原型链
。
原型继承的缺点:
如果原型对象中存在引用类型的话,则所有实例都会共享,例如一个实例追加数组元素,则其他实例也会同时被追加(push)。
作用域链:
查找变量时,先在自己的变量范围中查找,如果找不到就会沿着作用域往上找,直到找到或找至全局作用域,这个查找路线就是作用域链。
四、说一下JS继承(含ES6的)
——或者人家这样问有两个类A和B,B怎么继承A?
1.什么是继承:
通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法
2.如何实现继承
Js继承(构造函数继承、原型原型链插入继承)、es6中的继承(类)
1)Js继承:构造函数继承
让新实例的原型等于父类的实例
// 父类
function A(){
this.name='A';
this.info=function(){
console.log('我是'+this.name)
}
}
function B(){
this.age=18;
}
B.prototype=new A()
var b1=new B();
b1.info();
console.log(b1.age)
2)Js继承:插入继承
用.call()和.apply()将父类构造函数引入子类函数
// 父类
function A(){
this.name='A';
this.info=function(){
console.log('我是'+this.name)
}
}
function B(){
A.call(this);
this.age=20;
}
var b2=new B();
b2.info();
console.log(b2.age)
3)ES6:(类)继承
class A {
constructor(){//构造器代码,new时自动执行
this.name='A';
};
info(){
console.log('我是'+this.name)
};
};
class B extends A {
constructor(){
super();//表示父类
this.age=22;
};
};
var b3=new B();
b3.info();
console.log(b3.age);
五、call()、apply()、bind()的用法及区别
call()、apply()、bind()的用法及区别 详解
call,apply,bind主要作用都是改变this指向的,但使用上略有区别
区别:
call
和apply
的主要区别是在传递参数上不同,call
后面传递的参数是以逗号的形式分开的,apply
传递的参数是数组形式 (Apply是以A开头的,所以应该是跟Array(数组)形式的参数)
bind
返回的是一个函数形式,如果要执行,则后面要再加一个小括号
方法名.call( this的指向 , 其他参数1 , 其他参数2 );
方法名.apply( this的指向 , [ 其他参数1 , 其他参数2 ] );
方法名.bind( this的指向 , 其他参数1 , 其他参数2 )();
六、浅拷贝、深拷贝
浅拷贝:
只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
浅拷贝方法:
Object.assign()、Array.prototype.concat()、Array.prototype.slice()
深拷贝:
会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
深拷贝方法:
JSON转换、递归函数拷贝
七、数组去重
ES6实现
/*
* 基本思路:ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
* Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化 */
function uniq(array){
var x = new Set(array);
return [...x];
}
var arr = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(arr));
八、Javascript中callee和caller的作用?
callee
是返回正在被执行的function函数,也就是所指定的function对象的正文。
caller
是返回一个对函数的引用,该函数调用了当前函数;
function outer(){
inset();
}
function inset(){
console.log(arguments.callee)// f inset()
console.log(inset.caller)// f outer()
}
outer();
九、JS执行机制(同步、异步、宏任务、微任务)
同步任务:
在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。
异步任务:
不进入主线程、而进入”任务队列”的任务,当主线程中的任务运行完了,才会从”任务队列”取出异步任务放入主线程执行。
异步任务又分为微任务
(包括Promise,process.nextTick)和宏任务
(包括整体代码script,setTimeout,setInterval)
执行顺序总结:
先做同步任务,在做异步任务,异步任务又分为微任务和宏任务,先做微任务在做宏任务。
同步任务 => 异步任务( 微任务 => 宏任务 )
Vue部分
一、简述MVVM
MVVM
是Model-View-ViewModel
缩写,也就是把MVC
中的Controller
演变成ViewModel
。Model
层代表数据模型,View
代表UI组件,ViewModel
是View
和Model
层的桥梁,数据会绑定到viewModel
层并自动将数据渲染到页面中,视图变化的时候会通知viewModel
层更新数据。
二、Vue的生命周期
1.beforeCreate( 创建前 )
在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,无data,无dom
2.created( 创建后 )
实例已经创建完成之后被调用,有data无dom
3.beforeMount( 挂载前 )
挂载开始之前被调用,实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂在html到页面上。有data无dom
4.mounted( 挂载后 )
挂载完成,有data有dom
5.beforeUpdate( 更新前 )
在数据更新之前被调用,发生在虚拟DOM重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程
6.updated( 更新前 )
在由于数据更改导致地虚拟DOM重新渲染和打补丁只会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用
7.beforeDestroy( 销毁前 )
在实例销毁之前调用,实例仍然完全可用,
这一步还可以用this来获取实例,
一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的dom事件
8.destroyed( 销毁后 )
在实例销毁之后调用,调用后,所以的事件监听器会被移除,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用
当组件被keep-alive包裹时,会多两个生命周期
9.actived
keep-alive组件激活时调用
10.deactived
keep-alive组件停用时调用
三、对keep-alive的了解
1.是什么
vue系统自带的一个组件,功能:用来缓存组件,提升性能。
2.使用场景
缓存组件,提升项目性能。
如:列表页进入详情页,如果每次进入的都是同一个详情,那么详情就没必要请求多次了,直接缓存起来就可以了,如果不同就请求。
四、v-for和v-if的优先级
v-for > v-if
五、scoped原理
作用:让样式只在本组件中生效,不影响其他组件。
原理:属性选择器,给节点新增自定义属性,然后css根据属性选择器添加样式。如:div[data-v-xxx]
{ color:red; }
六、样式穿透
/deep/
、::v-deep
、>>>
七、组件间传值通信(父传子、子传父、兄弟组件传值)
1.父传子
父组件:<son :msg=“fatherMsg”></son>
子组件:props:[‘msg’]
2.子传父
父组件:
<son @自定义事件名称=“方法”></son>
子组件:
props:[‘自定义事件名称’]
this.$emit(自定义事件名称,要传的数据)
3.兄弟组件传值
通过一个中转(bus):
import Vue from ‘vue’
export default new Vue;
A兄弟传值:
import bus from ‘@/common/bus.js’
bus.$emit(‘toBorther’,this.msg)
B兄弟接收:
import bus from ‘@/common/bus.js’
bus.$on(‘toBorther’,(data)=>{
this.msg=data
})
八、computed、methods、watch有什么区别
1.computed vs methods
computed 是有缓存的
methods 没有缓存
2.computed vs watch
watch
当一条数据影响多条数据的时候就需要用watch
computed
当一个属性受多个属性影响的时候就需要用到computed
九、props和data的优先级谁高?
props > methods > data > computed > watch
十、$nextTick的使用
Vue实现响应式并不是数据发生变化之后DOM立即变化,而是异步执行DOM更新的。
nextTick是Vue提供的一个全局API,是在下次DOM更新循环结束之后执行延迟回调。
适用场景:
- created中的dom操作
- 改变dom结构后,需要根据更新后的dom状态去做某些事
- mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
十一、vue组件中data为什么必须是一个函数?
因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,如果组件中 data 是一个函数,那么每个实例都有自己私有的数据空间,组件实例之间的 data 属性值不会互相影响。
十二、渐进式框架的理解
vue是渐进式框架
主张(要求)最少;可以根据不同的需求选择不同的层级;
就是一开始不需要你完全掌握它的全部功能特性,可以后续逐步增加功能。没有多做职责之外的事情
Vue与React、Angular的不同是它是渐进的
1、vue.js只提供了vue-cli生态中最核心的组件系统和双向数据绑定
2、就好像 vuex、vue-router都属于围绕vue.js开发的库
十二、Vuex有哪些属性?
state、getters、mutations、actions 、modules
state
类似于组件中的data,用来存放数据的
getters
类似于组件中的computed
mutations
类似于组件中的methods
actions
提交mutations的
modules
把以上4个属性再细分,让仓库更好管理
十三、mutations和actions的区别
mutations:
都是同步事务。
actions:
提交的是mutaion,而不是直接变更状态。
可以包含任意异步操作。
十四、vuex持久化
vuex本身不是持久化存储
1.使用localStorage
2.使用插件 (vuex-persistedstate)
十五、vue路由模式及区别
路由模式:history、hash
区别:
- 表现形式不同
history: http://locahost:8080/about
hash: http://locahost:8080/#/about - 跳转请求(找不到的页面)
history: http://locahost:8080/abc 会发送请求,请求id页面
hash: http://locahost:8080/#/abc 不会发送请求 - 打包后前端自测要使用hash,如果使用history会出现空白页面
十六、SPA是什么?
SPA:单页面应用
缺点:
- SEO优化不好
- 首屏加载慢
十七、
插槽
https://baijiahao.baidu.com/s?id=1667546704320334891&wfr=spider&for=pc
Vuex 模块化 命名空间后, 如何调用其余模块
action的参数中有rootState、rootGetters
可通过以下方法来调用
dispatch(‘vip/get’, {}, {root: true})
参数一:是其他模块的 actions 路径。
参数二:是传给 actions 的数据, 如果不需要传数据, 也必须预留,
参数三:是配置选项, 申明这个 acitons 不是当前模块的
https://www.jianshu.com/p/5c467a3e1ca9
promise - 6.promise.all源码实现
function isPromise(x) { // 校验是否是 promise
if((typeof x == 'object' && x !== null) || typeof x == 'function') {
if(typeof x.then == 'function') {
return true
}
}
return false
}
Promise.all = function(promises) {
return new Promise((resolve, reject) => {
let arr = []
let idx = 0 // 执行个数
let dealProcess = (val, index) => {
arr[index] = val
if(++idx == promises.length) {
resolve(arr)
}
}
promises.forEach((item, i) => {
if(isPromise(item)) {
item.then(y => {
dealProcess(y, i)
}, reject)
}else {
dealProcess(item, i)
}
});
})
}
let util = require('util')
let read = util.promisify(fs.readFile)
Promise.all([1, read('./name.txt', 'utf8'), 2, read('./age.txt', 'utf8'), 3]).then(data => {
console.log(data);
})
为什么使用key?
答:给每个节点做一个唯一标识,让Diff算法可以正确的识别此节点。
作用主要是为了高效的更新虚拟DOM。
vue-loader是什么?使用它的用途有哪些?
答:vue文件的一个加载器,将template/js/style转换成js模块。
用途:js可以写es6、style样式可以scss或less、template可以加jade等
网络安全、HTTP协议
一、Http和Https区别
HTTP
的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头HTTP
是不安全的,而 HTTPS 是安全的HTTP
无法加密,而HTTPS 对传输的数据进行加密HTTP
无需证书,而HTTPS 需要CA机构wosign的颁发的SSL证书HTTP
标准端口是80 ,而 HTTPS 的标准端口是443在OSI
网络模型中,HTTP工作于应用层,而HTTPS 的安全传输机制工作在传输层
二、GET和POST区别
- GET参数通过URL传递,POST放在Request body中
- GET参数暴露在地址栏不安全,POST放在报文内部更安全
- GET一般用于查询信息,POST一般用于提交某种信息进行某些修改操作
- GET请求在URL中传送的参数是有长度限制的,而POST没有限制
- GET在浏览器回退不会再次请求,POST会再次提交请求
- GET请求会被浏览器主动缓存,POST不会,要手动设置
- GET请求参数会被完整保留在浏览器历史记录里,POST中的参数不会
- GET产生一个TCP数据包;POST产生两个TCP数据包
前端性能优化
做过的Vue性能优化
- 尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
- 如果需要使用v-for给每项元素绑定事件时使用事件代理
- v-for时key保证唯一
- 在更多的情况下,使用v-if替代v-show,减少初次加载的渲染成本
- 使用路由懒加载、异步组件
- 第三方模块按需导入
- 长列表滚动到可视区域动态加载
- 图片懒加载
- 骨架屏
- 防抖、节流
- SPA 页面采用keep-alive缓存组件
- SEO优化
- 预渲染
- 服务端渲染SSR
- 打包优化
- 压缩代码
- Tree Shaking/Scope Hoisting
- 使用cdn加载第三方模块
- 多线程打包happypack
- splitChunks抽离公共文件
- sourceMap优化
- 用户体验
- PWA
- 还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。
以上内容仅供个人学习,如有错误请指正。谢谢。