复盘最近的面试

这个礼拜一直在面试,想着看看能否拿到不错的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,我和我的小伙伴们有个面试群,可以进群讨论你面试过程中遇到的问题,我们一起解决

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

相关推荐
腾讯TNTWeb前端团队2 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
uhakadotcom5 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
范文杰5 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪5 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪5 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy6 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom7 小时前
快速开始使用 n8n
后端·面试·github
uhakadotcom7 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom7 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom7 小时前
React与Next.js:基础知识及应用场景
前端·面试·github