高级前端一面经典手写面试题汇总
图片懒加载
可以给 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数组中提前注册的回调








评论