前端面视经历笔记

声明

本文章仅作为我的笔记,不作为参考。

面后感

本次面视带给我的感觉就是:自我能力还需要提升。对于面视官所说的背景还可以,我认为我的背景是不够的,也是不够自信。因为我仅仅是个三本的本科大学生,在前端领域也没有深造,仅仅是因为我在学校的工作中更多的是前端开发。实验室里前端开发在我这一届也比较少,给了我种错觉:我已经会的足够多了。
然而结果可想而知~
一大早六点就起来前往公司所在城市去面视。早到了还有点不知所措,通过BOSS联系HR之后才进去的大楼。进去后在前台拿到了前端面试题以及信息表。让我重现当时的题目吧。

笔试题

题目可能有点乱或少。等我想起来再补充吧。先复习。

1. JS的数据类型有哪些?

undefind, null, boolean, string, symbol, number, bigint。

我当时答了什么呢?
我当时答了undefind, string, number, object, set, map, symbol
脑子里只有七种,没有知识体系支撑着我的面视,最终的结果是答出了非常离谱的答案。
object, set, map都是引用数据类型才对。包括Function,Array都是引用数据类型。
第一题就答得非常离谱了。

2. 前端有哪几种存储方式?

cookie: 储存再用户本地终端的数据
web storage API: {
	localStorage: 用于长久保存网站的数据,没有过期时间。(用户可删除)
	sessionStorage: 用于临时保存同一窗口或标签页的数据,在关闭窗口或标签页后会删除。
}
indexedDB: 浏览器提供的本地数据库,可以用js脚本创建和操作。允许储存大量数据,提供查找接口,还能建立索引。

我回答:3种。
笑死,我脑子里只有数量,没有具体的东西。对数量敏感是吧。

3. 手写防抖节流。

// 防抖
//业务逻辑
function task(){
    console.log(this.value);
}
function debounce(fn, delay){
    var time = null;
    return function(){
        if(time != null){
            clearTimeout(time)
    }
    time = setTimeout(() => {
            task.call(this)
        }, delay);
    } 
}
/*-------------------------------------------------------------------------------*/
//节流
//业务逻辑
function task(){
    console.log('触发');
}
function throttle(fn,delay){
    var flag = true;
    var time = null;
    return function(){
        if(flag){
            time = setTimeout(() => {
                task.call(this)
                flag = true;
            }, delay)
        }
        flag = false;
    }
}

我的答案:

// 防抖
let timer = null;
function debounce() {
	if (timer !== null) {
		return;
	}
	timer = setTimeout(() => {
		// 业务逻辑
		clearTimeout(timer);
	}, 100);
}
// 节流
let timer = null;
function throttle() {
	if (timer !== null) {
		timer = setTimeout(() => {
			// 业务逻辑
			clearTimeout();
		}, 100);
	}
}

面试官说的我写的两个是一个意思,好像。。。确实不知道是当时太紧张了写得有问题还是如何,可能跟我的答案不太一样。然后问我防抖节流的定义。
我答:
防抖:单位时间内只执行一次。
节流:单位时间内只执行最后一次。
这么再回去一看,确实,应该是我的节流写的有问题。应该覆盖上一个节流事件。。。

4. 数组操作:pop、push、shift、unshift的区别?

这个很简单,没问题。

5. this指向以及作用域。

当时是给了这么一道题。

var name = 1;
const obj = {
	name: 2,
	objFunc: function() {
		return function() {
			return this.name;
		}
	}
}
console.log(obj.objFunc()());

问输出是什么?
我的理解是这是一个闭包,this的上下文环境应该是通过obj.objFunc()调用后,当前的上下文环境是obj,再调用一次后进入匿名函数,上下文环境在堆栈中应该是obj?我理解了这应该是一个闭包?然后this.name应该是2?
然而答错了。回来用vscode跑一次试试。
额…在nodejs环境中是undefine, 在浏览器环境中是1。为何?
问了师兄。噢~内部this的指向是全局。好嘛,还是上下文环境不熟悉。js运行不熟悉。

6. http状态码

1xx: 请求信息
	表明这是一个临时性相应。此相应状态由状态行和可选的HTTP头组成,以一个空行结尾。HTTP /1.1以上
	100 *请继续请求 
	101 请切换协议
	102 将继续执行请求
