面试记录一

Zaylen大约 11 分钟随笔面试

面试记录一

ps:经历的大半个月的找工作, 终于约到了我的第一个面试了,从最先开始的拿着我那份什么东西写上去的菜鸟简历,投,没有任何响应 😅😅😅, 到后面经过同学,朋友的指导,只把自己想从事的工作岗位相关的东西写上总算是有 hr 愿意搭理我,到如愿约到我第一面试,中间虽有艰辛,但结果还是好的 😃😃😃,首选还是感谢 hr 和公司给了我一个面试机会,虽然没抱太大机会了,但是能走出第一步我已经很满足了,下面就对我这次面试作一个简单的记录.

1.笔试题

首先是笔试部分,都是些很基础的知识,但是由于我记忆不够牢固,还容易记混,很多东西只是有个印象,离开电脑,没有代码提示就大脑短路了 😔😔😔😔

1.1 javaScript 中数组有那些 API,表明那些数组是否改变原数组?(至少 10 个)

这个我感觉我写的不错,总的大部分都有写出来.数组的方法可以分为操作方法排序方法, 转换方法, 迭代方法

1.1.1 操作方法

下面前三种会影响原数组,最后一种不会, ps:(我把splice()也写成不会改变原数组了, 跟slice()记成一起去了 😭)

  • push()
  • unshift()
  • splice()
  • concat()

push()方法接收任意数量的参数,并将他添加到数组末尾,返回数组长度

let num = []
let count = num.push(1, 2, 3)
console.log(count) // 3

unshift()在数组开头添加任意多个值, 然后返回新的数组长度

let num = []
let count = num.unshift(1, 2, 3, 4)
console.log(count) // 4

splice() 传入三个参数,分别是开始位置, 0(要删除的元素数量),插入的元素,返回空数组

let num = [1, 2, 3, 4, 5]
let removed = num.splice(1, 0, 6, 7)
console.log(num) // [1, 6, 7, 2, 3, 4, 5]
console.log(removed) // []

concat()首先会被创建一个当前数组的副本,然后再把它的参数添加到副本尾部,最后返回这个构建数组

let num1 = [1, 2, 3]
let num2 = num1.concat(4, [5, 6])
console.log(num1) // [1, 2, 3]
console.log(num2) // [1, 2, 3, 4, 5, 6]

前三种会影响原数组,最后一项不影响原数组

  • pop()
  • shift()
  • splice()
  • slice()

pop()方法用于删除数组的最后一项,同时减少数组的 length 值,返回被删除的项

let num = [1, 2]
let item = num.pop() // 取得最后一项
console.log(num) // 1
console.log(item) // 2

shift()方法用于删除数组的第一项,同时减少数组的 length,返回被删除项

let num = [1, 2]
let item = num.pop() // 取得最后一项
console.log(num) // 1
console.log(item) // 2

splice() 方法传入两个参数,分别是开始位置,删除元素的数量,返回包含元素的数组

let num = [1, 2]
let removed = colors.splice(0, 1) // 下标零开始,删除一个
console.log(num) // [2]
console.log(removed)[1]

slice() 用于创建一个包含原有数组中一个或多个元素的新数组.不会影响原数组

let num = [1, 2, 3, 4, 5]
let num1 = num.slice(1, 4)
console.log(num1) // [2, 3, 4,5]

都不改变原数组,查找元素,返回元素坐标或元素值 (ps:就写了第一个,其他的忘了)

  • indexOf()
  • includes()
  • find()

indexOf() 返回要查找的元素在数组中的位置,如果没找到返回-1

let numbers = [1, 2, 3, 4, 5]
number.indexOf(4) // 3

includes()返回要查找的元素在数组中的位置,找到返回 true, 否则返回 false

let numbers = [1, 2, 3, 4, 5]
numbers.includes(4)

find()返回第一个匹配的元素

const people = [
  {
    name: 'Matt',
    age: 27,
  },
  {
    name: 'Nicholas',
    age: 29,
  },
]
people.find((element, index, array) => element.age < 28)

1.1.2 排序方法

主要有两个 ps:没写这方面的

  • reverse()
  • sort()

reverse()将元素反转

let values = [1, 2, 3, 4, 5]
values.reverse()
console.log(values) // 5, 4, 3, 2, 1

sort()接收一个比较函数,判断那个值应该排在前面

const arr = [1, 2, 3, 4, 5, 6]
console.log(arr.sort((a, b) => b - a)) // 6, 5, 4, 3, 2, 1
console.log(arr.sort((a, b) => a - b)) // 1, 2, 3, 4, 5, 6

1.1.3 转换方法

常见的转换方法有: (ps:这方面的我也没写)

  • join()

join()方法接收一个参数,即字符串分隔符,返回包含所有项的字符串

let colors = ['red', 'green', 'blue']
alert(colors.join(',')) // red,green,blue
alert(colors.join('||')) // red||green||blue

