面试题集训3

# 第一家公司

# 概况

  • 公司:坐标深圳。
  • 面试官:挺能引导回答的一位老哥。
  • 面试结果:没戏。
  • 面试感受:题目答的不是很好,但是面试大哥能引导我做出一些回答,面试过程感觉还行。

# 面试题

  1. 请简述从输入URL到页面渲染的完成过程。
  2. 移动端1px解决方案。
  3. 请简述rem布局的实现原理和方案。
  4. 公司有个项目。该项目需要做成单页应用,此时在不使用其他框架的情况下,说一下你该如何实现这个单页应用。
  5. Vue3中,如何监听数组的变化?为什么要用Proxy替换defineProperty
  6. Array(100).map(x=>1)结果是多少?如何生成100个元素为1的数组?
  7. Webpack如何优化项目体积。
  8. 假如你在爬楼梯,楼梯一共有N层,但你每次爬楼梯只能走一步或两步,计算共有多少种走法?
  9. 如何优化单页面项目首次加载白屏?
  10. 项目中比较难忘的事情。

# 请简述从输入URL到页面渲染的完成过程。

这里问的应该是渲染过程,答案可以看三元大神的这篇文章(这么多内容,光是这一题就够折腾😹)

(1.6w字)浏览器灵魂之问,请问你能接得住几个? (opens new window)

# 移动端1px解决方案。

当时就讲了一个伪类实现,太菜了。

  • 0.5px 方案
  • 伪类+transform
  • viewport + rem
  • border-image
  • background-image
  • postcss-write-svg

移动端1px解决方法知多少 (opens new window)

# 请简述rem布局的实现原理和方案。

原理

假设我们将屏幕平均分为10份,每一份宽度用一个a表示,即a=屏幕宽度/10;那么:

div{width: 5a} /* 屏幕宽度的50% */
1

但是css中没有a这个单位啊?我们可以实现借助rem代替上面的a。如:

html {font-size: 12px}
div {width: 2rem} /* 24px*/

html {font-size: 16px}
div {width: 2rem} /* 32px*/
1
2
3
4
5

那么问题来了?怎么让html元素字体大小恒等于屏幕的1/10呢?如ipone6宽是375px,font-size:37.5px;

html {fons-size: width / 10}
div {width: 5rem} /* 5rem = 5a = 屏幕宽度的50% */
1
2

我们用js很容易动态的设置htmlfont-size恒等屏幕的1/10;我们可以在页面domreadyresize和屏幕旋转中设置:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + ‘px‘;
1

如何把设计稿的像素单位换成以rem为单位呢?可以用一个比例来计算:如设计稿宽度为750px,某个元素量得75px,那么:

75px/750px = 计算所得rem/10rem,所以计算所得rem=75px;所以我们在样式中写width:1rem;实际宽度是75px;同理,如果设计稿总宽度是640px,则1rem=64px。

预处理函数可以简化:

$ue-width: 750; /* 设计稿图的宽度 */

@function px2rem($px) {
  @return #{$px/$ue-width*10}rem;
}

div {
  width: px2rem(100);/*编译后:  p{width:1.5625rem}*/
}
1
2
3
4
5
6
7
8
9

rem布局原理深度理解 (opens new window)

实现方案

vue-ydui中rem布局实现方式 (opens new window)

# 公司有个项目。该项目需要做成单页应用,此时在不使用其他框架的情况下,说一下你该如何实现这个单页应用。

web-component Web Components 入门实例教程 (opens new window)

hashchange JS原生一步步实现前端路由和单页面应用 (opens new window)

history 前端路由实现原理(history) (opens new window)

# Vue3中,如何监听数组的变化?为什么要用Proxy替换defineProperty?

  1. Vue3通过Proxy实现对数据的监听,可以把v2 v3的双向数据绑定原理讲一遍。
  2. ProxyObject.defineProperty方式相比有以下优势:
    • Proxy有多达13种拦截方法。
    • 可以监听数组对象变化
    • 代码更简化
    • 性能更优秀,Proxy返回的是一个新对象,我们可以只操作新对象达到目的,不需要深度遍历监听,性能高于Object.defineProperty,而Object.defineProperty只能遍历对象属性直接修改。