2xx: 成功状态
	表明请求成功。
	200 *请求成功
	201 *请求已被接受,等待资源响应。
	202 *请求已被接受,但尚未处理。
	203 请求已成功处理,结果来自第三方拷贝。
	204 *请求已成功处理,但无返回内容。
	205 请求已成功处理,但需重置内容。
	206 请求已成功处理,但仅返回了部分内容。
	207 请求已成功处理,返回了多个状态的XML消息。
	208 请求已发送。
	226 已完成相应。
3xx:重定向状态
	表示客户端需要采取更进一步的行动来完成请求。通常用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明。
	300 *返回多条重定向供选择。
	301 *永久重定向。
	302 *临时重定向。
	303 当前请求的资源在其他地址。
	304 *请求资源与本地缓存相同,未修改。
	305 必须通过代理访问。
	306 (已废弃)请切换代理。
	307 临时重定向,同302.
	308 永久重定向,且禁止改变http方法。
4xx:客户端错误
	表示客户端的请求存在错误,导致服务器无法处理。除非响应的是一个HEAD请求,否则服务器就应该返回一个解释当前错误状态的实体,以及这是临时的还是永久性的状况。这些状态码适用于任何请求方法。浏览器应当向用户显示任何包含在此类错误相应中的实体内容。
	400 *请求错误,通常是访问的域名未绑定引起。
	401 *需要身份认证验证。
	402 *暂无标准约定。
	403 *禁止访问。
	404 *请求的内容未找到或已删除。
	405 *不允许的请求方法。
	406 *无法响应,因资源无法满足客户端条件。
	407 要求通过代理的身份认证。
	408 请求超时。
	409 存在冲突。
	410 资源已经不存在(过去存在)
	411 需要定义 Content-Length 头部字段
	412 头部不满足服务器条件
	413 请求实体大于服务器定义的限制。
	414 URI过长(服务器不接受)
	415 数据格式错误,拒绝请求
	416 URI过长(服务器不支持)
	429 限制请求速率
	431 请求头字段太大。
	451 请求不合法。
5xx:服务器端错误
	500 *服务器错误
	501 *服务器不支持该请求方法,请用GET和HEAD。
	505 *HTTP版本错误
	506 服务器内部配置错误。
	508 请求时无限循环
	510 *服务器需升级
	511 需要身份认证

当然面试官没问那么多。只是自己还需要熟悉一下。

7. 宏任务以及微任务的执行流程(浏览器的执行流程)

先上笔试题

const p = () => new Promise((resolve, reject) => {
  console.info(3);
  const p1 = () => new Promise((resolve, reject) => {
    console.info(2);
    setTimeout(() => {
      console.info(5)
      resolve(7);
    }, 0)
    resolve(6);
  });

  resolve(1);
  p1().then((res) => {
    console.info(res);
  });
});

console.info(4);
p().then((res) => {
  console.info(res)
});

没准备充分就去面视是这样的,简单的宏任务微任务也没做出来。
正确答案应该是4 3 2 6 1 5
我当时答了啥?我答了4 3 1 2 6 5
对事件循环、宏任务微任务的执行了解到太少了。
正确应该是在一次事件循环中,先执行所有的宏任务、宏任务执行结束后,再开始执行本次事件循环中的所有的微任务。
应该最简单的例子应该就是这个了吧。

for (let i = 0; i < 5; i++) {
	setTimeout(() => {
		console.info(i);
	}, 100);
}

输出五次5。
诶呀~这还敢跑去面试。

人事面

人事小姐姐是在BOSS上联系的。看过简历后马上就约线下面了,爽快得有点不知所措~但还是珍惜每一次的面视机会吧。
开始是自我介绍,然后讲讲自己的优势吧。面视经验少的我不知该说啥,我有优势的话估计就是在校项目做得多?但也都是些小项目。然后人事就让我拿这BOSS上的条例说说~emmm还行吧。

技术面

人事面完事就是技术面了。技术面是两位,一位leader一位面试官。
再来一次自我介绍,巴拉巴拉把自己做过的项目讲一大堆~
介绍完后就是八股拷打了吧!让我回忆回忆~