1.1.4 迭代方法

常用迭代数组的方法(都不改变原数组) (ps:只写了 forEach, filter, map,reduce)

  • some()

  • every()

  • forEach()

  • filter()

  • map()

  • reduce()

some()对数组每一项运行传入测试的函数,如果至少有一个元素返回 true,则这个方法返回 ture(查找一样)

let numbers = [1, 2, 3, 4, 5, 6, 7]
let someReslut = numbers.some((item, index, array) => {
  return item > 2
})
console.log(someReslut) // true

every()对数组每一项都运行传入的测试函数,如果所有元素都返回 true ,则这个方法返回 true

let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1]
let everyResult = numbers.every((item, index, array) => item > 2)
console.log(everyResult) // false

forEach()对数组每一项都运行传入的函数,没有返回值

filter()对数组每一项都运行传入的函数,函数返回 true 的项会组成数组之后返回

map()对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组

reduce()每个元素按序执行一个提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入

const arr = [1, 2, 3, 4, 5, 6]

const total = arr.reduce((item, value) => {
  return item + value
}, 0)

console.log(total) // 21

1.2 如何判断数组还是对象?(不少于两种)

ps:全部记得模模糊糊,记得一个通过Object.prototype.toString.call([]) 都还没有没记全,其他的都没写出来 😭😭😭

// 以下体提供三种方法
const a = []
const b = {}
// Array.isArray() 方法
console.log(Array.isArray(a)) //true
console.log(Array.isArray(b)) // false

// 通过构造函数判断
console.log(a.constructor === Array) // true
console.log(b.constructor === Array) // false

// 通过`Object.prototype.toString.call([])`
console.log(
  Object.prototype.toString
    .call(a)
    .toString()
    .replace(/[\[\]]/g, '')
    .split(' ')[1] === 'Array'
) // true

console.log(
  Object.prototype.toString
    .call(b)
    .toString()
    .replace(/[\[\]]/g, '')
    .split(' ')[1] === 'Array'
) // false

1.3 把下面字符串进行分割成数组

const txt = '您好!欢迎来到,你是面试的吗?是的!'

ps:我首先想到的是正则txt.split(/!,。/) 回去试了一下, 没加[]也没加g全局匹配符, 真大脑短路,呜呜呜~~

// 正确答案
console.log(txt.split(/[!,\?。]/g))  // [ '您好', '欢迎来到', '你是面试的吗', '是的', '' ]

1.4 看以下代码的输出结果

setTimeout(() => {
  console.log(1)
}, 0)

let promise = new Promise((resolve, reject) => {
  console.log(2)
  resolve(3)
}).then((res) => {
  console.log(res)
})

console.log(4)

ps: 我写的答案是:4,2,3,1 中间有猜的成分,哈哈,分不清 settimeout 和 promise 那个先执行, 然后我回去测试了以下答案是:2,4,3,1, 又是错的 😭😭😭😭😭, 百思不得其解,为啥异步里的 promise 比主进程里的还先执行,网上查了下资料:

**promise 函数第一次执行是同步的!!!**只有 then 里面的才是异步的。

所以如上例子, 先执行console.log(2) 然后是打印 4

至于为什么promise.then 要优先于setTimeOut()

原因是promise.then微任务setTimeOut() 是**宏任务 **, 微任务的优先级要高于宏任务.

1.4.1 宏任务和微任务

在 js 中,有两类异步任务:宏任务队列,和微任务队列,宏任务队列可以有多个,微任务队列只有一个。

  • 宏任务:就是 js 内部的任务,严格按照时间顺序压栈执行,如:SetTimeout, setInterval, setImmediate, i/o, 等
  • 微任务:通常来说就是需要在当前 任务 执行结束后立即执行的任务, Promise, Async/Await

宏任务和微任务的执行顺序是,在一次事件循环中, 先运行一次宏任务 -> 然后取出所有微任务 -> 所有微任务执行完成 -> 开始其他宏任务

Script 代码为第一层宏任务,如果有 setTimeout,setInterval,则他们的回调函数会成为第二层的宏任务。

1.5 什么是纯函数,以下那种是纯函数?

列 1:

var a = 10
const fun = (b) => {
  return a + b
}

例 2:

var obj = new Object()
const fun = (b) => {
  obj.a = 10
  return b
}
console.log(fun(5))

ps: 这一题概念记混了,以为除高阶函数之外的就是纯函数(其实例子里面也没有高阶函数,紧张脑子就跟装了浆糊一样,就乱写了)

纯函数:纯函数是指在函数执行过长中,除返回结果外,不会对其他外部状态产生影响,也不依赖外部状态函数,就如上例子中:例子一中, 因为使用了外部变量 a所以它不是个纯函数,例子二中,因为太对外部变量进行了修改所以它也不是纯函数

1.6 vue2 中修改了对象和数组控制台打印数据更新,页面不更新问题,请给出解决方案

