复盘最近的面试

这个礼拜一直在面试,想着看看能否拿到不错的offer前去实习,从周一到周四,面了将近10家,特整理此份面经,希望对春招的各位有所帮助

A公司

一面

面试官人很好,我回答的时候不会他会笑笑然后提醒我

自我介绍~

面试官简单问了下项目情况,也没继续深入~

js数据类型

接着又问了原始和引用类型的区别

let,const的区别

const之后的原始类型无法更改

js作用域

全局,函数,块级,eval欺骗词法~

针对小白的js作用域详细介绍 - 掘金 (juejin.cn)

谈谈作用域链

函数内访问变量是顺着作用域链查找的,从内往外,但是不能从外往内,这个链状是看函数的声明位置,声明在全局,就往全局找

es6的Promise

先答了Promise三种状态,pending,fulfilled,rejected,然后面试官问我状态可以逆转吗,不可逆,否则处理异步就不可靠了

Promise和async,await区别

Promise可以用.catch或者.then的第二个参数来捕获错误,async需要借助try,catch来捕获错误,async是通过Promise和generator打造的,generator相当于可以用next控制执行

ref和reactive区别

源码剖析ref和reactive的区别 - 掘金 (juejin.cn)

讲Proxy,依赖收集,依赖触发,类型判断,js对象的getter,setter~

如何调用父组件的函数

组件传参,通过事件或者props

场景题:给你一个类数组,就是key,value对这种,设计一个组件,通过vue去把这些数据渲染出来,不用考虑后端

聊了迭代类数组,父子组件传参,v-for,key

然后希望实现分页处理,每页数据只有10条

写两个点击函数,用计算属性实现,把数据弄成二维数组,如果是往具体页面增加数据就是将那页的数据提取出来进行操作

最后面试官跟我说是校友哈哈哈

二面

自我介绍+聊自己的掘金

diff算法

面试官直接拿我最近的文章问

详聊vue的diff算法 - 掘金 (juejin.cn)

聊项目,项目亮点

二叉树遍历

好久没刷算法题~

scss 复制代码
// 先序遍历
function preorder(root) {
    if(!root)  return     
    console.log(root.val) 
    preorder(root.left)
    preorder(root.right)
}
// 中序遍历
function minorder(root) {
    if(!root)  return  
    minorder(root.left)
    console.log(root.val) 
    minorder(root.right)
}
// 后序遍历
function backorder(root) {
    if(!root) return 
    backorder(root.left)
    backorder(root.right)
    console.log(root.val)
}

B公司

这家公司电话面......,很不喜欢电话面

解决异步的方式

回调,promise,generator,async,await,发布订阅......

vue数据更新,但是页面没有更新,你如何排查

考虑数据是否响应式、考虑数据更新在异步中,可以使用nextTick、也有可能数据被缓存了,考虑使用$set方法直接修改数据

使用vuex的注意点

vuex遵循单向数据流的原则,只能从state流向组件,修改state只能通过action或者mutation来修改,而不是直接拿到state进行修改,另外mutation是同步的操作,action可以包含异步操作,另外一般使用vuex是因为需要管理较大型的状态,对于简单的状态管理,建议直接父子,子父传参

介绍下vue3的生命周期

分为几个阶段,创建阶段,挂载阶段,更新阶段,销毁阶段,还有捕获错误的阶段。每个阶段都有对应的钩子函数去执行。然后问我一般用哪个钩子去发请求,我说用onMounted,因为有些数据拿到之后可能会操作dom

vue2和vue3响应式原理区别

  1. vue2是用得Object.defineProperty,vue3是用得Proxy,Proxy可以捕获更多类型的操作,更灵活
  2. vue3对ts的支持更友好,提供了更好的类型判断和错误提示

Object.defineProperty的局限性

不能监听数组的变化,不能监听新增属性和删除属性,defineProperty定义的属性不可以枚举,因此无法监听新增的属性或删除的属性,不能监听对象的深层属性,defineProperty性能开销很大,

会用浏览器去打断点调试吗

我说我用过,但是用得很少,都是用log去打印调试的,因为一般打包工具会自动把无关代码剔除掉

C公司

自我介绍~

你有封装过组件吗,讲讲

聊得过程中谈到了插槽,就问我了作用域插槽

作用域插槽用过吗