能记起来多少是多少吧~

  1. es6新特性有哪些
    我只是在回答名字,什么set map proxy async await symbol…
    想逐个展开,但是脑子已经不支持我展开了。明明才看过书了解Symbol的特性、proxy的特性来着…
    麻了。
  2. vue2 vue3
    咋个说…我只会封装组件…用组件…生命周期钩子我还得看着图才能讲…废
    倒是刚开始翻开《vue2深入浅出》,知道了vue2的数据监测用的defineProperty做的,然后用proxy重构。额…真就只会用喽。
  3. webpack工作原理
    应该写了解webpack配置的。笑死。
    面试官说,当编译less的时候,浏览器是不认识less文件的,需要webpack翻译成浏览器认识的css文件。这懂哪。我以为要回答的是比如如何将js模块化、如何将静态文件分类打包…然后就说不懂…汗流浃背了。感情我是来上课的
    相信如果真有人看的话,看到这已经看不下去了吧哈哈哈哈我有多菜。
  4. 深拷贝浅拷贝
    啊 这也是面试题的一个,我写的啥
    obj1 = JSON.parse(JSON.stringify(obj2));
    
    emmm好好好,可以是可以。面试官说有弊端,比如当数据类型是Date这种的时候,可能会丢失类型,有没有其他的方法。嗯!有很多来着。但是脑子里想不出来了。只记得有Object.assign()可以实现第一层的深拷贝,第二层就是浅拷贝了。咋说呐…真想不出来力。难道要纯手写个for循环去遍历拷贝?
    递归实现深拷贝:
function deepClone(target) {
    // WeakMap作为记录对象Hash表(用于防止循环引用)
    const map = new WeakMap()

    // 判断是否为object类型的辅助函数,减少重复代码
    function isObject(target) {
        return (typeof target === 'object' && target ) || typeof target === 'function'
    }

    function clone(data) {

        // 基础类型直接返回值
        if (!isObject(data)) {
            return data
        }

        // 日期或者正则对象则直接构造一个新的对象返回
        if ([Date, RegExp].includes(data.constructor)) {
            return new data.constructor(data)
        }

        // 处理函数对象
        if (typeof data === 'function') {
            return new Function('return ' + data.toString())()
        }

        // 如果该对象已存在,则直接返回该对象
        const exist = map.get(data)
        if (exist) {
            return exist
        }

        // 处理Map对象
        if (data instanceof Map) {
            const result = new Map()
            map.set(data, result)
            data.forEach((val, key) => {
                // 注意:map中的值为object的话也得深拷贝
                if (isObject(val)) {
                    result.set(key, clone(val))
                } else {
                    result.set(key, val)
                }
            })
            return result
        }

        // 处理Set对象
        if (data instanceof Set) {
            const result = new Set()
            map.set(data, result)
            data.forEach(val => {
                // 注意:set中的值为object的话也得深拷贝
                if (isObject(val)) {
                    result.add(clone(val))
                } else {
                    result.add(val)
                }
            })
            return result
        }

        // 收集键名(考虑了以Symbol作为key以及不可枚举的属性)
        const keys = Reflect.ownKeys(data)
        // 利用 Object 的 getOwnPropertyDescriptors 方法可以获得对象的所有属性以及对应的属性描述
        const allDesc = Object.getOwnPropertyDescriptors(data)
        // 结合 Object 的 create 方法创建一个新对象,并继承传入原对象的原型链, 这里得到的result是对data的浅拷贝
        const result = Object.create(Object.getPrototypeOf(data), allDesc)

        // 新对象加入到map中,进行记录
        map.set(data, result)

        // Object.create()是浅拷贝,所以要判断并递归执行深拷贝
        keys.forEach(key => {
            const val = data[key]
            if (isObject(val)) {
                // 属性值为 对象类型 或 函数对象 的话也需要进行深拷贝
                result[key] = clone(val)
            } else {
                result[key] = val
            }
        })
        return result
    }

    return clone(target)
}



// 测试
const clonedObj = deepClone(obj)
clonedObj === obj  // false,返回的是一个新对象
clonedObj.arr === obj.arr  // false,说明拷贝的不是引用
clonedObj.func === obj.func  // false,说明function也复制了一份
clonedObj.proto  // proto,可以取到原型的属性

又或者,用第三方库!
比如Lodash库中的cloneDeep方法

最后当然估计是看我很多都答得很差,属于那种有印象但是说不出来的情况。那就结束喽。Leader开始给我提建议,都一一听取记在心里啦。

最后

买本红宝书学起来吧。把浏览器工作原理也搞清楚再来投简历!再战!

  • 25
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Raoxiaomi.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值