记录第一次找实习🧐(最后选择了腾讯)

392 阅读11分钟

跨度时间:3.12 ~ 4.27

补充:第一次找实习,从3.12开始投递的简历,从一开始的Boss直聘乱投,但是基本没啥回信后(感觉和我现在是大二有关),直接投大厂:知乎,小米,百度,腾讯,美团...

第一次面试是3.22,一个初创公司,技术栈挺新的,而且mt挺好的,打电话让我面试。俩面OC后我拒绝后,还打了好几个电话让我入职,感觉对自己能力有个评估,后面就没投小厂了

真的被大厂乱挂,简历直接被筛,做了一堆测评

3月底收到腾讯的一面邀约,特别开心,后面又通过群友内推投递了百度(之前简历晒直接被挂),摆烂了好多次,最后总共面了三个公司,运气很好,全部OC了

建议,投递简历可以提前一个星期开始,因为我第一个星期基本没有回信(后面发现投成暑期实习了怪不得)

格墨科技一面(3.22)

其中一个项目实现

js 的基础类型(8种)

  • null
  • undefined
  • string
  • bigint
  • boolean
  • object
  • symbol

闭包

  • 是一个函数及词法环境
  • 隐藏私有变量

写一个闭包

var store = (function() {
  let S = {}
  return () => {
    get(key) {
      return S[key];
    }
    set(key, value) {
      S[key] = value;
    }
  }
})()

数组求和

  • 用了reduce,问我如果是异步请求相加,如何并行实现?

跨域问题

  • 同源策略影响

跨域解决

  • jsonp
  • cors
  • 代理服务器
  • websocket

浏览器缓存

  • 强缓存 > 协商协商

osi七层模型

udp和tcp区别

  • udp无连接,tcp面向连接

tcp三次握手

  • syn
  • syn/ack半连接队列
  • ack全连接队列

vue和react区别

  • vue响应式双向绑定
  • react单向数据流

vue双向绑定原理

  • v-model,利用响应式原理监听用户输入事件

响应式原理(从源码角度出发)

  • 数据劫持结合发布订阅

proxy为什么有性能问题

  • 对整个对象进行代理

格墨科技二面(3.25)-> 第二天OC

补充:拿的第一个offer,还是比较开心的哈哈

react了解过没

  • 我说跟着文档敲了一点东西,比较熟悉的还是vue

vue如何编译模板的

  • 通过Complier生成ast语法树,然后通过vue-parse转化一下,生成渲染函数,并优化,生成虚拟vnode节点,最后再vm.patch通过虚拟dom算法利用vnode节点生成真实dom节点

看我项目用了Monorepo,问为什么用

  • 一个仓库(packages)管理所有项目,有利于团队合作开发,代码复用

问我pnpm和npm区别

问我软链接和硬链接区别

vite和webpack区别

  • 一个适用于轻量级的项目,是一种基于ES模块的构建工具开发,速度快,一个适用于大型项目,拥有丰富的插件等

vite为什么快

  • vite是一种基于ES模块的构建工具,它利用浏览器原生的ES模块加载机制,将代码分割成更小的块,并在浏览器中按需加载。这种方式比传统的打包工具(如webpack)更快,因为它不需要在本地打包和压缩代码,而是直接在浏览器中编译和加载代码。此外,vite还支持热更新,可以在开发过程中实时更新代码,从而提高开发效率。
  • vite的热更新与构建方式有关,它利用浏览器原生的模块加载机制,在开发过程中实时编译和加载代码。因此,热更新是vite的一个重要特性,可以提高开发效率。

浏览器输入URL发生了什么

  • url是否合法,不合法交给搜索引擎
  • 缓存判断,dns解析
  • 获取MAC地址
  • tcp三次握手
  • 判断有无https,有则TLS四次握手
  • 返回数据,浏览器进行页面渲染
  • tcp四次挥手(还说了http1.1默认keep-alive,也就是持久化连接不关闭)

浏览器进行页面渲染有什么细节

  • 解析html,生成dom树,解析css,生成cssom树(还说了下载不阻塞,解析阻塞),遇到js脚本,判断有无async和defer,都无则进行js脚本解析,阻塞Render树的构建,最后根据cssom树和dom树生成render树并渲染页面

实现keep-alive

  • 可以通过ref获取到组件实例,然后将该实例放入sessionstorge本地缓存中
<div id="app" keep-alive ref="child">
  <div v-if="sessionstorge.getItem(app)"></div>
  <div v-else></div>
