call、apply、bind是在前端开发过程中常用的,改变函数中this指向的方法,关于三种方法的详细使用,本文不做过多赘述。主要分享call、apply、bind三种方法的区别,即各自的封装方式。
1、call、apply、bind区别
-
call、apply
- 直接执行函数,替代函数中的this
- 一般应用于要即时执行的函数中替代this
- call和apply的第一个参数都是为了替换函数中的this指向
- call的其他参数正常传入,apply的其他参数以数组方式传入
function fn(a, b) { this.a = a; this.b = b; console.log(this); return this; } /* 直接执行函数 */ fn(3, 5); // 结果:Window console.log(a, b); // 结果:3 5 // 函数执行后,this指向window,此时a和b是window下的属性,可以直接打印出来 /* 如果使用call或apply */ // call和apply的第一个参数是为了替换函数中的this指向 // call fn.call({}, 5, 9); // 结果:{a: 3, b: 5} // apply fn.apply({}, [12, 15]); // 结果:{a: 12, b: 15}
-
bind
- 返回一个新函数,这个函数中的this都被替代为绑定的对象,当执行时this就会全部指向这个对象
- 一般用于回调函数中替代this指向
function fn(a, b) { this.a = a; this.b = b; return this; } var fn1 = fn.bind({}); var obj = fn1(3, 5); console.log(obj); // 结果:{a: 3, b: 5} // 在开发过程中,常见的还有以下写法 var obj2 = fn.bind({})(3, 5); console.log(obj2); // 结果:{a: 3, b: 5}
2、方法封装
-
call
Function.prototype.callHarvey = function (obj) { // 如果该方法的调用者不是一个函数,则抛出错误信息 if (typeof this !== "function") throw new Error(this + "is not a function!"); // 重定向this var _this = Object(obj) || window; // 创建一个新数组,用于获取第一个参数后的所有参数 var newArr = []; // 将call的调用函数传给重新定向的this _this.callback = this; // 遍历arguments,第一个之后的参数push到newArr中 for (let i = 1; i < arguments.length; i++) newArr.push(arguments[i]); // 使用apply方法,传入重新定向的this和newArr _this.callback.apply(_this, newArr); // 清除callback,防止污染this指向的对象 delete _this.callback; }
-
apply
Function.prototype.applyHarvey = function (obj, initArr) { // 如果该方法的调用者不是一个函数,则抛出错误信息 if (typeof this !== "function") throw new Error(this + "is not a function!"); // 重定向this var _this = Object(obj) || window; // 如果没有传入其他参数,则将一个空数组赋值给arr var arr = initArr || []; // 将call的调用函数传给重新定向的this _this.callback = this; // 使用ES6进行解构赋值,执行_this.callback _this.callback(...arr); // 防止污染this指向的对象 delete _this.callback; }
-
bind
Function.prototype.bindHarvey = function (obj) { // 如果该方法的调用者不是一个函数,则抛出错误信息 if (typeof this !== "function") throw new Error(this + "is not a function!"); // 重定向this var _this = Object(obj) || window; // 将call的调用函数传给重新定向的this _this.callback = this; // 返回函数 return function () { _this.callback.apply(_this, Array.from(arguments)); // 防止污染this指向的对象 delete _this.callback; } }
封装这三种Function方法的形式不唯一,常见的方法还有使用eval方式进行封装(即通过拼接字符串,然后通过eval方法执行),但是因为个人认为eval方法非常耗性能,且在实际项目中影响安全性,所以不推荐使用。
如果有什么不准确的地方,欢迎私信或留言指出,共同进步~~
网友评论