【面试】前端面试题整理

文章目录


一、HTML相关面试题

1. 如何理解HTML语义化?

HTML语义化可以提高代码可读性,维护起来更加方便;
还有利于SEO(搜索引擎优化)。

2. 块元素和内联元素

块元素:独占一行,div,h1-h6,p,table,ul,ol等都属于块元素;
内联元素:不独占一行,span,img,input,button等;

二、CSS相关面试题

1.盒模型宽度的计算

2 * border + 2 * padding + width

2.margin纵向重叠问题

相邻元素的margin-bottom和margin-top会发生重叠,以数值大的为准,空白内容的标签也会重叠.

3.margin的负值问题

margin-top设置负值,元素会向上移动;
margin-left设置负值,元素会向左移动;
margin-right设置负值,右侧元素左移,自身不受影响;
margin-bottom设置负值,下方元素上移,自身不受影响。

4.BFC的理解和应用

BFC(block format context),块级格式化上下文,一块独立的渲染区域,内部元素的渲染不会影响到边界以外的元素.
形成BFC的条件:
1.float不是none;
2.position是absolute或fixed;
3.overflow不是visible;
4.display是flex,inline-block等。
BFC一般应用于清除浮动

5.如何实现双飞翼布局和圣杯布局,这俩布局的目的是什么?

目的: 三栏布局,中间一栏最先加载和渲染(内容最重要),两侧内容固定,中间内容随着宽度自适应,一般用于PC网页。
共同点:都是使用float布局,两侧使用margin负值,以便和中间内容横向重叠,防止中间内容被两侧覆盖,一个使用padding,一个使用margin。

6.absolute和relative分别依据什么定位?

relative依据自身定位;
absolute依据距离自己最近的且有定位的元素来定位。

7.垂直居中对齐的实现方式

行内元素且知道高度:text-align:center;line-height:自身的高度;
块元素:
1.flex布局实现水平垂直居中;
2.定位+top:50%+left:50%+transform:translate(-50%, -50%)

8.line-height如何继承?

如果写具体数值,比如50px,那么直接继承该数值;
写比例,比如2/1.5,那么继承该比例;
写百分比,如200%,则继承计算出来的值(和父元素的font-size相乘的值)。

三、js面试题

1.typeof能判断哪些类型?

typeof可以判断出基本类型的值:string,number,boolean,undefined,symbol;
typeof判断引用类型和null返回的都是‘object’;
typeof判断函数返回‘function’。

2.手写js深拷贝

// 准备数据
const obj = {
  name: "zhangsan",
  age: 22,
  address: "xian",
  phone: {
    mobile: "11111111111",
    mobile1: "22222222222",
  },
};

// 声明函数
const deepClone = (obj) => {
  // 如果obj是基础类型的数据,那么就不存在深拷贝,直接返回就行
  if (typeof obj !== "object" || obj == null) {
    return obj;
  }

  // 判断obj是数组还是对象,并声明一个res变量并接收结果
  let res = obj instanceof Array ? [] : {};

  // 遍历原对象
  for (let key in obj) {
    // 通过hasOwnProperty来判断对象中的key是否属于该对象本身的属性
    if (obj.hasOwnProperty(key)) {
      // 通过递归,将值赋值给res的key
      res[key] = deepClone(obj[key]);
    }
  }
  // 返回res,实现深拷贝
  return res;
};

const obj1 = deepClone(obj);
obj.phone.mobile = "lisi";
console.log("obj: ", obj);
console.log("obj1: ", obj1);

3.如何准确判断一个变量是不是数组

1.Array.isArray(xx)方法
2.xx instanceof Array

4.如何理解原型和原型链

为了方便区分,这里把prototype称为显式原型,__proto__称为隐式原型;
原型:每个构造函数都有显式原型(prototype),通过这个构造函数构造出的实例会有一个隐式原型(proto),实例的隐式原型指向的就是构造出它的函数的显式原型。
原型链:构造函数的显式原型也有显式原型,这样从实例到构造函数的显式原型再到显式原型的显式原型,就形成一个链条,这就是原型链。
当在实例中查找属性和方法时,如果该实例中没找到,那么就会顺着原型链去一层层查找,这就是基于原型链的属性和方法的查找规则。

