前言
在前端面试中,this
指向、闭包
理解与应用、原型 Prototype
等知识点都是经常考察的。那有没有面试题会一次性涉及到这三块儿呢?当然是有的!
手撕一个bind函数
就是这样一道经典的面试题!
原生bind函数
bind()
方法创建一个新的函数,在 bind()
被调用时,这个新函数的 this
被指定为 bind()
的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
引自MDN
举个栗子🌰:
// 创建Person类 class Person { // 定义私有属性 name/age private name: string; private age: number; // 构造函数,初始化时指定name、age的值 constructor(name: string, age: number) { this.name = name; this.age = age; } // 定义printInfo方法,输出信息 printInfo(sex: string) { console.log(this.name, this.age, sex); } } // 实例化类,获取对象 const p = new Person("Jack", 12); // 调用printInfo方法 p.printInfo("男"); // Jack 12 男 // 使用bind更改this指向,同时传入参数,返回一个新函数 const printInfo = p.printInfo.bind({ name: "rose", age: 11 }, "女"); // 调用函数 printInfo(); // rose 11 女
梳理一下bind函数的特点:
- bind调用完成,返回的是一个新函数;
- bind调用时,传入的第一个参数是新的this对象,后续其他参数作为了返回的新函数调用时的参数值
通过prototype
自定义bind函数的实现
Up Code ~ 上代码 ~
/** * @description 自定义bind方法实现 * @param context any 传入的this对象 * @param bindArgs any[] 传入的参数 */ // @ts-ignore Function.prototype.myBind = function (context: any, ...bindArgs: any[]) { // 原函数的this // @ts-ignore const self: any = this; // 返回一个新函数 - 返回的新函数也是可以继续传递参数的 return function (...args: any[]) { // 最终的参数 const finalArgs = bindArgs.concat(args); // 返回原函数的执行结果 return self.apply(context, finalArgs); }; };
这里一定要注意,.myBind = function () {}位置,不能使用箭头函数,因为一旦使用箭头函数,this指向就确定了,self变量就不能再指向调用myBind的函数了
功能测试:
// @ts-ignore const printInfo2 = p.printInfo.myBind({ name: "rose", age: 11 }, "女"); printInfo2(); // rose 11 女
相当完美~
结语
手撕一个bind函数这道面试题,考察的知识点还是非常多的,this
指向问题、prototype
原型问题、ES6函数剩余参数、闭包
等等,是一道综合性较高的面试题。