作用域插槽允许子组件向父组件传递数据,需要在子组件v-bind绑定对应的数据,父组件通过slot-scope属性来接收传递的数据

xml 复制代码
<!-- 子组件 -->
<template>
  <div>
    <slot :item="item"></slot>
  </div>
</template>

<!-- 父组件 -->
<template>
  <child-component>
    <template v-slot:default="slotProps">
      <p>{{ slotProps.item }}</p>
    </template>
  </child-component>
</template>

盒模型

js闭包

面试官:聊聊js闭包。来看这篇,小白也能读懂!(内含调用栈及作用域链的详细讲解) - 掘金 (juejin.cn)

js判断数据类型

深入认识js四大常用数据类型判断,一次性带你搞明白(内含面试热点)! - 掘金 (juejin.cn)

event-loop

先执行同步,再执行微任务队列,最后执行宏任务,执行一次宏任务之前会清空掉微任务队列

== 和 === 的区别

== 判断的是值,并且比较时会进行类型转换,=== 判断类型是否一致,这种比较更严格,防止类型转换

es6的新特性

let,const,解构,箭头函数,set,map,WeakSet,WeakMap,Reflect,Promise,generator,async......

vue2和vue3响应式

vue生命周期

这个面试官跟我说请求数据一般放在beforeCreated,因为onMounted得话,等dom加载完毕再去请求数据,会导致数据等待更长的时间才能展示

keep-alive

将组件缓存起来,像是页面固定的广告组件就可以用这个包裹,这样跳转路由时不需要重新渲染dom,并且还提供了两个钩子activated和deactivated,分别在缓存过的组件加载时和离开时触发

后面聊了聊项目难点,面试官自己介绍了公司的业务相关内容

D公司

自我介绍~

为什么选择前端

项目难点

session,cookie,localStorage的区别

三者都是web开发用于在客户端和浏览器端之间存储数据的机制,不过各有特点

存储:session存在服务器,cookie和localStorage存储在浏览器

生命周期:session与用户会话相关联,即用户打开浏览器和关闭浏览器的时间段,cookie可以设置过期时间,localStorage永久,除非显示删除

存储容量:session最大,cookie一般4Kb,用于存放登录令牌,localStorage一般5Mb

安全性:session安全性最高,因为存储在服务端,客户端无法直接访问,cookie和localStorage容易受到XSS和CSRF等安全攻击

总得来说,session适合存储敏感信息和大数据,安全性高,cookie适合存储少量数据,用于客户端和服务端之间的通信,localStorage适合存储持久化数据,cookie最大特征就是任意请求都会把cookie带上

大文件上传

将大文件分割成多个小块,然后逐个上传这些切片,最后在服务端将这些切片组合成完整的文件

追问:后端如何确保这个顺序

前端将文件切片时,为每个切片添加一个序号或者唯一标识符,上传到服务端时,将这些切片按照序号或标识符的顺序进行上传

koa框架相比较于其他的node框架有何优势

koa使用了基于Promise的中间件机制,相比较Express等框架更加轻量级和灵活,并且中间件的写法更加简洁明了,使用async,await避免回调地狱。

Koa提供了一个集中的错误处理机制,通过try,catch语法捕获异步错误

Koa允许开发者更细粒度地控制http请求和相应的过程,比如通过洋葱模型可以精确地控制响应的顺序~

浏览器的线程和进程

进程包括多个线程,一般浏览器有一个主进程和多个渲染进程,主进程就是负责管理用户界面,网络请求,渲染进程负责处理网页的渲染和交互

浏览器的线程用于执行不同的任务,主要的线程如下

GUI线程:负责渲染用户界面,处理用户交互事件,比如点击

渲染线程:负责解析html,css和js,将页面渲染成可视化的页面

js引擎线程:执行js代码

事件触发线程:用于管理事件队列

定时器线程:用于管理定时器线程,处理定时器回调

追问:js引擎线程能否和htm渲染线程同时进行

答:不能,js执行会阻塞html的渲染,因为js能操作dom,若能同时进行,就会造成不安全的渲染

引入第三方库一般有什么方式

  1. cdn引入,也就是用script标签的src
  2. 通过npm安装
  3. 本地文件引入,下载到本地然后script的src引入
  4. 模块化引入,import, from

