前端面试题

132 阅读16分钟
  1. 你是如何理解HTML语义化的 HTML语义化就是不同的内容用不同的标签来包括。段落用p标签,超链接用a标签,边栏用aside,标题用h1~h6,页脚用footer,文章用article。

  2. meta viewport用来做什么的?怎么用? meta viewport是用来适配移动端的,适配之后用户不需要自行进行缩放就能清楚的显示内容和图片。在meta标签中,name设置为viewport。用content来定义viewport的属性。其中content能设置的属性有五个 width:移动设备下的宽度,值为正整数和device width user-scalable:是否能进行缩放 initial-scale:页面的初始缩放值 maximum:最大缩放 minimum:最小缩放

  3. H5是指移动端页面或者移动端web应用

  4. 两种盒模型 content-box:它的width和height只包含content。 border-box:它的width包含content,padding,border

  5. flex怎么用,常用的属性有那些? flex是弹性布局。 flex-direction:确定主轴方向,column/row flex-wrap:一条轴线排布,是否换行 flex-flow:是flex-direction和flex-wrap的简写形式。 justify-content:项目在主轴方向的对齐方式。flex-start|flex-end|center|space-between|space-around align-items:项目在交叉轴上怎么对齐。flex-start|flex-end|center|baseline|stretch align-content:多根轴线的对齐方法。flex-start|flex-end|center|space-between|space-around|stretch

项目属性: order:排列顺序,数值越小越靠前 flex—grow:定义项目放大的比例 flex-shrink:定义项目缩小的比例 flex-basis:分配多余的空间 flex:上面三个的缩写 align-self:允许单个项目与其他项目有不一样的对齐方式

  1. 如何进行垂直居中 table|flex|absolute margin auto|top left 50% translate transform(-50%,-50%)|top left 50%位移半个宽高

  2. BFC是什么? BFC即块级格式化上下文,当元素为浮动元素,行内块元素,绝对定位元素时就会触发.两个相邻的BFC的外边框会发生重叠。

  3. css的优先级 important优先级最高,然后是行内样式,id选择器,class选择器伪类选择器,然后是标签选择器和伪元素选择器,通配符优先级最低。

  4. css动画,box-shadow

  5. 清除浮动

.clearfix:after{
    content:'';
    display:block;
    clear:both;
}
  1. ES6语法有哪些? let,const,作用域,箭头函数,解析赋值,剩余参数

  2. 有哪些常用的事件? 资源事件:资源加载失败时触发error();资源加载完成时触发load()事件。

焦点事件:元素获得焦点触发focus();元素失去焦点时blur()

表单事件:点击重置按钮时触发reset();点击提交按钮时触发submit()

键盘事件:按下任意按键触发keydown()

鼠标事件:单击鼠标click(),双击鼠标dblclick();按下mousedown(),移动mousemove(),mouseup释放鼠标

  1. 箭头函数和普通函数的区别 箭头函数都是匿名函数,没有自己的this,它指向的是上一层指向的this不能作为构造函数,也没有arguments,没有原型prototype
  • .call()/.apply()/.bind无法改变箭头函数中的this指向
  • 箭头函数不能用作Generator函数
  1. Promise,Promise.race,Promise.all分别有什么用? promise是用来解决异步操作中地狱回调的一种方式,他有三种状态,分别是pending(待定),fulfilled(已阅现),reject(操作失败),并且定义了resolve用来返回成功,reject返回失败,可以通过then来获取数据,才catch获取失败数据。 Promise.race用法:谁跑的快,以谁为准执行回调 Promise.all:谁跑的慢以谁为准 执行回调,所有操作成功之后则成功,只要有一个失败,则失败。all接受一个数组参数,里面的值都算返回的Promise对象。

  2. 手写函数防抖和节流

防抖:如果在短时间内大量触发同一事件,之执行一次函数,例如:回到顶部

function fn(){}
var timerId =null
button.onclick = function(){
    if(timerId){
        window.clearTimeout(timerId)
    }
    timerId = setTimeout(()=>{
        fn()
        timerId=null
    },5000)
}

