记录广州申迪的前端面试
前言
记录广州申迪的前端面试。
找了一个月工作了,投了简历很多都是没回复的,一个月只面试了 4 家。
感觉要回家送外卖了。
正文
这个公司需要先笔试,所以在那里填了差不多 1 个小时题目。
基本数据类型和复杂数据类型
这个没什么好说的,看给的多少个空,一定要填的为 number
, string
, boolean
, undefined
, null
,空多的话再协商 symbol
和 bigint
。
复杂数据类型就是 object
对象。
盒子 margin-top 坍塌
给定两个块级盒子,上方盒子设置 margin-bottom: 10px
下方盒子设置 margin-top: 5px
,问两者的差距是多少。
这题主要考相邻盒子的 margin
坍塌(也称为外边距折叠)以及 BFC ,即 Block Formatting Context ,中文名为区块格式化上下文。
相邻盒子在默认情况下会发生 margin
坍塌,即会取 margin
大的一方作为两者的间距。所以该题答案为 10px
。
为了解决这种情况,需要让其中的一个盒子创建 BFC ,这样即可解决该问题,最简单地解决方法就是加上 overflow: hidden
使其创建 BFC 。
失焦的事件名
聚焦是 focus
,失焦是 blur
。
原型链
输出以下代码的结果
1 | function o(name) { |
问输出结果,这里需要对原型链有一些认识,o.protoType
和 i.__proto__
为相同的对象,每个实例化的对象的 __proto__
都指向它构造器的 protoType
。
接着我们需要知道,非箭头函数的调用的 this
取决于谁调用的它。
- 对于
i.__proto__.print()
此时this
为i.__proto__
。 - 对于
i.print()
此时this
为i
。
这里需要注意 i.print
和 i.__proto__.print
为同一个函数, i.print
在 i
上没有找到 print
方法后一直往原型链上面查找。
所以这道题的答案为 dd
和 ee
。
数组中插入元素的方法
这里给了三个空,应该是填 push
、 unshift
和 splice
。
PS:这里弄混了 shift
和 unshift
,写成 shift
了, shift
为弹出头元素,给自己菜麻了😅。
push
在尾部插入一个元素。unshift
在头部插入一个元素。splice
可以指定某个位置删除并插入元素,只需把第二个参数设置为 0 ,那么就不会删除元素了,再指定第三个以后的参数就可以往该位置插值了。
地址栏输入地址到显示页面的过程
纯八股文,这种直接百度。
深拷贝与浅拷贝
浅拷贝可以用很多内置的方法实现,比如字面对象的展开,数组的展开:
1 | const o = { a: 1, b: 2 }; |
1 | const o = [1, 2, 3]; |
或者使用 Object.assign 来进行浅拷贝:
1 | const o = { a: 1, b: 2 }; |
深拷贝其实就是递归浅拷贝,当然也有一些方便的方法来进行快速的深拷贝。
如果对象不包含无法序列化的类型(比如 Function , Symbol , DOM 对象等),且没有循环引用,则可以使用 JSON.parse(JSON.stringify(obj))
。
1 | const o = { a: 1, b: 2 }; |
如果你的执行环境够现代,你还可以使用 structuredClone 原生接口,它很好地处理了循环引用的情况,而且支持所有支持结构化克隆的类型,当然对于其他类型也是无法克隆的。
除此之外,还可以使用三方库,比如 lodash 的 clone ,不过它也是实现了结构化克隆的类型,如果还要支持其他不支持的类型,那就得手写克隆函数来处理对应的情况了。
手写一个节流(throttle)函数
可以基于时间戳或者 setTimeout
来实现。
setTimeout
的版本我们可以参考 radash 的实现:
1 | const throttle = ({ interval }, func) => { |
基于 Date.now
实现:
1 | function throttle(func, delay) { |
手写一个解析地址栏参数的函数
写一个函数 ,要求根据当前 href
来解析 query
参数,即,如果访问 http://example.com?a=1&b=2
,那么函数 fn("a")
返回 1
, fn("b")
返回 2
。
这道题直接使用 URL 对象来搞定,手写实现是不可能,只能调调 api 这个样子:
1 | function fn(key) { |
当然如果要手写实现的话,其实就是那几个步骤:
- 通过
location.search
拿到查询字符串。 - 去掉
?
,然后通过&
分割。 - 接着每一项通过
=
分割,索引0
为键,索引1
为值。 - 返回对应值。
1 | function fn(searchKey) { |