# Array(100).map(x=>1)结果是多少?如何生成100个元素为1的数组?

  1. 数组长度为100的空数组,map返回的长度和原数组长度是一致的。
  2. 如何生成100个元素为1的数组?
    • Array(100).fill(1)
    • 循环
    • '100个1'.split('')
    • 期待其他答案

# Webpack如何优化项目体积。

  • Scope Hoisting
  • Tree-shaking
  • 公共资源分离
  • 图片压缩
  • 动态Polyfill

webpack构建速度和体积优化策略 (opens new window)

# 假如你在爬楼梯,楼梯一共有N层,但你每次爬楼梯只能走一步或两步,计算共有多少种走法?

斐波那契数列有一个特征就是 这个数列从第3项开始,每一项都等于前两项之和。

最简单的解法就是递归😂,but,n超过50就很慢了,100标签页直接卡死。

算法的话,可以看看下面的文章,这里不过多描述。

function climbStairs(n) {
    return n < 3 ? n : climbStairs(n-1) + climbStairs(n-2)
};
1
2
3

百度百科 (opens new window)

算法题-爬楼梯【JS实现】 (opens new window)

# 如何优化单页面项目首次加载白屏?

  • 优化项目体积
  • 路由按需加载
  • 开启gzip
  • 图片懒加载
  • index.html加loading
  • ui组件按需加载
  • 打包后的项目,除了index.html,其他全放cdn,不过这个需要开发的时候配置一下
  • 骨架屏,这里面试官有提到,用Webpack统一处理骨架屏 page-skeleton-webpack-plugin (opens new window)

# 项目中比较难忘的事情

# 第二家公司

# 概况

  • 公司:坐标深圳,上市公司,招人做后台管理。
  • 面试官:居然是老乡。
  • 面试结果:没戏。
  • 面试感受:不咋样,不会就过的那种,回答了的也不知道答没答错😹。

# 面试题

  1. this的指向,严格模式下this指向,箭头函数this指向。
  2. 大文件切片上传,一起上传还是单个上传,其中一个失败了如何处理。
  3. 后台管理系统权限设计。
  4. 短链接如何实现,使用八位随机字符串匹配(大小写加数字),有多少概率重复。
  5. 301和302的区别。
  6. 和=区别。
  7. undefined==false
  8. 1+undefined
  9. 合并两个对象,相同的key如何处理的。
  10. 判断空对象。
  11. 立即执行函数有什么用途。
  12. call、bind、apply区别。
  13. 函数里面如何获取所有参数。
  14. 类数组如何转换成真数组。
  15. vue组件通信方式。
  16. vuex实现原理。

# this的指向,严格模式下this指向,箭头函数this指向

  • 默认绑定(非严格模式下this指向全局对象, 严格模式下this会绑定到undefined)
  • 隐式绑定(当函数引用有上下文对象时, 如 obj.foo()的调用方式, foo内的this指向obj)
  • 显示绑定(通过call()或者apply()方法直接指定this的绑定对象, 如foo.call(obj))
  • new绑定
  • 箭头函数绑定(this的指向由外层作用域决定的)

【建议👍】再来40道this面试题酸爽继续(1.2w字用手整理) (opens new window)

# 大文件切片上传,一起上传还是单个上传,其中一个失败了如何处理

多个切片一起上传,前端告诉后端切片数量,以及给后端一个上传完成的通知,后端如果发现缺少切片,通知前端续传。

前端大文件上传 (opens new window)

# 后台管理系统权限设计

根据自己接触的项目回答的

  • 一共四个表,接口表、菜单表、用户组表、用户表。
  • 数据库录入每一个需要权限的接口,并分配一个唯一id。
  • 数据库录入菜单,并分配一个唯一id。
  • 创建用户组,给用户组非配接口和菜单权限。
  • 给用户分配用户组。
  • 用户登录的时候拿到菜单权限,通过addRoutes动态生成菜单。
  • 拿到接口权限,通过自定义指令控制按钮权限。
  • 后端返回权限给前端时,同时在redis里面存一份方便权限查询,然后在中间件进行请求拦截。

之前写的一个小玩意,用到了这种权限管理方法,感兴趣的可以看看 https://github.com/taosiqi/uni-head

# 短链接如何实现,使用八位随机字符串匹配(大小写加数字),有多少个?