节流:如果在短时间内大量触发同一事件,那么在函数执行一次后,该函数在时间期限内不会在工作

function fn(){}
var cd = false
button.onclick = function(){
    if(cd){

    }else{
        fn()
        cd=true
        var timerId = setTimeout(()=>{
            cd = false
        },3000)
    }
}
  1. 手写ajax ajax是浏览器上的功能,浏览器可以发送请求,接受响应。浏览器在window上加了一个XMLHttpRequest函数,这个构造函数可以构造出一个对象,js通过它实现发送请求和接受响应。
//四点
const request = new XMLHttpRequest()
request.open('GET','URL')
request.onreadystatechange = () =>{
    if(request.status === 200 && request.readyState === 4){
        console.log(request.responseText)
    }
}
request.send()
  1. 代码中的this是什么? 搜索方应杭this

  2. 闭包和立即执行函数是什么?

  • 闭包 函数和函数内部能访问到的变量的环境统称为闭包。闭包常常用来间接访问一个变量

  • 立即执行函数 马上声明一个函数,并且马上调用这个匿名函数。常常用来创建一个独立的作用域,这个作用域里面的变量,外面访问不到(即避免变量污染)。

  1. 什么是JSONP什么是CROS,什么是跨域? 因为有同源策略的存在,当两个页面有协议,域名,端口任意不相同都属于跨域,JSONP和CROS是来解决跨域的方案。JSONP是通过script标签加载数据的方式去获取数据当做JS代码来执行,兼容性好,但是只能进行GET请求,一般和后端配合使用。CROS成为跨域资源共享,他允许浏览器向跨域服务器发送XMLHttpRequest请求,从而解决同源问题,支持所有请求。

同源策略:协议、端口、域名一致

  1. POST和GET的区别(数据请求码) 请求方法
  • GET:读取 产生一个TCP数据包。浏览器把http header和data一并发出去,服务器响应200。
  • POST:修改 产生两个TCP数据包。浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok返回数据。

图片

最大的不同就是报文格式不同,GET在URL上写参数,POST在body写参数

  • PUT:更新
  • PATCH:更新,部分更新
  • DELETE:删除
  1. HTTP状态码有哪些 100:continue 200:ok 301:临时重定向 302:永久重定向 404:没有找到网页 500:服务器内部出错 504:网关错误

1xx:等待信息响应 2XX:成功 3XX:需要进一步操作 4XX:浏览器出错 5XX:服务器出错

  1. async await怎么用,如何捕获异常 async和await是promise then catch的语法糖,await只能在async的函数内进行使用,可以使用try catch来进行捕获异常。

  2. 如何实行深拷贝? 将一个对象型从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。 使用JSON.stringfy,JSON.parse可以进行深拷贝,缺点是undefined,symbol,函数 这些类型数据会消失,无法拷贝对象的循环应用(对象成环)

JSON.parse(JSON.stringfy)
  • 递归
function clone(target){
    if(typeof target === 'object'){
        let cloneTarget = {}
        for (const key in target){
            cloneTarget[key] = clone(target[key])
        }
        return cloneTarget
    }else{
        return target
    }
}
  • 考虑数组
module.exports = function clone(target){
    if(type target === 'object'){
        let cloneTarget = Array.isArray(target)?[]:{}
        for(const kry in target){
            cloneTarget[key] = clone(target[key])
        }
        return cloneTarget
    }else{
        return target
    }
}
  • 检查循环引用(环),如果某一个对象引用了自己,递归出不来(额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系,当需要拷贝当前对象时,先去存储空间中找,有没有拷贝过这个对象,如果有的话直接返回,如果没有的话继续拷贝,这样就巧妙化解的循环引用的问题。)
function clone(target,map = new Map()){
    if(typeof target === 'object'){
        let cloneTarget === Array.isArray(target)?[]:{}
        if(map.get(target)){
           return map.get(target)
        }
        map.set(target,cloneTarget)
        for(const key in target){
            cloneTarget[key] = clone(target[key],map)
        }
        return cloneTarget
    }else{
        return target
    }
}
  1. 如何使用正则实现trim() 删除一个字符串的两端空白字符