追问:script阻塞可以用defer解决,加了defer还有什么影响

加了defer后,除了解决script的阻塞问题,还会让script异步加载,如果有多个defer的script,按照从上到下的顺序执行,遵循的宏任务队列;defer属性会让script延迟执行,直到dom构建完执行,因为defer的script会让DOMContentLoaded事件触发前执行;另外就是IE9极其以下版本不兼容

css的伪类

  1. hover:鼠标悬停在元素上的状态

    css 复制代码
    a:hover {
        color: red;
    }
  2. focus:被选中时的状态

    css 复制代码
    input:focus {
        border-color: blue;
    }
  3. active:鼠标点击不放时的状态

    css 复制代码
    button:active {
        background-color: yellow;
    }
  4. visited:选择已经被访问过的链接的状态

    css 复制代码
    a:visited {
        color: purple;
    }
  5. first-child:某个子元素的第一个子元素

    css 复制代码
    li:first-child {
        font-weight: bold;
    }
  6. last-child:某个子元素的最后一个子元素

    css 复制代码
    li:last-child {
        color: green;
    }
  7. nth-child:某个子元素的指定位置的元素

    css 复制代码
    li:nth-child(odd) {
        background-color: #f2f2f2;
    }
  8. nth-of-type:某个子元素的指定类型的子元素

    css 复制代码
    p:nth-of-type(2) {
        color: blue;
    }

es6新增的数据类型

Symbol:表示唯一值,一般用作对象的key,确保属性的唯一性,像是set的迭代属性就放在symbol中,symbol值一般在控制台不会显示描述符

BigInt:可以表示任意精度的值,不受Number的64位双精度浮点数范围的限制,在数字后面加一个n就可以表示为大整型

Promise和async,await的区别

追问:await报错后面是否还会执行

答:不会

继续追问:如果想要继续执行,怎么做

我回答的是try,finally,或者一个try,catch

js有哪些监听事件的方式

  1. addEventListener

    javascript 复制代码
    document.getElementById('myButton').addEventListener('click', function() {
        console.log('Button clicked!');
    });
  2. on事件属性

    javascript 复制代码
    document.getElementById('myButton').onclick = function() {
        console.log('Button clicked!');
    };
  3. html事件属性

    css 复制代码
    <button onclick="console.log('Button clicked!')">Click me</button>
  4. 事件委托

    javascript 复制代码
    document.getElementById('parentElement').addEventListener('click', function(event) {
        if (event.target.tagName === 'BUTTON') {
            console.log('Button clicked!');
        }
    });
  5. jQuery事件

    javascript 复制代码
    $('#myButton').on('click', function() {
        console.log('Button clicked!');
    });

vue2,vue3的区别

  1. 性能优化。vue3在VDom上有很多改进
  2. Composition API。贴近原生js的函数式写法
  3. 支持ts。vue3对ts的支持更加完善
  4. 响应式。Proxy代替了Object.defineProperty,提高了性能
  5. Tree-shaking支持。vue3更好地支持了Tree-shaking,打包后代码更加精简
  6. 更小的体积。

子组件如何监听父组件传值的变化

子组件可以通过watch来监听props的变化

computed,watch的区别

二者都是用于监听数据的变化,但是computed有缓存属性,watch在用法上更灵活,适用于监听特定数据走一个回调,处理异步

vue初始化页面有了解它底层的渲染过程吗

先通过new Vue()来创建一个vue实例对象,然后会将数据进行响应式处理,这样数据发生变化时,相关的视图就会自动更新,之后vue会将模板template解析生成VDom,然后将VDom进行挂载渲染到页面上,最后数据发生变化时,diff算法会对比新旧dom,只更新变化的VDom到真实Dom,这样保证了页面的高效更新

最后介绍公司业务

E公司

这个面试官挺好的,句句有回应,就是说话有丢丢结巴

自我介绍~

vue3响应式原理

追问:数据代理为什么比数据拦截好

答(这是面试官说的):数据拦截就是vue2的defineProperty,Proxy性能会更好,可以对象嵌套对象,数据拦截只会代理第一层,是懒代理,defineProperty会把对象进行一个深层次的递归,性能欠缺,proxy只需要for循环第一层,后面的对象在你使用的时候才会执行代理,因此vue3有个缺点就是,当你对一个对象添加属性时,vue不会自动响应这个变化,这就是对象新增属性不响应的问题,可以用$set解决这个问题