找一个短点域名做中转,携带8为随机字符串进行匹配。62个字符生成随机8位有多少个 62^8=218340105584896

# 301和302的区别

官方说法

301 redirect: 301 代表永久性转移(Permanently Moved)。

302 redirect: 302 代表暂时性转移(Temporarily Moved )。

301重定向是永久的重定向,搜索引擎在抓取新的内容的同时也将旧的网址替换为了重定向之后的网址。

302重定向只是暂时的重定向,搜索引擎会抓取新的内容而保留旧的地址。

# 和=区别

简单来说: == 代表相同, ===代表严格相同。

最好是先刷一遍这篇文章 undefined!=false之解 及==比较的规则 (opens new window)

==:

  • 如果两个值类型相同,再进行三个等号(===)的比较。

  • 如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换在比较:

    • 如果一个是null,一个是undefined,那么相等。
    • NaN==NaN返回false(注意:Object.is(NaN,NaN)为true)
    • Number,Boolean,String,Undefined这几种基本类型混合比较时,会将其转换成数字再进行比较 。 ===:
  • 如果类型不同,就一定不相等。

  • 如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。判断一个值是否是NaN,只能使用isNaN() 来判断。

  • 如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。

  • 如果两个值都是true,或是false,那么相等。

  • 如果两个值都引用同一个对象或是函数,那么相等,否则不相等。

  • 如果两个值都是null,或是undefined,那么相等。

第三篇: JS数据类型之问—转换篇 (建议收藏)原生JS灵魂之问, 请问你能接得住几个?(上) (opens new window)

# undefined==false

类型转换是真的要我的老命,这两题都回答错了,下面的解释不知道对不对,有错误请大佬们提出 。

Number,Boolean,String,Undefined这几种基本类型混合比较时,会将其转换成数字再进行比较

Undefined==false两边都会转换成数字

Undefined`转成数字是`NaN
1

false转成数字为0

NAN==0?
1

结果 false

这篇文章讲的比较好

undefined!=false之解 及==比较的规则 (opens new window)

# 1+undefined

这里有解释 http://es5.github.io/#x9.3 (死记?)

Undefined转换成数字后为NaN Null为+0

NaN`加任何都是`NaN
1

结果 NaN

# 合并两个对象,相同的key如何处理的

相同的key,后面一个会覆盖前面一个

  • In 遍历赋值
  • Obj.assign()
  • 拓展运算符

# 判断空对象

  • Object.keys(obj).length === 0
  • JSON.stringify(data) == "{}"

# 立即执行函数有什么用途

创建一个独立的作用域,避免变量污染。

# call、bind、apply区别

相同点

  • 都是改变this指向
  • 第一个参数都是 this 的指向对象。

不同点

  • callbind 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 。
  • apply 的所有参数都放在一个数组里面 obj.myFun.apply(db,['成都', ..., 'string' ])
  • bind 返回的是一个函数,需要手动调用执行,其他参数和 call 一样。

# 函数里面如何获取所有参数

arguments 按参数索引包含所有的参数

注意:箭头函数是没有 arguments ,如果在箭头函数中访问 arguments,访问到的 arguments

并不属于箭头函数,而是属于箭头函数外部的“普通”函数

# 类数组如何转换成真数组

  • ... 运算符
  • Array.from
  • Array.prototype.slice.apply(arguments)

# vue组件通信方式

  • 父子间通信:父亲提供数据通过属性props传给儿子;儿子通过$on 绑父亲的事件,再通过$emit 触发自己的事件(发布订阅)
  • 利用父子关系$parent$children
  • 父组件提供数据,子组件注入。provideinject ,插件用得多。
  • ref 获取组件实例,调用组件的属性、方法
  • 跨组件通信Event Bus (Vue.prototype.bus=newVue)基于on与$emit
  • vuex 状态管理实现通信

Vue组件通信 (opens new window)

# vuex实现原理

[Vuex原理 浅析] (opens new window)

面试复盘(一):面试官「前阿里大佬」果然厉害 (opens new window)