function trim(string){
    return string.replace(/^\s+|\s+$/g/,'')
}
  1. 不用class如何继承?用class又如何实现?
//使用class实现
class Animal{
    constructor(color){
        this.color = color
    }
    move(){}
}
class Dog extends Animal{
    constructor(color,name){
        super(color)
        this.name = name
    }
    say(){}
}

//不使用class
function Animal(color){
    this.color = color
}
Animal.prototype.move = function(){}

function Dog(color,name){
    Animal.call(this,color)
    this.name = name
}

function temp(){}
temp.prototype = Animal.prototype
Dog.prototype = Animal.prototype
Dog.prototype = new temp()

Dog.prototype.constructor = Dog
Dog.prototype.say = function(){console.lod('汪')}

var dog = Dog('黄色','阿黄')
  1. 如何实现数组去重
const arr = [1,2,3,2,4,5,5,6,6,7,7]
//1.new Set
function unique(x){
    return Array.from(new Set(x))
}
console.log(unique(arr))
  1. 事件委托
const ul = document.getElementById('app')
ul.addEventListener('click',(e)=>{
    if(e.target.tagName.toLowerCase() === 'li'){
        console.log('你点击了li')
    }
})
  1. cookie,LocalStorage,SessionStorage,Session的区别

本地储存: cookie会发送到服务器端,大小一般是4k,数据不可以跨域调用。默认失效时间是关闭浏览器,可以设置失效时间。所有同源窗口中都是共享的。 LocalStorage大小一般为5M。除非被清除否则永久保存。在所有同源窗口中都是共享的。 SessionStorage大小一般为5M。仅在当前会话有效,关闭页面或浏览器后被清除。不在不同的浏览器窗口中共享,即使是同一个页面。

服务器储存:session的id值会保存在cookie。

  1. Vue的watch和computed和methods的区别 watch是监控属性,如果属性有变化就会触发

computed是计算属性,他使用缓存的,如果从普特定以来的属性没有变化,那么它就不会发生变化。

methods是方法,只有在调用时才会被调用。

  1. Vue的nextTick有什么用 在下次 DOM 更新循环结束之后执行延迟回调。mounted 不会保证所有的子组件也都一起被挂载。如果希望等到整个视图都渲染完毕,可以在mounted内部使用 vm.$nextTick。在渲染视图时,保证子组件的视图也会被渲染或更新

  2. 讲一讲Vue的生命周期,生命周期钩子,分别有什么作用? Vue的生命周期是指组件从创建到销毁的过程。

beforeCreate:实例初始化之后,创建之前,此时组件内的data,methods都是不可访问的

Created:组件刚刚创建完,这是可以对数据进行操作,可以使用nextTick来操作dom

beforeMount:组件被挂载之前,当前dom已经挂载完毕,等待渲染

Mounted:组件挂载之后,当前节点已经完成双向绑定且DOM节点也已经渲染完毕且可以访问。

beforeUpdate:组件更新之前。

Updated:组件已经更新,避免在此时更改数据。

beforeDestroy:实例被销毁之前调用。

Destroyed:实例被销毁之后。对应的Vue实例左右指令被解绑,事件监听器被移除,子实例也被销毁。

  1. Vue之间如何实现组件之间的通信 父子组件:props emit

任意组件:eventBus Vuex

eventBus 
var eventBus = new Vue();
eventBus.$emit()
eventBus.$on()
  1. Vue的数据响应式是做什么的? 当JavaScript对象传入Vue实例作为data选项时,Vue将遍历此对象所有property,并使用Object.defineProperty将所有property全部转化为getter/setter。当访问对象属性时会执行getter函数,当修改对象属性时会修改setter属性。

  2. Vue.set是做什么的? Vue.set是解决无法检测到普通新增property,从而导致页面无法显示适时数据的问题。当实例进行数据绑定之后再添加新的属性,便不是响应式,会导致数据变化,页面不变的情况。这是使用Vue.set方法来进行双向绑定。

  3. Vuex怎么用? Vuex是一个专门为vue.js应用程序开发的状态管理模式。