watch,watchEffect的区别

二者都是用于监听数据变化,watch接收三个参数,监听的数据,回调和一些参数,而watchEffect包含了watch的功能,无论是否监听响应式数据,watchEffect都会在初次进入页面时或者更新页面时立即执行一次,并且里面可以写调度函数,不会二次执行相冲突

说说Pinia

然后聊到了ts,面试官说ts不仅仅是给数据类型加了个限制,还有就是多人协作时的一个规范性,很多es6的高级语法是ts才具备的

你对于组件的想法

组件就相当于一个模块化的思想,设计好一个组件可以拿去重用,提高代码的复用性

组件传参如何双向绑定

我先说了父子组件是不建议去双向流动数据的,面试官说有时候需要这么干,还是在emit里面,写个语法糖updata-,这样props变量就看也i支持在外面v-model双向绑定

display:table设置为1列时,占多少分之一

没答上来,面试官说默认情况屏幕被划分为24块,也即是1/24

请求方法get,post区别

这里忘记了,全程都是面试官在解释

请求方法都是前后端一起规范好的,方法中delete就不说了,就是作删除用得,一般用户操作就是一个增删改查,增得话就是用post请求,查一般就是get请求,并且get请求是没有请求体body的,就相当于所有的参数都放在url中,所以不安全,并且url的长度是限制的。post请求是有body的,比如用户填一个form表单就是用post放到body中

因此就是get通过url传参,有长度限制,并且不安全,post请求有请求体,长度没有限制

后面聊了聊说现在写vue,一般都是用ts写的,而非template,并且他们公司是用低代码平台搭建前端应用,低代码可以更好地解决路由和菜单的管理,前后端配合

F公司

自我介绍+项目~

还问我前端学了多久......

组件通讯

父子:父组件v-bind绑定属性用于传值,子组件props接收

子父:父组件订阅一个事件,子组件通过$emit发布该事件,且携带事件参数,让父组件订阅生效

vuex,pinia

vue组件通信【父子,子父,vuex】 - 掘金 (juejin.cn)

eventbus

eventbus就是用于vue组件通讯的模式,它是一个全局总线,可以用来在不同的组件之间进行传递信息和触发事件,不需要明确地通过父子组件传递props或者走回调的形式来实现

先创建一个vue实例对象,用它来触发和监听事件,一般这个写在入口文件或者根组件,让后将其挂载到vue的原型上,这样所有的组件都可以访问到它

比如下面的组件A和组件B借助eventbus进行通讯,A组件点击按钮发送信息,B组件监听到该消息

javascript 复制代码
// EventBus.js
import Vue from 'vue';

// 创建一个空的Vue实例作为事件总线
const EventBus = new Vue();

export default EventBus;
xml 复制代码
// ComponentA.vue
<template>
  <button @click="sendMessage">Send Message</button>
</template>

<script>
import EventBus from './EventBus';

export default {
  methods: {
    sendMessage() {
      // 发送名为 'message' 的事件,附带一些数据
      EventBus.$emit('message', 'Hello from Component A');
    }
  }
}
</script>
xml 复制代码
// ComponentB.vue
<template>
  <div>{{ receivedMessage }}</div>
</template>

<script>
import EventBus from './EventBus';

export default {
  data() {
    return {
      receivedMessage: ''
    };
  },
  created() {
    // 监听名为 'message' 的事件
    EventBus.$on('message', message => {
      this.receivedMessage = message;
    });
  }
}
</script>

通过使用eventbus就不需要了解组件的层级关系,当然也不能滥用,过多的全局事件会导致代码难以维护

抛开vue,如何用js实现组件通信

  1. 定义全局变量:所有组件都可以直接访问和修改这些数据
  2. 发布-订阅模式:自定义事件,组件可以订阅某个事件,事件被另一个组件发布时,订阅者收到通知并执行相关操作
  3. 回调函数:一个组件将自己的函数传给另一个组件,在适当的时候调用这个函数

vue源码看过吗,说下

只看过响应式和路由......

输入url到页面渲染的整个过程

自行吟唱~

dns缓存在哪里