ps: 面的时候只记得数组的 splice 方法了,其他的脑子短路,全部都不知道

方式一:使用Vue.set或者this.$set,(对象)

Vue.set(obj, 'a', newValue)

方式二(数组):通过this.arr = [...this.arr]

this.arr = [...this.arr]

方式三(数组):splice 方法

this.arr.splice(index, 1, newValue)

1.7 React 中 useEffect 对应类组件那些生命周期

ps:这个不是很了解,React 没有系统的学习过,只有之前用的时候对照的官方文档看。

  • 当 useEffect 第二个参数为空数组的时候[],会在组件挂载后仅执行一次.相当于componentDidMount
  • 不指定第二个参数,或者指定需要监听的依赖数组时,useEffect 会在组件更新后触发, 相当于componentDidUpdate
  • useEffect 返回的清除函数会在组件卸载前触发,用于清理副作用。相当于componentWillUnmount

1.8 css 实现左侧固定,右侧自适应

ps:这个我理解成右侧自适适应外边距了 😭😭😭, 写成了margin-right:auto !!!!, 回来仔细看了看,还 margin-right: auto......,这铁傻蛋了。。。。(怎么应该也是margin-left: auto)

正确答案应该:flex 布局的

<div class="content">
  <div class="left"></div>
  <div class="right"></div>
</div>

<style>
  .content {
    display: flex;
    flex-direction: column;
  }
  .left {
    width: 200px;
  }
  .right {
    flex: 1;
  }
</style>

1.9 如何实现一个 BFC?

ps: 这个我应该没错吧:overflow:hidden 不过就写了一个

  • 方式一:将容器元素的 overflow 属性设置为 autohiddenscroll 或其它非 visible 值,会创建一个 BFC
  • 方式二:将浮动元素的 float 属性设置为 leftright,会创建一个 BFC。
  • 方式三:将容器元素的 position 属性设置为 absolutefixedrelativesticky,会创建一个 BFC。
  • 方式四:将容器元素的 display 属性设置为 inline-blocktable-celltable-captionflexinline-flexgrid,会创建一个 BFC。
  • 方式五:将一个元素的 clear 属性设置为 leftrightboth,可以创建一个新的 BFC。

1.10 以下例子怎样才能输出 True?

const a = ?
console.log(a ==1 && a==2 && a==3)

ps:这个我只有在闲逛论坛时刷到过, 只记得要重写一个什么方法, 我写成了 toString()🙄🙄🙄,正确的是 ValueOf(), 好吧根据我后面的了解,两个方法都可以.

// 方式一
const a = {
  value: 1,
  toString() {
    return this.value++
  },
}
console.log(a == 1 && a == 2 && a == 3)

// 方式二
const a = {
  value: 1,
  valueOf() {
    return this.value++
  },
}
console.log(a == 1 && a == 2 && a == 3)

// 方式三
const a = new Proxy(
  {},
  {
    i: 1,
    get(target, prop) {
      return () => this.i++
    },
  }
)
console.log(a == 1 && a == 2 && a == 3)

原因:js 中当对象于基本类型进行比较的时候, 默认会使用对象的valueOf方法进行比较,没有valueof方法就会使用toString()方法,所有在如上例子中, 通过重写该方法 使其递增,就科一实现.

2.面试

ps:大部分都是问项目, 少数几个八股文,我也没准备,都是有啥说啥, 项目也讲的很乱, 老是把一些东西混在一起讲了,现在回想起来, 就一团浆糊, 乱起八糟 😅😅😅😅😅😅😅😅

2.1 Vue2 和 Vue3 有那些区别?

ps:说了 Vue3 的数据劫持的区别,vue3 用的代理,vue2 用到 defineProperty, 然后 vue3 有 tree-shaking,只会把有用的地方打包进去,然后 diff 算法有点区别之外其他的的就不知道.

2.2 v-if 和 v-for 能在一起使用吗?

ps:只知道不建议一起使用,原因不知道。

永远不要把 v-ifv-for 同时用在同一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断),因为 v-for 具有比 v-if 更高的优先级

2.2 你觉得 Ts 在你项目里能起到什么帮助?

ps:说了能让代码更加的规范, 然后能起到类型提示的作用,方便代码编写。

2.3 你用过 git 做过除基本操作之外的其他使用吗?

ps:愣头青,直接说了只会 push, 和 pull .., 其他操作其实也有使用过,但是忘了。。。

其他的差不多都是项目上的问题,还有一些我也不记得了 😅😅😅😅

3.总结

这此面试对自己的表现总的来说可以是很糟糕

1.基础知识不牢固,记得模棱两可。

2.紧张,一问问题就大脑打转, 问完之后直接不知道刚刚回答的是啥,问的是啥.....

3.回答不通畅,表达能力有待提高.

一定要努力改正,增强自己的表达能力,争取下一次面试能做到自己满意。。