# 面试题

  1. npm私有仓库搭建【简历有写】。
  2. ui组件库开发,版本不兼容怎么处理
  3. 系统权限设计,接口权限那里配置的【简历有写】。
  4. 介绍下WebSocket
  5. 大文件上传怎么做的【简历有写】。
  6. 小程序分包,支付流程,手机号码,setData大数据优化手段
  7. this的指向
  8. call、bind、apply
  9. 做过app内嵌h5没,js和原生通信如何处理的?
  10. 介绍下vue keep-live
  11. vue数据响应式原理
  12. 做过vue3的项目没【简历有写】。
  13. 介绍下vue3 composition-api
  14. refreactive有什么不一样
  15. JS数据类型
  16. 过什么es6语法
  17. 数据类型判断
  18. 深拷贝
  19. Promise有几种状态
  20. EventLoop
  21. 原型链是什么
  22. 项目里面做过什么优化
  23. 前后端如何联调
  24. 短链接平台如何实现【简历有写】。

# npm私有仓库搭建

使用verdaccio 搭建私有npm 服务器 (opens new window)

# 系统权限设计,接口权限那里配置的

  1. 系统权限设计,根据自己接触的项目回答的。
    • 一共四个表,接口表、菜单表、用户组表、用户表。
    • 数据库录入每一个需要权限的接口,并分配一个唯一id。
    • 数据库录入菜单,并分配一个唯一id。
    • 创建用户组,给用户组非配接口和菜单权限。
    • 给用户分配用户组。
    • 用户登录的时候拿到菜单权限,通过addRoutes动态生成菜单。
    • 拿到接口权限,通过自定义指令控制按钮权限。
    • 后端返回权限给前端时,同时在redis里面存一份方便权限查询,然后在中间件进行请求拦截。

之前写的一个小玩意,用到了这种权限管理方法,感兴趣的可以看看 https://github.com/taosiqi/uni-head

  1. 接口权限哪里配置的 有超级管理员账户,他拥有配置权限的权限。

# ui组件库开发,版本不兼容怎么处理

不兼容提升组件库大版本就行

vue组件库及文档开发 (opens new window)

# 介绍下WebSocket

主要讲了他两三个特点,以及工作中哪里用到了它。

它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

其他特点包括:

  • 建立在 TCP 协议之上,服务器端的实现比较容易。
  • 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  • 数据格式比较轻量,性能开销小,通信高效。
  • 可以发送文本,也可以发送二进制数据。
  • 没有同源限制,客户端可以与任意服务器通信。
  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
  • 阮一峰WebSocket 教程 (opens new window)

# 大文件上传怎么做的

前端大文件上传 (opens new window)

# 小程序分包,支付流程,手机号码,setData大数据优化手段

感觉简历写了小程序,这几个问题都有可能问到。

小程序分包 文档直达 (opens new window)

支付流程 文档直达 (opens new window)

手机号码 文档直达 (opens new window)

setData大数据优化手段,可以只修改变化了的数据(^^) 微信小程序setData数据太大解决方案 (opens new window)

# this的指向

  • 默认绑定(非严格模式下this指向全局对象, 严格模式下this会绑定到undefined)
  • 隐式绑定(当函数引用有上下文对象时, 如 obj.foo()的调用方式, foo内的this指向obj)
  • 显示绑定(通过call()或者apply()方法直接指定this的绑定对象, 如foo.call(obj))
  • new绑定
  • 箭头函数绑定(this的指向由外层作用域决定的)

# call、bind、apply

相同点

  • 都是改变this指向
  • 第一个参数都是 this 的指向对象。

不同点

  • callbind 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面 。
  • apply 的所有参数都放在一个数组里面 obj.myFun.apply(db,['成都', ..., 'string' ])
  • bind 返回的是一个函数,需要手动调用执行,其他参数和 call 一样。

# 做过app内嵌h5没,js和原生通信如何处理的?

做过

原生通信不太懂,也没找到写的很好的文章,期待你的回答

# 介绍下vue keep-live

  1. Props:
  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  • max - 数字。最多可以缓存多少组件实例。
  1. 用法:
  • <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和<transition>相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。
  • 它有 activateddeactivated 两个生命周期。如<keep-alive>包裹两个组件:组件A和组件B。当第一次切换到组件A时,组件A的createdactivated生命周期函数都会被执行,切换到组件B,这时组件A的deactivated的生命周期函数会被触发;在切换回组件A,组件A的activated生命周期函数会被触发,但是它的created生命周期函数不会被触发了。

vue官方文档介绍 (opens new window)