dns(Domain Name System)缓存通常存在于操作系统和浏览器中

  1. 操作系统的dns:本地维护一个dns缓存,用于存储最近解析过的域名和对应的ip
  2. 浏览器的dns缓存:现代浏览器也会维护自己的dns缓存,同样存储解析过的域名和ip,这样可以避免重复的dns查询

如何解决js阻塞渲染

js阻塞渲染是因为js线程和渲染线程不能同时进行,可以用async和defer属性解决

async和defer的区别

二者都是可以异步加载script标签,但是defer最后是有一个执行顺序的,这个顺序就是代码顺序,async执行顺序不确定,取决于哪个脚本先加载完成

因此脚本之间互相独立并且顺序不重要时可以使用async属性,若有依赖关系则使用defer属性

设计模式有了解多少

单例模式:确保一个类只有一个实例对象,并提供一个全局访问点

工厂模式:将对象的创建过程封装在一个工厂方法中,根据不同的条件创建不同类型的对象

观察者模式:定义对象之间一对多的依赖关系,一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新

发布订阅模式:至今不明白和观察者模式什么区别,发布者可以有多个订阅者,它发布信息并通知所有的订阅者,订阅者收到信息可以去执行相应操作

闭包

因提到了GC,有了后面的问题......

垃圾回收机制你了解吗

垃圾回收机制Garbage Collection 简称GC,是一种自动内存管理的技术,在程序运行中自动回收不再使用的内存,也就是管理内存的分配和释放

js的GC主要有两种:

  1. 标记清除:这是最常见的策略,GC会周期性的扫描程序中的对象,标记那些仍然被引用的对象,GC会清楚那些没有被标记的对象,然后释放它
  2. 引用计数:实际上很少用这个,GC会根据每个对象的引用计数,对象被创建时,计数为1,被引用时,计数加1,不在被引用时,计数减1,计数为0时,释放它

异步你了解吗

event-loop

先同步,后执行微任务,再执行宏任务,宏任务和微任务都有相应的队列执行,执行一次宏任务之前掏空前面的微任务队列~

用户打开首页,加载5s才看到了内容,优化方案都可以说说

这么久才看到页面有可能是因为数据资源大,用户网速慢,服务器响应慢

优化如下:

  1. 对css,js和图片等静态资源进行压缩处理,减小文件大小,加快下载速度;
  2. 将页面的非关键资源设置成延迟加载,使页面首页加载时只加载必要的内容,后再加载其他资源;
  3. 不影响页面渲染的资源可以使用异步的方式进行加载;
  4. 将静态资源部署到CDN上,利用cdn的分布式节点加速资源的传输
  5. 利用浏览器缓存机制和服务端缓存机制,减少重复请求
  6. 对前端代码进行优化,减少重复逻辑

大文件上传

你项目跨域是怎么解决的

跨域就是因为浏览器的同源策略,后期单独出篇文章来讲,我答的是cors,还有josnp

简单请求和非简单请求

简单请求是浏览器向服务器发送的一种特定类型的跨域请求,满足如下条件就不会触发浏览器的预检请求

  1. 使用以下方法:get,head,post
  2. 请求头只包含以下字段:accept,accept-language,content-language,content-type(有限制)

满足这些条件浏览器会将其视为简单请求,直接发送给后端,不会触发预检请求,服务器收到请求后,若允许跨域,则会返回响应

不满足那些条件就是非简单请求,这些请求会触发浏览器的预检请求,服务器接收到预检请求后,需要返回相应的cors头部信息来确认是否允许跨域

强缓存和协商缓存了解吗

强缓存和协商缓存是浏览器在缓存资源时使用的两种不同策略

强缓存:强缓存是通过设置http响应头的cache-control和expires字段来实现的,当浏览器发送请求时,会先检查缓存中是否存在资源以及是否过期,若没有则直接从缓存中获取资源,不会向服务器发送请求。

协商缓存:协商缓存是通过http响应头中的etag和last-modified字段来实现的,当浏览器发送请求时,会先向服务器发送一个验证请求,询问资源是否有更新,服务器收到验证请求后,会根据资源的内容来生成一个唯一标识etag和最后修改时间last-modified,若资源没有发生变化,则服务器返回304状态码,告诉浏览器可以继续使用缓存中的资源,若资源发生了变化,则服务器返回新的资源内容和相应的状态码

