常见的前端面试题

800 阅读7分钟

前言

写博客主要是用来总结、巩固知识点,加深自己对这个知识点的理解。同时希望能帮助到有需要的人。如有不正确的地方。可以在评论区指出。你们的支持。是我不断进步的源泉。

金三银四跳槽季,我相信很多人应该都在看新的机会吧(其实就只有我了)。把一些常见的自认为比较经典的面试题在这里做个梳理。同时也给再给找工作的小伙伴们一个参考。

1.vue的生命周期

我们先看张图

alt

这是vue官方文档里的生命周期图,我结合这张图来说下我的理解 vue的生命周期一共分为8个阶段。

1.beforeCreated阶段此时是获取不到props,data里的任何数据,因为此时数据还未初始化 created阶段可以访问之前访问不到的数据,但此时组件还没有挂载,所以el是访问不到的。

2.beforeMounted阶段开始执行render函数,el和data数据开始执行。但此时还是挂载在虚拟dom上 到了mounted阶段才开始挂载到实际的dom上。此时我们可以进行ajax请求了。

3.beforeUpdated和updated分别是在数据更新的时候调用

4.最后就是销毁组件的钩子函数 beforeDestroy 和 destroyed。前者适合移除事件、定时器等等,否则可能会引起内存泄露的问题。然后进行一系列的销毁操作,如果有子组件的话,也会递归销毁子组件,所有子组件都销毁完毕后才会执行根组件的 destroyed 钩子函数。

2.什么是宏任务、微任务以及它们之间的区别

由于技术深入程度有限,我只能简单的说下我对宏任务微任务的理解:

js是单线程执行的,所以在队列中会优先执行宏任务,但是如果宏任务里面还有微任务的话,会优先把微任务执行完再去执行下一个宏任务。具体看这里

3.webpack和gulp的区别

Gulp 的定位是 Task Runner, 就是用来跑一个一个任务的

我们可以通过gulp配置task来编译sass,less。进行图片压缩,代码压缩等。但是gulp不能解决js模块的问题。这时候webpack就出现了。webpack可以把css,js。图片等都打包成一个bundle。所以webpack也叫file bundler

同时webpack为了解决require不同的文件。引入了核心之一的loader 我们可以通过sass-loader把sass编译成css。 通过babel-loader可以把es6等转换成浏览器识别的es5等。

webpack的核心就是entry,output,loader,puglin。

4.前端路由有那几种方式

有hash,history两种。 hash模式主要是通过hashchange来实现 history模式主要是通过pushstate和popstate方法。

5.浏览器的渲染过程

1.用户输入url

2.浏览器对输入的url进行DNS解析

3.建立TCP连接(三次握手)

4.浏览器发起http请求

5.服务器响应http请求

6.销毁TCP连接(四次挥手)

7.浏览器通过渲染引擎进行页面渲染。

6.for in 和 for of 的区别

for in 在数组和对象中的使用

//遍历数组
var array=[1,2,3,4,5];
for(let item in array ){
    console.log(item)   // 0 1 2 3 4
}

//遍历对象
var obj={
    name:'leo',
    age:26,
    job:'FED'
}
for(let item in obj){
    console.log(item) // name age job
}

for of 在数组和对象中的使用

//遍历数组
var array=[1,2,3,4,5];
for(let item of array ){
    console.log(item)   // 1 2 3 4 5
}

//遍历对象
var obj={
    name:'leo',
    age:26,
    job:'FED'
}
for(let item of obj){
    console.log(item) //  Error obj is not iterable
}

从上面可以看出:for in 用来遍历数组和对象的key或索引。for of用来遍历value。同时for of不能用来遍历普通对象需要搭配Object.keys()来使用。如下

var obj = {
    name: 'leo',
    age: 26,
    job: 'FED'
}
let objValue = Object.keys(obj);
for (let item of objValue) {
 console.log(obj[item])   // leo 26 FED
}

7.小程序中组件如何进行通信

小程序中的组件如何创建,这里就不详细说明了。请移步官方文档查看详细教程

我们主要来讨论下小程序中的组件如何进行通信

1.页面如何向自定义组件传递数据

//页面使用自定义组件
<online userList="{{list}}"></online>

