高级前端一面经典手写面试题汇总
图片懒加载
可以给 img 标签统一自定义属性data-src='default.png'
,当检测到图片出现在窗口之后再补充 src 属性,此时才会进行图片资源加载。
请实现一个 add 函数,满足以下功能
考点:
使用闭包, 同时要对 JavaScript 的作用域链(原型链)有深入的理解
重写函数的
toSting()
方法
实现数组的 push 方法
解析 URL Params 为对象
手写深度比较 isEqual
思路:深度比较两个对象,就是要深度比较对象的每一个元素。=> 递归
递归退出条件:
被比较的是两个值类型变量,直接用“===”判断
被比较的两个变量之一为
null
,直接判断另一个元素是否也为null
提前结束递推:
两个变量
keys
数量不同传入的两个参数是同一个变量
递推工作:深度比较每一个
key
实现千位分隔符
正则表达式(运用了正则的前向声明和反前向声明):
参考 前端进阶面试题详细解答
手写 Object.create
思路:将传入的对象作为原型
实现一个拖拽
实现数组的 flat 方法
将 js 对象转化为树形结构
代码实现:
手写 call 函数
call 函数的实现步骤:
判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
判断传入上下文对象是否存在,如果不存在,则设置为 window 。
处理传入的参数,截取第一个参数后的所有参数。
将函数作为上下文对象的一个属性。
使用上下文对象来调用这个方法,并保存返回结果。
删除刚才新增的属性。
返回结果。
实现 JSON.parse
此方法属于黑魔法,极易容易被 xss 攻击,还有一种new Function
大同小异。
Function.prototype.call
于call
唯一不同的是,call()
方法接受的是一个参数列表
函数珂里化
指的是将一个接受多个参数的函数 变为 接受一个参数返回一个函数的固定形式,这样便于再次调用,例如 f(1)(2)
经典面试题:实现add(1)(2)(3)(4)=10;
、 add(1)(1,2,3)(2)=9;
Object.is
Object.is
解决的主要是这两个问题:
实现 getValue/setValue 函数来获取 path 对应的值
实现
使用 promise 来实现
创建 enhancedObject
函数
使用 enhancedObject
函数
以上代码运行后,控制台会输出以下代码:
通过观察以上的输出结果可知,使用
enhancedObject
函数处理过的对象,我们就可以方便地访问普通对象内部的深层属性。
reduce 用法汇总
语法
reduceRight()
该方法用法与reduce()
其实是相同的,只是遍历的顺序相反,它是从数组的最后一项开始,向前遍历到第一项
1. 数组求和
2. 数组最大值
3. 数组转对象
4. 扁平一个二维数组
5. 数组去重
6. 对象数组去重
7. 求字符串中字母出现的次数
8. compose 函数
redux compose
源码实现
实现 bind 方法
bind
的实现对比其他两个函数略微地复杂了一点,涉及到参数合并(类似函数柯里化),因为bind
需要返回一个函数,需要判断一些边界问题,以下是bind
的实现
bind
返回了一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过new
的方式,我们先来说直接调用的方式对于直接调用来说,这里选择了
apply
的方式实现,但是对于参数需要注意以下情况:因为bind
可以实现类似这样的代码f.bind(obj, 1)(2)
,所以我们需要将两边的参数拼接起来最后来说通过
new
的方式,对于new
的情况来说,不会被任何方式改变this
,所以对于这种情况我们需要忽略传入的this
简洁版本
对于普通函数,绑定
this
指向对于构造函数,要保证原函数的原型对象上的属性不能丢失
注意:
bind
之后不能再次修改this
的指向,bind
多次后执行,函数this
还是指向第一次bind
的对象
实现一个 JSON.parse
用来解析 JSON 字符串,构造由字符串描述的 JavaScript 值或对象。提供可选的 reviver 函数用以在返回之前对所得到的对象执行变换(操作)
第一种:直接调用 eval
避免在不必要的情况下使用
eval
,eval()
是一个危险的函数,他执行的代码拥有着执行者的权利。如果你用eval()
运行的字符串代码被恶意方(不怀好意的人)操控修改,您最终可能会在您的网页/扩展程序的权限下,在用户计算机上运行恶意代码。它会执行 JS 代码,有 XSS 漏洞。
如果你只想记这个方法,就得对参数 json 做校验。
第二种:Function
核心:Function 与 eval 有相同的字符串参数特性
在转换 JSON 的实际应用中,只需要这么做
eval
与Function
都有着动态编译 js 代码的作用,但是在实际的编程中并不推荐使用
手写 Promise.then
then
方法返回一个新的 promise
实例,为了在 promise
状态发生变化时(resolve
/ reject
被调用时)再执行 then
里的函数,我们使用一个 callbacks
数组先把传给 then 的函数暂存起来,等状态改变时再调用。
**那么,怎么保证后一个 **then**
里的方法在前一个 ****then**
(可能是异步)结束之后再执行呢? 我们可以将传给 then
的函数和新 promise
的 resolve
一起 push
到前一个 promise
的 callbacks
数组中,达到承前启后的效果:
承前:当前一个
promise
完成后,调用其resolve
变更状态,在这个resolve
里会依次调用callbacks
里的回调,这样就执行了then
里的方法了启后:上一步中,当
then
里的方法执行完成后,返回一个结果,如果这个结果是个简单的值,就直接调用新promise
的resolve
,让其状态变更,这又会依次调用新promise
的callbacks
数组里的方法,循环往复。。如果返回的结果是个promise
,则需要等它完成之后再触发新promise
的resolve
,所以可以在其结果的then
里调用新promise
的resolve
注意:
连续多个
then
里的回调方法是同步注册的,但注册到了不同的callbacks
数组中,因为每次then
都返回新的promise
实例(参考上面的例子和图)注册完成后开始执行构造函数中的异步事件,异步完成之后依次调用
callbacks
数组中提前注册的回调
评论