# vue数据响应式原理

一文搞懂Vue2和Vue3的Proxy (opens new window)

# 做过vue3的项目没

目前在写vue3+ts的脚手架工具

https://github.com/taosiqi/v3ts-template

# 介绍下vue3 composition-api

vue3官方文档 composition-api (opens new window)

# ref和reactive有什么不一样

ref、reactiveVue3中实现响应式数据的方法 ,Vue2中通过defineProperty实现,Vue3通过ES6Proxy实现的。

reactive

  • 接受引用类型的参数,返回其Proxy,无法响应对整个Proxy的赋值。
      let person = reactive({ name: 'Tom' })
      person = { name: 'Tony' } //视图不会更新
      person.name = 'Tony'  //会更新
1
2
3
  • 使用场景: 不需要赋值操作的数据,结构较深的引用类型(建议)。
  • 两者在引用类型的处理上,区别在ref拥有value的包裹,内部则一致。 ref
  • 接受一个any类型的参数,返回{value:''}包裹的Proxy,可以通过改变value属性实现响应式的赋值操作。
  • ref的底层本质还是reactive,系统会根据给ref传入的值将它转换成reactive({value:data})
  • Vue template中可以直接使用ref,Vue会自动添加.value,在Js中使用ref需要.value
  • 使用场景:适用于需要赋值操作的数据,基本类型(必须)、结构较浅的引用类型(建议)。

vue3的ref和reactive的使用 (opens new window)

# JS 数据类型

这里可以了解一下js的包装类

  1. Boolean
  2. String
  3. Number 原始值不能有属性和方法,当给它们添加属性的时候系统会自动进行包装类并销毁。
let str = new String("小猪佩奇");
let str2="小猪佩奇"
console.log(str.length);  //输出4 .length是String自带的属性。
console.log(str2.length); //输出4  会先new String('小猪佩奇)再取.length; 然后delete;
1
2
3
4

image

JS数据类型分类和判断 (opens new window)

# 用过什么es6语法

  • Class
  • 模块importexport
  • 箭头函数
  • 函数默认参数
  • ...扩展运输符允许展开数组
  • 解构
  • 字符串模版
  • Promise
  • let const
  • Proxy、Map、Set

# 数据类型判断

第2篇: JS数据类型之问——检测篇 (opens new window)

# 深拷贝

第23篇: 能不能写一个完整的深拷贝? (opens new window)

# Promise有几种状态