</div>
  • 以组件uid为键值用Map缓存该组件,并使用自定义组件获取slot插槽
<template>
    <div v-if="isCached">
      <slot></slot>
    </div>
    <div v-else ref="RefDom"></div>
</template>

<script setup>
import { Cache } from './Cache.js'
import { getCurrentInstance, render, ref, nextTick, defineProps } from 'vue'
const props = defineProps({ // 缓存key值
  _key: {
    type: String,
    required: true
  }
})
const instance = getCurrentInstance()
const RefDom = ref(null)
const isCached = ref(false)

let vnode = Cache.get(props._key)
nextTick(() => {
  if (!vnode) {
    isCached.value = true
    vnode = instance.slots.default()[0]
    Cache.set(props._key, vnode)
    console.log('初始未缓存')
  }
  render(vnode, RefDom.value)
})
</script>

// 使用
<template>
  <div>
    <CacheView _key="1">
      <h1>app</h1>
    </CacheView>
  </div>
</template>

<script setup>
import CacheView from './CacheView.vue'
</script>

算法:生成dom节点

<div id="app"></div>

const dom = el('ul', {'class': 'a'}, [
  el('li', {'id': 'b'}, ['item1']),
  el('li', {'id': 'c'}, ['item2'])
])
const vm = dom.render();
app.appendChild(vm);
// 生成以下代码
<ul class="a">
  <li id="b"></li>
  <li id="c"></li>
</ul>

// 实现如下:
function el(element, attribute = {}, children = []){
  return {
    render(){
      const el = document.createElement(element);
      Object.keys(attribute).forEach(key => el.setAttribute(key, attribute[key]));
      children.forEach(item => {
        if(typeof item == 'string') el.innerText = item;
        else el.appendChild(item.render());
      })
      return el;
    }
  }
}

LRU缓存

class LRUCache {
  constructor(n) {
    this.size = n // 初始化最大缓存数据条为n
    this.cacheMap = new Map() // 初始化缓存空间map
  }
  put(domain, info) {
    if(this.cacheMap.has(domain)) {
      // 已存在需更新数据的位置
      this.cacheMap.delete(domain); //移除数据
    }
    if(this.cacheMap.size >= this.size) {
      // 删除最不常用数据(Map.keys()返回一个迭代器 function* )
      const firstKey = this.cacheMap.keys().next().value; // 不必当心cacheMap为空,因为this.size一般不为空
      this.cacheMap.delete(firstKey);
    }
    this.cacheMap.set(domain, info); // 在末尾重新插入数据
  }
  get(domain) {
    if(!this.cacheMap.has(domain)) return false;
    const info = this.cacheMap.get(domain); // 获取结果
    this.cacheMap.delete(domain); // 移除数据
    this.cacheMap.set(domain, info); // 在末尾重新插入数据
    return info; 
  }
}

问我怎么学习 前端

  • 自学

有了解业界发生的事情吗

  • chatGPT

目前在学什么

  • 说自己最近在学编译原理,ast语法树的解析,还有next.js,react等

职业规划

  • 不考研,全栈,架构方面

腾讯一面(3.31)

OpenEuler开源项目负责的模块

第一次有人问我的这个项目

ts泛型

ts的class、type、interface区别

let const和 var

预检请求

非简单请求和简单请求

项目如何处理跨域

node中间层代理转发

cookie作用(存储信息+身份验证)

xhr、fetch区别

axios有看过源码吗?如何判断是服务器环境还是浏览器环境

  • 服务端用http模块转发请求,浏览器端用xhr发送请求
  • window?
  • typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]'

vuex和全局变量,能不能用全局变量替换vuex

腾讯二面(4.11)

补充

leader面,有点哈人

我简历写了首屏加载时间由4.7s优化到1.7s,其实是看之前群友的简历随便模仿的一个时间,这里给自己挖了一个坑,他一直问我,对于一个博客系统,首屏加载需要这么久吗?不应该啊?所以,简历问题大家应该好好看待,不用一味模仿,对于有数据的需要自己测试一下。

项目问题

get和post区别

  • 是否缓存
  • 参数由url亦或者body传递,可携带数据大小
  • 幂等性

性能方面做了哪些优化

邮箱SMTP协议登录(token)

webpack

webpack中使用的插件有什么

webpack常用的loader有什么

死亡webpack连问

