JS前端面试手写apply和bind实例
一条会coding的Shark 人气:0前言
面试官问:“聊一聊你理解的 apply
和 bind
。”
于是我便开始开始介绍起这两个知识点,最后顺带提了它们的实现代码。
这不提倒还好,一提就出了大事,一下子给面试官找到了面试题目。
面试官紧接着说:“既然你提到了代码,那就手写一下它俩吧。”
我一下子不知所措。虽然我了解过 apply
和 bind
手写代码,但是现在让我立马手写出来它们,实属有些困难。
不过最后还是硬着头皮写了一下,但是结果不尽人意。
apply && bind
函数 apply
和 bind
在日常开发中经常会被用到,理解它们的作用以及逻辑至关重要。所以今天我们来探讨一下它们的实现逻辑,并对它们进行手写,来学会如何轻松手写它们。
apply && bind 作用
知己知彼,方能百战百胜。在进行手写之前,我们先来简单聊一下它们。 众所周知,apply 和 bind 作用是改变函数的调用对象。很多人对这个不是很理解,什么是函数的调用对象呢?其实简单点理解就是改变函数的 this
对象指向。因为这时候 this
在函数就充当了一个调用的作用,而 apply 和 bind 就是有着改变 this
指向的作用。
apply
的其他作用,是改变对象的执行上下文,并且是立即执行的。 bind
也能改变对象的执行上下文。
相同点 VS 不同点
它们的相同点在于都可以改变 this
的指向,并且传入的第一个参数都是绑定的 this
,不同点在于 bind 返回的是一个改变了 this
指向的函数,便于稍后调用,而 apply 会立即调用。另外 apply 是一次性传入参数,而 bind 可以分为多次传入。
轻松手写
有了理论基础,我们可以开始手写部分了。
手写实现 apply
我们先来看 apply,apply 手写实现其实很简单,大致思路如下:
首先用 typeof
来检查调用 apply
的对象是否为函数,如果不是则抛出错误。然后将函数作为传入的 context
对象的一个属性,并调用该函数。 最后调用之后通过 delete
删除该属性,避免对传入对象造成污染。context
代表上下文对象。
代码如下:
Function.prototype.apply = function (context, args) { if (typeof this !== 'function') { console.log('not a function') } const fn = Symbol() context[fn] = this context[fn](...args) delete context[fn] }
这里使用到了新的 Symbol
数据类型,主要是避免在把函数赋值给 context
对象的时候,因为属性名冲突而覆盖掉原有属性。
手写实现 bind
相比较与 apply 手写,我个人觉得 bind 手写会相对复杂一些。bind 手写实现思路如下:
和之前一样,首先判断调用对象是否为函数,然后获取其余传入参数值,并创建一个函数返回。最后根据调用方式,传入不同的绑定值。
函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this
给 apply 调用,其余情况都传入指定的上下文对象 context
。
代码如下:
Function.prototype.myBind = function(context) { if (typeof this !== "function") { console.log("Error"); } let args = [...arguments].slice(1), fn = this; return function Fn() { return fn.apply( this instanceof Fn ? this : context, args.concat(...arguments) ); }; };
总结
关于它们的手写就到这里了,相信下次再面对同样的问题时处理起来就能游刃有余了。这两个手写各有各的特点,我个人建议可以多写写 bind 的手写,我觉得它会比 apply 出错率更高。
虽然文章中是以手写 apply 和 bind 为主,但是并不缺少 js
相关知识点,比如 this
指向问题,总之,js
很重要,既是基础又是重点。
加载全部内容