//组件online.js
Component({
    properties:{
        userList:{
          type:Array,
          value:[],
         }
    }
})

这样自定义组件就能拿到页面的list数据了,怎么样是不是很简单。

2.自定义组件如何传递数据给页面

跟vue类似,组件间的数据交互主要是通过自定义事件。

自定义组件触发事件时,需要使用 triggerEvent 方法,指定事件名、detail对象和事件选项: 来直观的看代码:

<!-- 在自定义组件online中 -->
<button bindtap="onTap">点击这个按钮将触发myEvent事件</button>
Component({
    properties:{},
    methods:{
        onTap() {
          // detail对象,提供给事件监听函数 (需要带到主页面的数据放这里)
          const myEventDetail = {
            name:'leo',
            age:26
          } 
          //触发事件的选项
          //bubbles为事件是否冒泡 
          //composed 事件是否可以穿越组件边界,为false时,事件将只能在引用组件的节点树上触发,不进入其他任何组件内部
          //capturePhase 事件是否拥有捕获阶段
          const myEventOption = {
              "composed": true
          } 
          this.triggerEvent('myEvent', myEventDetail, myEventOption)
        }
    }
})

<!--在页面中监听自定义事件-->
<online bind:myEvent="getData"></online>
getData (eventDetail) {
    console.log(eventDetail)
    // detail 所有的子组件的数据,都通过该参数的detail属性暴露出来
}

3.兄弟组件之间如何进行数据通信

同样的兄弟组件之间的通信业可以通过自定义事件来解决。但是小程序中还为我们提供了另一种更轻巧的方法。可以通过relations属性来解决。 有如下组件

<online>
    <chat></chat>
</online>

两个组件捕获到对方组件的实例,是通过 this.getRelationNodes()方法。既然获取到了对方组件的实例,那么就可以访问到对方组件上的data, 也可以设置对方组件上的data, 但是不能调用对方组件上的方法。

<!--在online组件中-->
Component({
    relations:{
        './chat': {
            type: 'child',
            linked:function(target){  }  // target是组件online的实例,
            linkChanged: function(target){}
            unlinked: function(target){}
        }
    },
    methods:{
        test () {
            var nodes = this.getRelationNodes('./chat')
            var component_b = nodes[0];
            
            // 获取到b组件的数据
            console.log(component_b.data.name)
            // 需要调用对方组件的setData()方法来设置
            component_b.setData({
                name:'leo93'
            })
        }
    }
})

<!--在chat组件中-->
Component({
    relations:{
        './online':{
            type:'parent'
        }
    },
    data:{
        name:'leo'
    }
})

注意:必须在两个组件定义中都加入relations定义,否则不会生效。

本组件无法获取本组件的实例,使用this.getRelatonsNodes('./ path_to_self ') 会返回一个null

type 可以选择的 parent 、 child 、 ancestor 、 descendant

这里有篇文章把小程序的组件通信讲的很清楚

8.exports和module.exports,export和export default他们之间的区别

首先exports和module.exports 都是属于node模块里的

export和export default属于ES6模块里

exports 是属于module.exports的一个引用

export与export default均可用于导出常量、函数、文件、模块等

在一个文件或模块中,export、import可以有多个,export default仅有一个

通过export方式导出,在导入时要加{ },export default则不需要

export能直接导出变量表达式,export default不行。

9.微信中openId和unionId的区别

两者长度不一样

openId=28;

unionId=29;

openId同一用户同一应用中是唯一的

unionId同一用户在同一个微信公众平台的多个应用中是唯一的。

10.写出你所知道的所有让一个div元素垂直水平居中的方法

关于这个问题,可以看我的这篇文章

11.什么是原型,原型链

js中每当定义一个对象的时候,对象中都会包含一些预定义的属性,其中就包括prototype。prototype执行对象的原型。使用原型对象的好处是,所有对象的实列都包含他的属性和方法 原型链主要用来解决继承的问题。 每个对象都有一个原型对象,通过proto指针指向其原型对象,并从中继承方法和属性,同事原型对象也可能拥有原型,这样一层一层,最终指向null,这种关系被称为原型链。

持续更新中。。。

如有描述不当的地方,恳请指正。谢谢!