前端面试题:Call的用法及实现

网站建设3年前发布
23 0 0

20230305223113647dbff66855fa08db555060e8f75d1bc3fd04771,大家好,我是前端西瓜哥。,我之前写了一篇手写 bind 的文章,里面直接使用了原生 call 方法。,有读者说他面试的时候这个 call 也要求自己实现的。,那我们今天来手写 call。apply 的实现也是一样,只是调用形式有点区别。,我们先看看 Function.prototype.call() 的用法。,call() 可以修改函数调用时 this 的指向,其余参数则会作为原函数的参数。,call 接收的参数:,例子:,上面代码中,this 指向了 obj。,Function.prototype.apply 也是类似,但它的参数是以数组的形式存在的。上面的 call 写法等价于:,JS 函数中的 this 指向是在运行时决定的,里面的规则比较多,但其中有一条是:,如果是通过 obj.fn() 执行时,this 会指向前面的 obj 对象。,那我们只要将传入对象和原方法进行拼接,拼成上面这个 对象.方法 的形式,执行时,this 就能乖乖指向我们传入的 thisArg 了。,实现如下:,这里我们用 Symbol() 创建了一个唯一的 key,是为了防止覆盖掉 thisArg 原有的同名属性。,执行完后,记得将这个 key 移除掉,防止污染 thisArg 对象。,如果面试官要你用 ES5 实现,那会复杂很多,我这里也给出实现吧。,在这之前,我们先来学点前置知识。,利用了严格模式下,如果没有指定 this(通过 bind、call、前面带对象等方式),就会得到 undefined 的机制。如果是非严格模式,this 会拿到全局变量。,ES6 的扩展运算符 ... 能够将数组 args,进行拆分按顺序放到函数中。,那我们用 ES5,也能将数组拆分成一个参数塞到函数中吗?,可以,但我们要用一点奇技淫巧:Function 方法。,Function 方法用得比较少。它可以在运行时创建一个函数,最后一个参数是函数体内容,前面的参数则是函数的参数。,fn(...args) 的 ES5 实现为:,Function 方法可以根据参数长度,动态生成 new Function('fn', 'a', 'return fn(a[0], a[1])') 形式的函数,来实现类似扩展运算符的效果。,还有种写法是用 eval,也能根据字符串动态生成可执行代码。,为了不被干扰,上面的代码实现 忽略掉了一些细节。,另外我的实现,没有考虑严格模式。严格模式下,如果 thisArg 是 undefined 或 null,直接执行原函数就行了,不需要拼装成 obj.fn 形式。,手写 call,核心在于通过另一种修改 this 指向的方式:obj.fn() 执行时 this 会指向 obj 对象。,手写 apply 也是一样的逻辑,还能少写一个 slice 方法。

© 版权声明

相关文章