主要包含应用:

state:存放数据

getter:是store的计算属性,getter的返回值会根据它的依赖被缓存起来,只有当依赖值改变才会重新计算。

mutation:提交mutation更改store的唯一方法,类似于事件。可以传入额外的参数(载荷:payload)

action:类似于mutation。但action提交的是mutation,而不是直接变更状态,通过提交mutation来改变store。action可以包含任意异步操作。

module:将store分割成模块,每个模块都有state,getter,mutation,action。

  1. Vue Router怎么用? VueRouter是路由管理器。

实现原理:通过router-link router-view来实现的,当我们在使用vue.use(router)时,vue-router已经注册了router-link router-view组件了。

动态路由匹配:使用动态路由参数来达到一个组件下,显示不同的用户。匹配到路由是,参数值会被设置到this.$route.params,可以在每个组件中访问。

重定向:当路由匹配成功时显示其下的子路由视同就可以使用到重定向或者空路由。用redirect。

别名:alias

history:路由模式

路由懒加载:将不同路由对用的组建分割成不同的代码块,然后当路由被访问时才加载对应的组件,这样会更加高效。const foo = () => import('./Foo.vue')

  1. Vue的路由模式 hash:默认模式,当url改变时,页面不会重新加载。url中永远带着#号,当要考虑到url规范就要使用此模式。

history:url跳转(跳转和后退)无需重新加载。在二级页面时刷新页面,会出现404错误。

  1. 路由守卫 路由守卫跳转过程中一系列的钩子函数,当路由准备跳转会执行这些钩子函数,我们可以在这些好钩子函数连做我们需要做的事情。

【1】全局守卫:是指路由实例上直接操作的钩子函数,特点是所有路由配置的组件都会触发,直白点就是触发路由就会触发这些钩子函数beforeEach(to,from, next) beforeResolve(to,from, next) afterEach(to,from)

【2】路由守卫: 是指在单个路由配置的时候也可以设置的钩子函数beforeEnter(to,from, next)

【3】组件守卫:是指在组件内执行的钩子函数,类似于组件内的生命周期,相当于为配置路由的组件添加的生命周期钩子函数。beforeRouteEnter(to,from, next) beforeRouteUpdate(to,from, next) beforeRouteLeave(to,from, next)

beforeEach、beforeLeave不会应用在跳转路由上,而会应用到目标路由上。

  1. TS比JS有什么优点?

TS是JS的超集,TS对类型的约束,因此更加可控以及更加容易维护和重构,更利于团队开发。

  1. 什么是XSS,如何预防? XSS是跨站脚本漏洞,恶意用户通过XSS将代码诸如页面中,使正常用户浏览的信息遭到篡改。可通过对用户提交的信息进行转码及过滤来进行预防。

  2. 什么是CSRF,如何防御? CSRF是跨站请求伪造,恶意用户通过欺骗浏览器去访问一个曾经认证过的网站,由于浏览器曾经认证过,所以认为是正常用户进行操作。可以检查refer字段以及添加校验token来进行预防。

  3. v-model实现原理