闭包的业务场景

  • 在事件处理程序中使用闭包

  • 使用闭包来隐藏私有变量

    • 如防抖节流中timer外部不可访问
    • const myModule = (function() {
        const privateVar = 'I am private';
      
        function privateFunction() {
          console.log(privateVar);
        }
      
        return {
          publicFunction: function() {
            privateFunction();
          }
        };
      })();
      
      myModule.publicFunction(); // 输出 'I am private'
      

匿名函数作用

  • 避免污染全局变量,隐藏私有变量

反问

全程因为时间比较短,20来分钟,而且没有问算法题,我很疑惑哈哈,以为是kpi,没想到给过了🤣

腾讯三面(4.12)-> 4.23OC

介绍一下自己

  • 自己坚持每周的15km长跑

平时学习方面

说一下你认为最有挑战性的项目

项目中的难点,以及怎么解决

项目中体现你能力的地方

  • 在项目中,学习网络安全,让信息安全的同学帮忙测试网站安全,并实时进行修复和改进

如果给你负责一个项目,你会如何进行开展

  • 制定详细的计划,并与团队成员和利益相关者保持沟通。同时,需要定期监控项目进度,并及时采取措施来应对任何问题。

团队沟通?如果团队的成员和你合作沟通不来(因为他造成项目进展方面的问题),怎么解决

  • 主动询问,帮忙推进进度,拉双方领导进群沟通

性格方面

百度一面(4.20)

软工学的课

  • 编译原理、数据库、c语言、计网、计组、操作系统...

手写快排

  • 天天刷,5分钟秒
function sortArray(arr, left = 0, right = arr.length - 1) {
    if (left >= right) return arr;
    var i = left, j = right, flag = i;
    while(i < j) {
        // i为最大数,j为最小,flag为中间
        while(arr[j] >= arr[flag] && j > flag) j --;
        if (i >= j) break;
        while(arr[i] <= arr[flag] && i < j) i ++; 
        var temp = arr[flag];
        arr[flag] = arr[j];
        arr[j] = arr[i];
        arr[i] = temp;
        flag = i;
    }
    sortArray(arr, left, flag - 1);
    sortArray(arr, flag + 1, right);
    return arr;
}

手写深拷贝

// 浅拷贝
function _shallowClone(obj) {
    if(typeof obj !== 'object' && obj === null) return obj;
    if(/^(Object|Array)/.test(obj.constructor.name)) {
        return obj instanceof Array ? [...obj] : {...obj};
    }
    return obj;
}

// 深拷贝
function _completeDeepClone(obj, visited = new WeakMap()) {
    if (typeof obj !== "object" || obj === null) return obj;
    // 防止循环引用
    if (visited.has(obj)) {
      return visited.get(obj);
    }
    // 获取对象的构造函数
    const constructor = obj.constructor;
    // 处理特殊对象类型~正则对象和时间对象、弱引用对象
    if(/^(RegExp|Date|WeakMap|WeakSet)/.test(constructor.name)) {
        const res = new constructor(obj);
        visited.set(obj, res);
        return res;
    }
    // Map
    if (constructor === Map) {
      const map = new Map();
      visited.set(obj, map);
      obj.forEach((value, key) => {
        map.set(key, _completeDeepClone(value, visited));
      });
      return map;
    }
    // Set
    if (constructor === Set) {
      const set = new Set();
      visited.set(obj, set);
      obj.forEach((value) => {
        set.add(_completeDeepClone(value, visited));
      });
      return set;
    }
    // 处理函数对象和箭头函数
    if(constructor === Function) {
        let res;
        if(!obj.hasOwnProperty("prototype")) { // 箭头函数
            // res = new Function(`return ${obj.toString()}`)()
            res = eval(obj.toString());
            visited.set(obj, res); // 避免循环引用
            return res;
        }
        // 考虑到构造函数和普通对象
        res = function(...args) {
            return obj.call(this, ...args);
        }
        visited.set(obj, res); // 避免循环引用
        // 普通对象的自身的属性,比如fn.a = 2这种静态属性
        Object.keys(obj).forEach(key => res[key] = obj[key]);
        // 原型继承,寄生组合继承,复制该函数的原型链
        res.prototype = Object.create(obj.prototype);
        res.prototype.constructor = res;
        return res;
    }
    // 处理普通对象和数组
    const result = Array.isArray(obj) ? [] : {};
    visited.set(obj, result);
    // 获取对象的所有属性名,包括不可枚举属性
    const props = Object.getOwnPropertyNames(obj); // 不可枚举类型
    const symbolProps = Object.getOwnPropertySymbols(obj); // Symbol类型
    props.concat(symbolProps).forEach(key => {
        const descriptor = Object.getOwnPropertyDescriptor(obj, key);
        if(descriptor) {
            const { value, writable, enumerable, configurable } = descriptor;
            Object.defineProperty(result, key, {
                value: _completeDeepClone(value, visited),
                writable, enumerable, configurable
            })
        }
    });
    return result;
}