4.this的不同应用场景,如何取值

1.当作普通函数被调用,this指向的是window;
2.使用call,apply,bind方法,指向的是绑定的对象;
3.作为对象方法被调用,指向的是该对象;
4.在class中调用,this指向的是实例本身;
5.在箭头函数中调用,指向的永远是它上级作用域中的this。

5.闭包的应用

1.隐藏数据
2.做一个简单的cache工具

const createCache = () => {
  // 闭包中的数据,不会被外部访问到
  const data = {};

  // 只提供api供外部使用
  return {
    set: (key, val) => {
      data[key] = val;
    },

    get: (key) => {
      return data[key];
    },
  };
};

const c = createCache();
c.set("a", 100);
console.log(c.get("a")); // 100

6.同步和异步的区别是什么?

同步会阻塞代码的运行,异步则不会

7.前端异步的应用场景

网络请求,定时任务

8.描述event loop机制

同步代码执行的过程中,如果碰到异步代码,会将异步代码挂起,继续执行同步代码
当同步代码执行完毕之后,就会触发event loop 事件轮询机制,但在event loop生效之前,如果dom结构发生了变化,都会重新渲染dom,然后它会去查看挂起的异步代码中是否有执行完毕的,如果有,就会去执行

9.什么是宏任务和微任务,两者区别

宏任务:setTimeout,setInterval,Ajax,DOM事件
微任务:Promise,async/await
微任务执行时机比宏任务更早,微任务是在dom渲染之前触发,宏任务是在dom渲染之后触发

10.promise的三种状态

三种状态: pending resolve rejected
状态的表现:pending状态,不会触发then和catch;resolve状态,会触发then;rejected状态,会触发catch。
then和catch改变状态:then和catch正常都会返回resolved,里边有报错则返回rejected;

四、DOM,BOM操作相关面试题

1.DOM是哪种数据结构

DOM是一种树形的数据结构

2.DOM操作常用API

DOM元素操作

3.property和attribute的区别

property修改对象属性,不会体现在html结构中;
attribute修改html属性,会改变html结构;
两者都有可能引起DOM重新渲染。

4.一次性插入多个节点,考虑性能

可以使用createDocumentFragment方法,创建一个代码片段,这时这个代码片段还没有插入DOM树中,然后把节点都插入到这个代码片段里,最后再把这个代码片段插入到dom树中.

五、HTTP相关面试题

1.从输入url到浏览器渲染出页面的过程

1.输入url之后,首先开始查找本地缓存,如果有,就直接返回,否则就开始DNS解析
2.通过DNS解析拿到IP地址,如果是HTTPS协议,就会建立tls连接,如果是http协议,就会建立tcp连接,进行三次握手
3.利用IP地址和服务器建立连接之后,向服务器发起请求
4.服务器收到请求信息后,会根据请求信息生成响应行,响应头,响应体并发给网络进程,网络进程开始解析响应头的内容
5.如果响应头中有301,302等状态码,那么网络进程就会从location字段中读取地址并重新发起请求
6.导航会根据content-type这个字段来判断响应体数据的类型,浏览器通过这个来判断如何显示响应体的内容
这时浏览器开始准备渲染页面:
1.准备渲染进程,渲染进程一般一个页面一个,如果同一站点(协议+根域名相同),就会复用
2.提交文档,浏览器开始渲染
3.先构建DOM树,然后将css文件变成cssom树,根据这两棵树生成渲染树,开始布局渲染

六、VUE相关面试题

1.v-show和v-if的区别

v-show相当于加了display:none样式,但dom元素依旧存在于DOM树中,一般用于频繁的隐藏或显示中
v-if则是将这个元素从DOM树中彻底移除掉,一般用于不频繁的隐藏或显示中

2.为何在v-for中使用key

diff算法中通过tag和key来判断,是否是sameNode,这样可以减少渲染次数,提升渲染性能

3.描述vue组件生命周期(父子组件)

挂载阶段:父组件beforeCreate,created,beforeMount,子组件beforeCreate,cerated,beforeMount,mounted,父组件mounted。
更新阶段:父组件beforeUpdate,子组件beforeUpdate,updated,父组件updated.
销毁阶段:父组件beforeDestory,子组件beforeDestory,destoryed,父组件destoryed.

4.vue组件常见的通讯方式

父传子(props),子传父(emit),兄弟传值(eventBus),vuex,路由传参等

5.描述组件渲染和更新的过程

解析template模板生成render函数,如果模板中没有胡子语法(Mustache,双大括号),那么直接生成vnode并渲染。如果模板中有胡子语法,那么就会触发响应式,watcher会监听触发了哪个getter,然后生成一个vnode并渲染出来。当修改这个getter的时候,会重新生成render函数,并生成一个新的vnode,然后通过pach函数和旧的vnode去对比后渲染出来。

6.双向数据绑定v-model的实现原理

input元素的value = this.name
绑定input事件,this.name = $event.target.value
当触发input事件时,data会更新,触发re-render。

7.对MVVM的理解

MVVM分为model,view,viewModel
model相当于vue中的data,数据一般都在model层中定义
view代表ui视图,负责展示数据
viewModel负责监听model中数据的改变并控制视图的更新,处理用户交互操作
model和view并无直接关联,而是通过viewModel来进行联系的,model和viewModel之间有双向数据绑定的联系,因此当model中的数据改变时会触发view层的刷新,view层中由于用户交互操作而改变的数据也会在model中同步
这种模式实现了model和view的数据自动同步,因此开发者只需要专注对数据的维护操作,不需要自己操作dom

8.computed有何特点

缓存,data不变的话不会重新计算,可以提高性能

9.为何组件data必须是一个函数

如果data不是一个函数,那么所有实例的data中的数据就是公共的,会互相影响.但data是函数就不一样了,data中的数据会形成一个闭包,生成的实例中的data都在闭包中,不会互相影响

10.ajax请求应该放在哪个生命周期中

mounted中,因为js是单线程的,必须等页面渲染完成后才会去执行异步操作获取数据,而created只是数据初始化完成了,并没有开始渲染,所以放在created中没有任何意义,它还是会等mounted钩子执行完毕页面渲染完成后才会异步获取数据。所以放在mounted中比较合适并且逻辑看起来更加清晰。

11.如何将组件所有的props传递给子组件

可以使用$props

12.何时使用keep-alive

缓存组件,不需要重复渲染
多个静态tab页的切换
优化性能

13.何时需要使用beforeDestory

解绑自定义事件
清除定时器
解绑自定义的DOM事件,如window scroll等

14.vuex中action和mutation有何区别

action中处理异步,mutation中不可以
mutation做原子操作
action可以整合多个mutation

15.使用vnode描述一个DOM结构

// dom结构
<div id="div1" class="container">

  <p>vdom</p>

  <ul style="font-size: 20px;">

    <li>a</li>

  </ul>

</div>

// vnode
{
  tag: "div",
  props: {
    className: "container",
    id: "div1",
  },
  children: [
    {
      tag: "p",
      children: "vdom",
    },
    {
      tag: "ul",
      props: { style: "font-size:20px" },
      children: [
        {
          tag: "li",
          children: "a",
        },
        // ...
      ],
    },
  ],
};

16.监听data变化的核心api是什么

object.defineProperty
缺点:
1.深度监听需要使用递归,导致计算量特别大;
2.这个api不能监听新增和删除,所以vue有了$set和$delete

17.vue如何监听数组变化

object.defineProperty不能监听数组变化,因此只能重新定义原型,重写push pop等方法,实现监听

18.描述响应式原理

通过object.defineProperty来监听数据,当取值或修改属性的值时,会触发数据的getter和setter,getter和setter方法内可以触发视图的更新,从而实现响应式

19.diff算法的时间复杂度

O(n)
在O(n^3)基础上做了优化,优化完成后时间复杂度就变为O(n):
1.只比较同意层级,不跨级比较
2.tag不相同,则直接删掉重建,不再深度比较
3.tag和key相同,则认为是相同节点,不再深度比较

20.vue为何是异步渲染,$nextTick有什么用

异步渲染可以提高渲染性能
$nextTick在DOM更新完之后,触发回调

21.vue常见性能优化方式

1.合理使用v-show和v-if
2.合理使用computed
3.v-for加key,避免和v-if同时使用
4.自定义事件,DOM事件及时销毁
5.合理使用异步组件
6.合理使用keep-alive
7.data层级不要太深

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值