强缓存和协商缓存可以结合使用,浏览器在接收到服务器的响应时会根据cache-control和expires字段判断是否使用强缓存,如果强缓存失效,则会发送一个带有if-none-match或if-modified-since字段的请求,进行协商缓存验证。

keep-alive源码看过吗,描述下

先创建一个缓存对象,核心逻辑是获取第一个子组件的VNode,然后获取组件的唯一key,如果缓存中存在该组件实例,那么直接返回缓存中的实例,若没有则创建一个实例并存入缓存中,最终还要通过mixin来监听组件的销毁事件,在组件销毁时从缓存中移除

mixin

mixin是一种在vue中用于复用组件选项的方式。通过mixin,可以将一组组件选项合并到多个组件中,mixin通常是一个js对象,可以包含任意组件选项,比如data,methods,computed等,当一个组件使用mixin时,mixin中的选项会被合并到组件的选项中

前后端通讯

  1. http请求
  2. ajax,js异步与服务器进行通信
  3. websocket,允许前端和后端建立持久连接,并进行双向实时通信,比如在线聊天
  4. SSE(Server-Sent Events),允许服务器向客户端推送实时更新的数据,与websocket不同,sse只能从服务器向客户端发送数据,不能双向通信

axios

axios基于Promise,让我们可以轻松地发送异步请求,基于XML和Fetch,并且使用promise对http请求进行封装,还可以进行拦截操作,可以在请求或响应在发送或者接收前进行拦截和处理,比如弹出框可以借助它来实现,另外还可以取消请求,避免不必要的资源浪费,另外axios提供了丰富的错误捕获机制,可以自定义全局的错误处理函数

返回一个数字的千分位

比如数字123返回字符串123,数字1234返回字符串1.234,数字123456返回字符串123.456......

先将数字转字符串,然后3个字符串一起作为数组的元素,最后数组join时带个点

ini 复制代码
let n = 1234 // 输出"1.234"
function getThousandSign (n) {
    const str = n.toString()
    const arr = []
    let len = str.length
    for(let i = len; i > 0; i -= 3) {
        let block = str.substring(i - 3, i)
        arr.unshift(block)
    }
    return arr.join('.')
}
console.log(getThousandSign(n)); // 1.234

G公司

这家公司是做uniapp开发的

uniapp如何实现下拉刷新,上拉加载

下拉刷新:使用页面钩子onPullDownRefresh处理逻辑,页面中使用refresh-view组件展示下拉刷新的效果,并监听refresh事件

上拉加载:使用页面钩子onReachBottom处理逻辑,页面中使用scroll-view组件,并监听scrolltolower事件

如何实现多端适配

通过# ifndef 来包裹顶部电量信息view盒子

vue和nvue

vue.js:vue时uniapp中主要的开发方式,适用于多个平台的开发

nvue.js:nvue时uniapp中的一种新的开发方式,专门为小程序端而设计的一种开发方式,通过使用原生组件和原生渲染方式来提高小程序端的性能和体验

封装过组件吗

定位的缺点

position用absolute,fixed会导致元素脱离文档流,并且二者依靠最近的祖先元素发生变更会导致定位不准

后面一直在闲聊......

H公司

这个面试官一直拿着我的往期文章来问

自我介绍+项目

深浅拷贝

面试官:手写一个浅拷贝和一个深拷贝(拷贝详解) - 掘金 (juejin.cn)

自己写的文章当然有印象,不过关于深拷贝我没处理函数,因此他接着问我如何深拷贝函数

函数得话应该就是直接返回即可,但是如果是箭头函数,那么就不能有实例对象,因此可能需要用上eval()生成一个新函数

类型判断

深入认识js四大常用数据类型判断,一次性带你搞明白(内含面试热点)! - 掘金 (juejin.cn)

闭包

面试官:聊聊js闭包。来看这篇,小白也能读懂!(内含调用栈及作用域链的详细讲解) - 掘金 (juejin.cn)

手写防抖节流

面试官:手写下防抖节流 - 掘金 (juejin.cn)

localStorage,cookie,session的区别

js事件触发

面试官:请问js事件触发过程是怎样的 - 掘金 (juejin.cn)

为什么0.1 + 0.2 !== 0.3

因为浮点数精度问题,这些数被转换成二进制时,二进制是无法精确表示一些十进制小数,0.1和0.2在二进制中是无限循环小数,会产生精度丢失