总结:

  1. Promise的状态一经改变就不能再改变。
  2. .then.catch都会返回一个新的Promise
  3. catch不管被连接到哪里,都能捕获上层未捕捉过的错误。
  4. Promise中,返回任意一个非 promise 的值都会被包裹成 promise 对象,例如return 2会被包装为return Promise.resolve(2)
  5. Promise.then或者.catch 可以被调用多次, 但如果Promise内部的状态一经改变,并且有了一个值,那么后续每次调用.then或者.catch的时候都会直接拿到该值。
  6. .then 或者 .catchreturn 一个 error 对象并不会抛出错误,所以不会被后续的 .catch捕获。
  7. .then.catch 返回的值不能是 promise 本身,否则会造成死循环。
  8. .then 或者 .catch 的参数期望是函数,传入非函数则会发生值透传。
  9. .then方法是能接收两个参数的,第一个是处理成功的函数,第二个是处理失败的函数,再某些时候你可以认为`catch是.then第二个参数的简便写法。
  10. .finally方法也是返回一个Promise,他在Promise结束的时候,无论结果为resolved还是rejected,都会执行里面的回调函数。

【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理) (opens new window)

# EventLoop

第28篇:如何理解EventLoop——宏任务和微任务篇 (opens new window)

# 原型链是什么

第5篇: 谈谈你对原型链的理解 (opens new window)

# 项目里面做过什么优化

# 前后端如何联调

使用Swagger

# 短链接平台如何实现

找一个短点域名做中转,携带8为随机字符串进行匹配。62个字符生成随机8位有多少个 62^8=218340105584896

# 面试题

  1. 介绍一下自己之前做过的项目。
  2. Vue的生命周期。
  3. CreatebeforeMount他们两之间有什么区别。
  4. Vue组件通信。
  5. v-ifv-show的区别以及使用场景。
  6. nextTick的使用场景和作用。
  7. Vue中的key有什么作用。
  8. 计算属性和watch的区别。
  9. 子元素上下左右居中。
  10. 生成一条0.5px的线。
  11. 自适应方案。
  12. remrm的区别。
  13. vw和百分比有什么区别。
  14. 合并两个数组。
  15. 数组去重,冒泡排序。
  16. Object去掉其中一项属性,delete删除对象有什么影响。
  17. 深浅拷贝。
  18. 防抖节流 。
  19. 从0+100怎么实现。
  20. 一到一百个相同的请求,后面的依赖前面一个的结果,现在要拿到第一百个结果要怎么做。
  21. 假如你在爬楼梯,楼梯一共有N层,但你每次爬楼梯只能走一步、两步或三步,计算共有多少种走法,怎么打印出所有走法?

# 介绍一下自己之前做过的项目。

你可以回答的更好

# Vue的生命周期。

组件生命周期

  1. new Vue(),初始化事件和生命周期
  2. beforeCreate$eldata都是undefined
  3. 初始化数据和方法(dataprops的响应式处理,mehods方法声明)
  4. created$elundefined,修改data不触发update
  5. 判断有没有el项(vm.$mount(el)),判断有没有模板(没有将el外层的HTML当模板),将模板编译成渲染函数,返回虚拟DOM
  6. beforeMounted$el是虚拟DOM,修改data不触发update
  7. 创建正式DOM替换虚拟DOM,挂载到页面指定容器显示
  8. mounted(可操作真实DOM
  9. 数据变更
  10. beforeUpdate
  11. 重新渲染虚拟DOM并通过DIFF算法比较差异更新真实DOM
  12. updated
  13. 调用vm.$destory()
  14. beforeDestory(清理计时器、事件)
  15. 移除数据监听、事件监听和子组件
  16. destoryed(实例不可用) keep-alive生命周期keep-alive包裹的组件有activateddeactivated两个生命周期。如<keep-alive>包裹两个组件:组件A和组件B。当第一次切换到组件A时,组件A的createdactivated生命周期函数都会被执行,切换到组件B,这时组件A的deactivated的生命周期函数会被触发;在切换回组件A,组件A的activated生命周期函数会被触发,但是它的created生命周期函数不会被触发了。

介绍下vue keep-live (opens new window)

vue生命周期 (opens new window)

# Create和beforeMount他们两之间有什么区别。

同上题

# vue组件通信。

  1. 父子间通信:父亲提供数据通过属性 props传给儿子;儿子通过$on 绑父亲的事件,再通过 $emit 触发自己的事件(发布订阅)
  2. 利用父子关系 $parent 、 $children
  3. 父组件提供数据,子组件注入。provide 、 inject ,插件用得多。
  4. ref 获取组件实例,调用组件的属性、方法
  5. 跨组件通信 Event BusVue.prototype.bus=newVue)基于on$emit
  6. vuex 状态管理实现通信

# v-if和v-show的区别以及使用场景。

区别

v-if是删除生成dom,v-show是切换dispaly的状态。

使用场景

  • v-if
  1. 某一块代码在运行时条件很少改变,使用 v-if 较好 (v-if 有更高的切换开销)
  2. 在组件上使用v-if可触发组件的生命周期函数
  3. transition结合使用 当条件变化时该指令可以触发过渡效果(用于动画切换)
  • v-show
  1. 需要非常频繁地切换某块代码,使用 v-show渲染
  2. 当条件变化时该指令触发过渡效果(用于动画切换)

# nextTick的使用场景和作用。

使用场景

例:一个子组件通过v-if控制隐藏显示<t v-if='show'><t/>,当修改完显示状态后,立马通过ref去操作子组件的方法,这个时候会报错,原因在于子组件此时可能还未渲染完成,这个时候使用nextTick可以解决,他会在dom更新完成之后再去调用。

作用

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

# vue中的key有什么作用。

  • key会用在虚拟DOM算法(diff算法)中,用来辨别新旧节点。
  • 不带key的时候会最大限度减少元素的变动,尽可能用相同元素。(就地复用)
  • key的时候,会基于相同的key来进行排列。(相同的复用)
  • key还能触发过渡效果,以及触发组件的生命周期

# 计算属性和watch的区别。

  • 处理数据的场景不同,监听器(watch)适合一个数据影响多个数据,计算属性适合一个数据受多个数据影响
  • 计算属性有缓存性,计算所得的值如果没有变化不会重复执行,但是watch会重复执行
  • 监听器选项提供了更通用的方法,适合执行异步操作或较大开销操作的情况

# 子元素上下左右居中。

元素水平垂直居中 (opens new window)

# 生成一条0.5px的线。

image

怎么画一条0.5px的边(更新) (opens new window)

# 自适应方案。

自适应布局方案 (opens new window)

# rem和rm的区别。

  • rem是相对于根元素字体大小
  • em是相对于自身字体大小

# vw和百分比有什么区别。

  • 百分比是相对高度,相对于他的父元素而言。
  • vw永远都是相对于视窗大小的。

# 合并两个数组。

  1. arr1.concat(arr2)
  2. [...arr1,...arr2]
  3. 循环

# 数组去重,冒泡排序。

数组去重

1.Array.from(new Set(arr))

2.[...new Set(arr)]

\3. for循环嵌套,利用splice去重

\4. 新建数组,利用indexOf或者includes去重

\5. 先用sort排序,然后用一个指针从第0位开始,配合while循环去重

冒泡排序

function bubbleSort (arr) {
  for (let i = 0; i < arr.length; i++) {
    let flag = true;
    for (let j = 0; j < arr.length - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        flag = false;
        let temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
    }
    if (flag) break;
  }
  return arr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这个是优化过后的冒泡排序。用了一个flag来优化,它的意思是:如果某一次循环中没有交换过元素,那么意味着排序已经完成了。

冒泡排序总会执行(N-1)+(N-2)+(N-3)+..+2+1趟,但如果运行到当中某一趟时排序已经完成,或者输入的是一个有序数组,那么后边的比较就都是多余的,为了避免这种情况,我们增加一个flag,判断排序是否在中途就已经完成(也就是判断有无发生元素交换)

冒泡排序算法和数组去重 (opens new window)

# Object去掉其中一项属性,delete删除对象有什么影响。

delete Object['name']
1

delete只能删除自有属性,不会影响原型链上的属性

# 深浅拷贝。

第二十二篇: JS中浅拷贝的手段有哪些? (opens new window)

第二十三篇: 能不能写一个完整的深拷贝? (opens new window)

# 防抖节流 。

防抖节流 (opens new window)

# 从0+100怎么实现。

1、使用for循环从1加到100的总和

let sum=0;
for(var i=0;i<=100;i++){
    sum+=i;
}
1
2
3
4

2、使用while函数从1加到1000的总和

let i=0, sum=0;
while(i<=100){
    sum+=i++;
}
1
2
3
4

# 一到一百个相同的请求,后面的依赖前面一个的结果,现在要拿到第一百个结果要怎么做。

await async循环

# 假如你在爬楼梯,楼梯一共有N层,但你每次爬楼梯只能走一步、两步或三步,计算共有多少种走法,怎么打印出所有走法?

代码有点多,具体看我写的另一篇文章

爬楼梯2 (opens new window)

# 第二家公司

# 概况

  • 公司:在线教育。
  • 面试官:一般。
  • 面试结果:互相看不上😂。
  • 面试感受:你什么技术能匹配这个工资的???。

# 笔试题

  1. httphttps的区别
  2. requestAnimationFrame的作用。
  3. instanceof的原理
  4. localStoragesessionStorageCookie 区别。
  5. CommonJSES6 Module 的区别。
  6. 内存泄漏场景。
  7. 一道包含async、await、setTimeout、Promise的事件循环题。
  8. React HOC的作用,解决了什么问题,怎么理解Hook,解决了什么问题。
  9. Vue什么是渲染函数,尝试写一个简单的。
  10. 给定一个整数数组,找出其中两个数相加等于目标值。

# http和https的区别

  • Http是超文本传输协议,数据明文传输。
  • Https则是具有安全性的SSL加密传输协议,传输是加密了的。
  • HttpHttps使用的端口不一样,前者是80,后者是443

# requestAnimationFrame的作用

你知道的requestAnimationFrame (opens new window)

# instanceof的原理

instanceof的原理 (opens new window)

  • 数据存储方面:cookie在同源的HTTP请求里,在服务器和客户端来回传递。storage是本地保存。
  • 存储数据大小:cookie限制4kbstorage5MB
  • 数据有效期:cookie的有效期与过期时间设置有关(默认是会话),sessionStorage 当前标签页有效, localStorage始终有效。
  • 作用域:cookielocalStorage同源窗口,sessionStorage当前标签页
  • 操作:cookie只作为document的一个属性可获取,没有其他操作方法。storagegetItemsetItemremoveItemclear等方法。

# CommonJS 和 ES6 Module 的区别

CommonJS 和 ES6 Module 究竟有什么区别? (opens new window)

# 内存泄漏场景

js 内存泄漏场景、如何监控以及分析 (opens new window)

# 一道包含async、await、setTimeout、Promise的事件循环题

大致是这个样子的一个题目:今日头条async/await面试题执行顺序 (opens new window)

# React HOC的作用,解决了什么问题,怎么理解Hook,解决了什么问题。

没写过react

# Vue什么是渲染函数,尝试写一个简单的

实现简单render函数 (opens new window)

# 给定一个整数数组,找出其中两个数相加等于目标值,要求时间复杂度O(n)

https://leetcode-cn.com/problems/two-sum/

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 * 创建媒介所(字典表Map),遍历数组,匹配符合信息的目标值 taget - currentValue,
 * 匹配成功返回两个数值下标,匹配失败就将选手的信息放入媒介所。
 */
var twoSum = function(nums, target) {
  if(!nums) return [];
  // 创建字典表
  const m = new Map();
  // 遍历nums数组
  for(let i = 0; i < nums.length; i++){
    // 获取当前值
    const n = nums[i];
    // 获取对当前与该值匹配的数值
    const n2 = target - nums[i];
    // 判断目标值是否在字典中
    if(m.has(n2)){
      // 是,在返回目标值的坐标和当前数值的坐标
      return [m.get(n2),i]
    }
    // 不在字典中,则放入字典,key为数值,value为下标
    m.set(n,i)
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 面试题

  1. 做过小程序的错误监控没
  2. script引入一个第三方的脚本,脚本报错了,怎么能拿到他的详细信息。
  3. 小程序生命周期
  4. (盒子模型)一个大盒子,里面两个小盒子,他们款分别是50%,高是100%,都有一个1px的边框,这个时候会宽高溢出,怎么处理。
  5. 上下居中
  6. Webpack开启按需加载
  7. svg雪碧图怎能做的
  8. 大文件切片上传
  9. 微信多端用户同意,小程序怎么拿到unionid
  10. Canvas实现一个刮刮乐
  11. WebSocket遇到过什么问题

# 做过小程序的错误监控没

# script引入一个第三方的脚本,脚本报错了,怎么能拿到他的详细信息。

我想到的是用onerror捕捉,但是面试官问如何拿到详细错误,暂时没想到好的手段。

# 小程序生命周期

小程序生命周期 (opens new window)

# (盒子模型)一个大盒子,里面两个小盒子,他们款分别是50%,高是100%,都有一个1px的边框,这个时候会宽高溢出,怎么处理。

切换盒子模型

image

image

# 上下居中

和这个差不多

元素水平垂直居中 (opens new window)

# Webpack开启按需加载

webpack4下使用import()模块按需加载 (opens new window)

# svg雪碧图怎能做的

具体实现 vue3+ts模版 (opens new window)

原理 方便前端使用的SVG雪碧图 (opens new window)

# 大文件切片上传

前端大文件上传 (opens new window)

# 微信多端用户统一,小程序怎么拿到unionid

UnionID 机制说明

如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过UnionID 来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的UnionID是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,UnionID是相同的。

UnionID获取途径

  • 开发者可以直接通过 wx.login + code2Session 获取到该用户 UnionID,无须用户授权。
  • 小程序端调用云函数时,可在云函数中通过 cloud.getWXContext 获取 UnionID

# Canvas实现一个刮刮乐

可以看看这个,和我面试时讲的思路差不多。

Canvas 实现刮刮乐 js实现刮刮乐 (opens new window)

# WebSocket遇到过什么问题

ios切换页面以及锁屏断开连接

# 参考链接

https://www.yuque.com/istao/interview/

上次更新: 2022/04/15, 05:41:34
×