v-model是绑定数据value和触发input事件的语法糖

  1. JS原型链 js对象都有原型,每个对象的__proto__是它指向了构造它的对象的原型地址,而构造它的对象也有原型,这就构成了原型链。

  2. 什么是数据可视化? 借助图形的展示,清晰明了的向用户展示数据信息,便于用户认知相较于文字更加直观。

  3. Vue中 for循环的key有什么作用? key是用来精准高效更新DOM的,key相当于与星环的DOM绑定在一起,如果key发生变化相对应的DOM也会发生变化,直接更新就行,不用全部更新一遍。但是并不建议用index来作为key,会出现服用的问题。

  4. 为什么Vue data是一个函数 一个组件被复用多次其本身就是一个构造函数,data里面的数据会放到一个内存地址中,当数据变化时,data中的数据也会发生变化,为了保证不被影响,data要是一个函数

  5. babel-loader有什么作用? babel可以将我们使用的js较新的语法或未来语法转换成老的语法。

  6. 除了webpack用过哪些构建工具? parcel 比较适合简单的项目,rollup 比较适合 vue react ,webpack 比较适合大型的项目,vite是vue.js 官方出的构建工具,目前用这个比较多,速度要比 webpack 快,但是生态没有 webpack好。

  7. 有哪些常见的Loader?他们解决什么问题? file-loader:把文件输入文件夹中,在代码中通过相对路径引用文件夹文件 image-loader:对图片文件进新家在并压缩 babel-loader:对js或者ts语法进行转换es5的语法 css-loader:对css文件进行加载,支持模块化 style-loader:把css代码注入到js中通过dom操作去加载css

  8. 常见的Plugin他们是解决什么问题的? htmlwebpackplugin:用于最终创建HTML文件可以自动生成可可以创建模板创建。 MiniCssExtractPlugin:用来分割css chunk包 optimizeCssAssetsWebpackPlugin:压缩css代码

  9. 如何提高webpack的构建速度 减少打包文件体积,使用happypack,开启多线程操作

  10. 性能优化 加载优化:针对js css进行压缩,减少其他文件体积,服务店开启gzip,开启CDN,服务器开启缓存,对模块化进行按需加载。 渲染优化:针对DOM操作进行优化,尽量避免操作大面积的dom,更新的呃逆荣要少。 滚动优化 针对资源进行懒加载,比图图片,使用节流或者防抖来控制请求数量。 动画优化 使用 transform translate 来让gpu渲染页面,尽量不要使用js sitetimeout 来制作动画。

  11. 判断是否为数组的方式

array.isarray,instanceof,数组的 constructor

  1. DOM执行捕获或者冒泡是先捕获还是先冒泡,如何组织捕获和冒泡

按照 w3c 标准是先执行捕获在执行冒泡的,可以使用 stopPropagation 来阻止冒泡,或者捕获。

  1. 什么是 mvvm

    mvvm 是 model-view-viewmodel 的缩写,也就是将mvc的 controller 演变成了 viewmodel,view 代表视图UI组件

  2. vue2 如何监测数组的变化

    使用了函数劫持的方式,vue2 对 data 里的数组重写了原型链,指定了自己定义的数组原型方法,当调用数组api时,可以通知依赖更新,如果数组包含引用类型的话会对数组引用的类型进行遍历监控,这样就实现了对数组变化的监控

  3. 什么是虚拟dom

    虚拟 dom 就是使用 js 去模拟我们的 dom 结构

  4. object.assign() 是深拷贝还是浅拷贝

    当拷贝对象为一层对象则为深拷贝,多层对象为浅拷贝。

  5. 什么是防抖什么是节流

    防抖是就在规定时间内不管执行多少次都就只执行最后一次,

    节流就是每隔一段时间执行一次

  6. v-for v-if 为什么不可以一起用

    v-for 比 v-if 优先级要高,如果需要使用的话 每次v-for 都会执行 v-if 造成不必要的计算,影响性能。

    解决方法,可以再 template 标签上进行循环,子标签上用 v-if

  7. array.forEach() 如何跳出

    可以使用 throw error 的方式来中断循环

  8. 宏任务和微任务

    微任务执行要比宏任务早

    宏任务 settimeout,setinterval,dom,ajax 请求

    微任务 promise,async/await

    因为微任务和宏任务之间隔了一个DOM的渲染,微任务会在DOM渲染之前进行,宏任务会在DOM渲染之后进行。

  9. 父子组件的生命周期是什么

    • 父组件 beforeCreate

    • 父组件 created

    • 父组件 beforeMount

      • 子组件 beforeCreate
      • 子组件 Created
      • 子组件 beforeMount
      • 子组件 mounted
    • 父组件 mounted

    • 父组件 beforeUpdate
      • 子组件 beforeUpdate
      • 子组件 updated
    • 父组件 updated