追问:如何解决

将浮点数乘以10,使其最终转换成整数再进行比较

es6新特性

call,apply,bind区别

三者都是去显示改变this指向,call和apply的区别是apply可以以数组的形式进行传参,bind会返回一个新的函数,需要再次进行调用

new操作的过程

在构造函数中创建一个this对象,然后构造函数中的内容就相当于往this里面挂属性,另外还会放一个实例对象的隐式原型,也就是构造函数的显示原型,最终return出这个this对象

js中this究竟指向哪里?现在终于搞定了! - 掘金 (juejin.cn)

css垂直水平居中

元素隐藏

最新css面试题汇总【助力金三银四】 - 掘金 (juejin.cn)

减少重排重绘

输入url到页面渲染后半段:回流,重绘,优化【一次性带你搞明白】 - 掘金 (juejin.cn)

这个时候我就笑着说面试官拿着我的文章来问,面试官说这些八股其实在开发中确确实实是会用上的

谈谈你对vue的认识

mvvm,响应式,组件化,生态......

vue的插槽

  1. 默认插槽,子组件未命名的插槽,父组件传递内容到子组件时,子组件通过一个不带属性的slot标签来定义默认插槽的位置

    xml 复制代码
    <!-- 子组件 -->
    <template>
      <div>
        <slot></slot>
      </div>
    </template>
    
    <!-- 父组件 -->
    <template>
      <my-component>
        <div>默认插槽内容</div>
      </my-component>
    </template>
  2. 具名插槽,允许父组件向子组件传递特定名称的内容,并指定插入到子组件的特定位置,子组件通过slot标签的name属性来定义具名插槽的位置

    xml 复制代码
    <!-- 子组件 -->
    <template>
      <div>
        <slot name="header"></slot> 
        <div>子组件内容</div>
        <slot name="footer"></slot> 
      </div>
    </template>
    
    <!-- 父组件 -->
    <template>
      <my-component>
        <template v-slot:header>
          <h1>头部内容</h1>
        </template>
        <template v-slot:footer>
          <p>底部内容</p>
        </template>
      </my-component>
    </template>
  3. 作用域插槽,允许子组件将数据传递给父组件,并在父组件中进行渲染,子组件通过slot标签中使用具名插槽的方式来传递数据,父组件通过slot指令来接收数据并进行渲染

    xml 复制代码
    <!-- 子组件 -->
    <template>
      <div>
        <slot name="item" v-for="item in items" :item="item"></slot> 
      </div>
    </template>
    
    <!-- 父组件 -->
    <template>
      <my-component>
        <template v-slot:item="slotProps">
          <div>{{ slotProps.item }}</div>
        </template>
      </my-component>
    </template>

nextTick

细聊vue的nextTick - 掘金 (juejin.cn)

前端路由

面试官:谈谈前端路由的实现原理【hash&history】 - 掘金 (juejin.cn)

map和weakmap的区别

Iterator-Set-Map-WeakSet-弱引用详解 - 掘金 (juejin.cn)

git切换分支用什么指令

csharp 复制代码
将修改的文件暂存起来
git add myfile.txt

保存变更到堆栈中
git stash

切换到其他分支进行工作
git checkout other-branch

在其他分支上完成工作后,可以恢复之前保存的变更
git stash apply

手写个ajax

详谈ajax发展历程 - 掘金 (juejin.cn)

vuex和pinia的区别

vuex基于vue2的OptionsAPI,pinia基于vue3的CompositionAPI,并且更兼容ts......

最后

如果你对春招感兴趣,可以加我的个人微信:Dolphin_Fung,我和我的小伙伴们有个面试群,可以进群讨论你面试过程中遇到的问题,我们一起解决

另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请"点赞+评论+收藏"一键三连,感谢支持!

相关推荐
熊的猫35 分钟前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
瑶琴AI前端1 小时前
uniapp组件实现省市区三级联动选择
java·前端·uni-app
会发光的猪。1 小时前
如何在vscode中安装git详细新手教程
前端·ide·git·vscode
别拿曾经看以后~2 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
我要洋人死2 小时前
导航栏及下拉菜单的实现
前端·css·css3
川石课堂软件测试2 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
科技探秘人2 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人2 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR3 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香3 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel