前端面试题【总结篇】持续更新中....

1.用css编写一个宽高浏览器一半的正方形

答:设置视口width(宽度)为50vw  高度为50vw

vw 表示视口宽度的 1/100。例如,100vw 表示占据整个视口的宽度。

vh 表示视口高度的 1/100。例如,100vh 表示占据整个视口的高度。

      .half-square {
            width: 50vw;
            height: 50vw;
            /* padding-bottom: 50vh; */
            background-color: blue;
          }

2.说说MVC的认识

答:MVC 是一种软件设计模式,即M模型(Model) - V视图(View) - C控制器(Controller)。

模型(Model):用于负责处理数据和业务逻辑,跟数据库进行交互处理数据的储存,检索,更新和验证

视图(View):主要负责数据的展示,把模型中的数据以用户可见的形式展示出来,比如网页、界面等。视图通常只关注数据的展示形式,不包含业务逻辑。

控制器(Controller):控制器用于接收请求,校验参数,调用 Model 层获取业务数据,构造和绑定上下文,并转给 View 层去渲染

3.说说MVVM框架

  • M:模型(Model) :对应 data 中的数据

  • V:视图(View) :模板

  • VM:视图模型(ViewModel) : Vue 实例对象

  • 模型(Model):代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。数据保存—存放着各种数据,有的是固定写死的,大多数是从后端返回的数据
    视图 (View):代表UI 组件,它负责将数据模型转化成UI 展现出来,用户界面,也就是DOM

  • 视图模型(View-Model):监听数据模型的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和Model的对象,连接Model和View。

4.MVVM和MVC的区别?

都是一种设计思想
MVC后台用的多,MVC是Model-view-Controller的简写,即模型-视图-控制器。
MVC的目的就是将M和V的代码分离
MVC是单向通信,也就是View和Model,必须通过controller来承上启下。
MVVM实现了View和Model的自动同步,当Model的属性改变时,不用再自己手动操作DOM元素,提高了页面渲染性能。

5.input和change的区别

input和change都是JavaScript中用于处理表单元素事件的关键词,它们的区别在于:

  1. input:这个事件触发于用户改变输入字段的内容,无论该变化是由键入、剪切板粘贴还是通过其他方式引起的。它会在内容发生变化时立即触发,通常用于实时获取用户的输入值。

  2. change:相比之下,change事件更为谨慎,它只在用户完成输入并离开相关的表单元素(如文本框、下拉列表等)时才会触发。也就是说,只有当用户点击了“确定”按钮或者失去了对焦点(例如按下Enter键),change事件才会被激活。

6.说说闭包的理解

闭包是一个函数加上到创建函数的作用域的连接,闭包“关闭”了函数的自由变量
自由变量(在函数内部引用了一个不在该函数作用域内定义的变量)

2. 闭包可以解决什么问题【闭包的优点】
	2.1 内部函数可以访问到外部函数的局部变量
	2.2 闭包可以解决的问题
	var lis = document.getElementsByTagName('li');
      for(var i=0;i<lis.length;i++){
        (function(i){
          lis[i].onclick = function(){
            alert(i);
          }
        })(i)
      }
3. 闭包的缺点
	3.1 变量会驻留在内存中,造成内存损耗问题。
				解决:把闭包的函数设置为null
    3.2 内存泄漏【ie】 ==> 可说可不说,如果说一定要提到ie

7.vue2组件中数据更新视图没有更新如何解决?

方案1:静默刷新(使用v-if的特性)

在修改值之后将元素销毁,然后在修改后的下一次DOM渲染完成时再显示出来,这样就会触发组件重新加载data的数据进行渲染,data中被修改的数据才是最新的。

change(){
    this.info = {b:99}
    this.show = false
    this.$nextTick(()=>{
        this.show = true
    })
}

方案2:Vue.$set(官方推荐)

使用这个api修改的数据会为其添加响应式getter和setter让其拥有数据响应的特性,vm.$set(要操作的对象或数组, 要新增或者修改的数组或对象key, 对应的值)

方案3:可以使用 this.$forceUpdate 方法强制更新视图(影响性能)

updateName(){
    this.userInfo.name='小红'//在此时,确实已经将userInfo对象修改完成
    console.log(this.userInfo.name);//输出结果: 小红
    this.$forceUpdate();//在这里,强制刷新之后,页面的结果变为'小红'
  }

方案4:使用变异方法:对于数组的操作,尽量使用 Vue 能够监测到的变异方法,如 push、pop、shift、unshift、splice、sort、reverse 等。如果需要使用其他方法,可以考虑使用新数组替换原数组。

8.输入url地址栏都做了什么?

  1. 浏览器获取您输入的网址

    • 浏览器会检测输入的内容是否符合有效的 URL 格式。
  2. 进行域名解析

    • 如果输入的是域名(例如:www.example.com),浏览器会向 DNS(域名系统)服务器发送请求,以获取该域名对应的 IP 地址。
  3. 建立 TCP 连接

    • 使用获取到的 IP 地址,浏览器尝试与服务器建立 TCP(传输控制协议)连接。
  4. 发送 HTTP 请求

    • 连接建立成功后,浏览器会向服务器发送 HTTP(超文本传输协议)请求,请求中包含了您想要访问的具体页面路径、请求方法(如 GET、POST 等)、以及一些头部信息(如浏览器类型、语言偏好等)。
  5. 服务器处理请求

    • 服务器接收到请求后,根据请求的内容进行处理,例如从数据库中获取数据、执行相应的脚本等。
  6. 服务器响应

    • 服务器处理完请求后,会向浏览器发送 HTTP 响应,响应包含了状态码(如 200 表示成功、404 表示未找到等)、响应头(如内容类型、长度等)以及响应体(即您请求的网页内容)。
  7. 浏览器解析和渲染页面

    • 浏览器接收到响应后,会根据响应的内容进行解析。如果是 HTML 页面,会构建 DOM 树、计算样式、进行布局和绘制,最终将页面呈现给用户。
  8. 加载资源

    • 在解析 HTML 页面的过程中,如果遇到需要加载的其他资源(如 CSS 文件、JavaScript 文件、图片等),浏览器会再次发起请求获取这些资源,并进行相应的处理和渲染。

9.vue2对比vue3都做了哪些优化

  1. 响应式系统:Vue3 使用 Proxy 替代 Object.defineProperty 来实现响应式,Proxy 可以直接监听对象的属性变化,并且支持对数组、Set、Map 等数据结构的监听,还可以监听到新增和删除属性。而在 Vue2 中,需要使用 Vue.set 或 $set 来实现对新增属性的监听。
  2. 编译优化
    • 静态提升:Vue3 在编译阶段会将一些静态的节点或属性提升到渲染函数之外,避免了在每次渲染时都重新创建这些节点或属性,从而提高了渲染性能。在 Vue2 中,无论节点是否参与更新,都会重新创建再渲染。
    • PatchFlag:Vue3 在编译阶段会为动态节点添加 PatchFlag,在 diff 算法中,只会比较有 PatchFlag 的节点,从而减少了不必要的比较操作,提高了 diff 算法的效率。而 Vue2 是进行全量的对比,在运行时会对所有节点生成一个虚拟节点树,当页面数据发生变化时,会遍历判断 virtual dom 所有节点(包括一些不会变化的节点)有没有发生变化。
    • 静态属性提升:Vue3 还对组件选项进行了优化,将静态属性提升到渲染函数外部,避免了每次渲染都重新创建这些属性的开销。
  3. 代码结构:Vue3 采用了组合式 API(Composition API),将组件的逻辑拆分成多个函数,使得代码更加清晰和易于维护。而 Vue2 则是Options API,将组件的逻辑写在一个对象中,代码结构相对较为混乱。
  4. 类型支持:Vue3 基于 TypeScript 进行重构,提供了更好的类型推导和类型检查,使得代码更加健壮和易于维护。而 Vue2 则是基于 JavaScript 的,类型检查相对较弱。
  5. 体积优化:Vue3 对核心库进行了重构,删除了一些不常用的功能,使得整个库的体积更小。同时,Vue3 还支持 Tree-Shaking,可以将没有使用到的模块进行摇树优化,进一步减小了代码体积。
  6. 性能优化
    • 事件侦听器缓存:Vue3 使用了更高效的事件处理机制,将事件处理函数缓存起来,避免了每次渲染都重新创建事件处理函数的开销。
    • 数据追踪的改进:Vue3 对数据追踪机制进行了改进,使得只有被依赖的数据发生变化时,相关的更新才会被触发,减少了不必要的更新操作。
    • 组件级别的异步更新:Vue3 允许在组件级别设置异步更新,只对需要更新的组件进行渲染,避免了全局更新的开销。
    • 列表渲染的优化:Vue3 为列表渲染引入了新的动态更新策略,只会对发生变化的列表项进行更新,而不是重新渲染整个列表。

10.链式调用的理解

链式调用是一种编程中的方法调用风格,通过在一个方法调用的返回值上紧接着调用另一个方法,形成一个连续的调用链

优点:

  1. 提高代码的可读性和简洁性,使得一系列相关的操作可以以一种连贯和直观的方式表达。
  2. 减少中间变量的使用,避免了为每个中间结果创建新的变量,从而使代码更加紧凑。
  3. 例如,在 JavaScript 中,如果一个对象的方法返回 this(即对象本身),就可以实现链式调用。
class MyClass {
  value = 0;

  increment() {
    this.value++;
    return this;
  }

  multiplyBy(n) {
    this.value *= n;
    return this;
  }
}

const obj = new MyClass();

// 链式调用
obj.increment().multiplyBy(2);

console.log(obj.value); 
//在上述示例中,increment 和 multiplyBy 方法返回了对象本身,从而支持了链式调用。

11.链式调用的题型

    //根据data中的数据根据 groupld字段分组输出,过滤null 和没有分组的id数据 
    var data = [{groupld: "new",userld:2}, null, null, {groupld: "top",userld:2}, {userld:'2'}, {groupld:"new", userld:2}, {groupld: "new", userld:5}]

    let obj =  data.filter(item=> item && item.userld && item.groupld).reduce((pre,cur)=>{
       if(!pre[cur.groupld]){
            pre[cur.groupld] = []
       }
        pre[cur.groupld].push(cur)
        return pre
    },{})

    console.log(obj);
    var obj2 = Object.keys(obj).reduce((pre,cur)=>{
        // console.log(obj[cur],'----');
        if(!pre[cur]){
            pre[cur] = []
            // console.log( pre[cur],'----');
        }
        console.log(obj[cur],'----');

        obj[cur].map(e => {
            if(!pre[cur].includes(e.userld)){
                pre[cur].push(e.userld) 
            }
            
        })
        
        return pre
    },{})
    console.log(obj2);

12.如何做移动端适配?

rem的概念

rem 是移动端适配单位,是用来写移动端布局的

1rem 的大小就是1个 html 设置的 font-size 的大小(未设置情况下默认是1rem等于16px)


// 封装一个根据屏幕尺寸自动改变html的font-size大小的函数
function rem() {
  //  获取html的宽度
  let htmlW = document.documentElement.clientWidth;
  // 获取body的宽度
  let bodyW = document.body.clientWidth;
  // 兼容处理
  let W = htmlW || bodyW;
  // 设置html的font-size大小
  // 因为设计图尺寸是750,所以平分,这样*100之后,1rem就等于100px;
  document.documentElement.style.fontSize = (W / 750 * 100) + 'px';
}
 
// 定义屏幕宽度改变时触发
window.onresize = function () {
  rem()
}
 
// 设置初始触发一次
rem()

13.清除浮动有哪些方式?

1. 触发BFC

2. 多创建一个盒子,添加样式:clear: both;

3. after方式

 ul:after{

      content: '';

      display: block;

      clear: both;

}

14.延迟加载JS有哪些方式?

延迟加载:async、defer

例如:<script defer type="text/javascript" src='script.js'></script>

defer : 等html全部解析完成,才会执行js代码,顺次执行js脚本。

async : async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)。

  1. defer 属性:在 <script> 标签中添加 defer 属性,浏览器会在解析完 HTML 文档后再执行脚本。
<script defer src="script.js"></script>
  1. async 属性:使用 async 属性,脚本一旦下载完成就会立即执行,不会阻塞文档的解析,但执行顺序不一定。
<script async src="script.js"></script>
  1. 动态创建 script 元素:通过 JavaScript 代码在页面加载完成后动态创建 script 元素并添加到页面中,从而实现延迟加载。
function loadScript(url) {
  var script = document.createElement('script');
  script.src = url;
  document.head.appendChild(script);

15.JS微任务和宏任务

1. js是单线程的语言。

2. js代码执行流程:同步执行完==》事件循环

      同步的任务都执行完了,才会执行事件循环的内容

      进入事件循环:请求、定时器、事件....

3. 事件循环中包含:【微任务、宏任务】

微任务:promise.then

宏任务:setTimeout..

要执行宏任务的前提是清空了所有的微任务

流程:同步任务执行完毕==》事件循环(任务队列)【微任务和宏任务】==》微任务==》宏任务=》微任务...

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值