数据类型

Boolean\String\Number\BigInt\Int\undefined\null

继承,原型链

  • 看我深拷贝中的函数拷贝说我继承学的很不错

tcp三次握手

  • syn
  • ack/syn
  • ack

syn确认码是怎么+1

tcp4次挥手

  • fin
  • ack
  • fin
  • ack

为什么需要tcp4次挥手,3次不就行吗?

面试官和我说也有tcp3挥手,将fin和ack一起发送

OSI七层模型

网络死亡几连问,问麻了

http状态码

反问

百度二面(4.24)

实习多久

哈哈开始画饼,让我最好实习到毕业且可提供转正名额

项目

手写防抖节流

手写dfs和bfs

简单的算法

// 用 JavaScript 写一个函数,输入 int 型,返回整数逆序后的字符串。如:输入
// 整型 1234,返回字符串“4321”。要求必须使用递归函数调用,不能用全局变量,
// 输入函数必须只有一个参数传入,必须返回字符串

function getR(num) {
  if(parseInt(num) !== num) {console.log("Invalid number");return;}
  let res = '';
  G(String(num));
  return res;
  function G(str) {
    if(str.length === 0) return;
    res += str[str.length - 1];
    G(str.slice(0, -1));
  }
}
console.log(getR(23.40))
// 优化
function reverseInt(num) {
    if(parseInt(num) !== num) throw Error("Invalid number");
    if (num < 10) return num.toString();
    const lastDigit = num % 10;
    const remainingDigits = Math.floor(num / 10);
    const reversed = reverseInt(remainingDigits);
    return lastDigit.toString() + reversed;
}
const reversed = reverseInt(12340);
console.log(reversed); // "4321"

轮播图实现

npm执行过程

项目中测试方面

  • 用pnpm workplace

盒模型

css文字截断

.truncate {
  display: -webkit-box;
  -webkit-line-clamp: 2; /* number of lines to show */
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

flex实现两边大小固定,中间自适应

<!DOCTYPE html>
<html lang="en">
  <body>
    <style>
      div {
        display: flex;
        flex-direction: row;
      }
      div div {
        height: 100px;
      }
      div div:nth-child(1) {
        width: 100px;
        background-color: aqua;
      }
      div div:nth-child(2) {
        width: 100%;
        background-color: rgb(255, 0, 0);
      }
      div div:nth-child(3) {
        width: 100px;
        background-color: rgb(0, 0, 0);

      }
    </style>
    <div class="div">
      <div></div>
      <div></div>
      <div></div>
    </div>
  </body>
</html>

也可以用grid和table布局实现

<style>
/* .container {
  display: table;
  width: 100%;
}
.left, .right {
  background-color: antiquewhite;
  display: table-cell;
  width: 100px;
  height: 100px;
}

.middle {
  display: table-cell;
  height: 100px;
} */
.container {
  display: grid;
  grid-template-columns: 100px auto 100px;
  width: 100%;
}

.left, .right {
  background-color: antiquewhite;
  width: 100%;
  height: 100px;
}

.middle {
  background-color: rgb(0, 0, 0);
  width: 100%;
  height: 100px;
}
</style>
<div class="container">
   <div class="left"></div>
   <div class="middle"></div>
   <div class="right"></div>
</div>

百度三面(4.27)-> 第二天OC

主管面,该说不说,人真的特别好,后面还来找我,说有变动直接找她

自我介绍,部门介绍

哪里人,有没有谈恋爱

不知道为什么问我有没有谈恋爱?很奇怪

学习情况,实习多久,入职时间

项目介绍

项目中遇到的难点或者难以解决的地方

项目启动需要制定风险以控制突发情况

聊天

哈哈说我普通话不太标准,问我是不是广东人,笑的,被发现了😂

面评

说对我很满意,会联系hr

写在结尾

还面了小米,不过一面后不想面了,这个时候已经接了offer啦!!!

PS:滴滴约面了,离谱!3月投的,现在约。。。

祝各位全部 OC!