详解改变this指向的三种方法call apply bind及重写(模拟)
2020-03-06 15:09
1496 查看
call方法
- 语法:函数.call([context],[params1],…)
- 函数基于原型链找到Function.prototype.call这个方法,并且把它执行,在call方法执行的时候完成了一些功能
- 首先让当前函数执行
- 把函数中的THIS指向改为第一个传递给CALL的实参
- 把传递给CALL其余的实参,当做参数信息传递给当前函数
- 如果执行CALL一个实参都没有传递,非严格模式下是让函数中的THIS指向WINDOW,严格模式下指向的是UNDEFINED
window.name = 'WINDOW'; let obj = {name: 'OBJ'}; function fn(n,m) { console.log(this.name); } fn(10,20); //=>this:window 严格下是undefined fn.call(obj); //=>this:obj n/m=undefined fn.call(obj,10,20); //=>this:obj n=10 m=20 fn.call(10,20); //=>this:10 n=20 m=undefined fn.call(); //=>this:window 严格下是undefined fn.call(null); //=>this:window 严格下是null(第一个参数传递的是null/undefined/不传,非严格模式下this指向window,严格模式下传递的是谁this就是谁,不传this是undefined) 还可以基于call让类数组使用数组方法 function sum(){ //=>把ARGUMENTS转换为数组:借用数组原型上的SLICE方法,只要让SLICE中的THIS指向ARGUMENTS,就相当于把ARGUMENTS转换为新数组 //let arg=Array.prototype.slice.call(arguments,0); let arg=[].slice.call(arguments,0); //=>数组求和 return eval(arg.join('+')); } let total=sum(10,20,30,40); //100 或这样循环元素类数组 [].forEach.call(listArr,(item,index)+>{ console.log(item,index); })
apply
- apply方法和call方法作用一样,修改函数中的this,并且让这个修改this之后的函数执行;
- 但是传参方式不同;call方法是一个一个的传递实参给sum的,apply是把实参都放到一个数组中,数组项是传递给sum的实参
骚操作 求数组最大值 Math.max 只能传一组数但不能传递数组 let ary = [12,23,13,24,10,25], n = Math.max.apply(null,ary); n //25 其中apply第一个参数是谁并不重要,只是想基于它传值的方式传给Math.max
bind
- 作用:预先改变函数中的this,不让函数执行,返回一个修改this后的新函数。
window.name='WIN'; function fn() { console.log(this.name); } var obj = { name: "OBJ", fn: () => { console.log(this.name); } }; fn.bind(obj); //不会执行 fn.bind(obj)(); //=>会执行bind OBJ let shark = fn.bind(obj); shark(); //=>也会执行 OBJ obj.fn.bind(obj)(); // 这个结果是WIN // 因为箭头函数没有this!!!不懂请看前一篇文章
重写(模拟)这些方法
·模拟一个call方法· ~function () { /*生成随机函数名:时间戳的方式*/ function queryRandomName () { let time = new Date().getTime(); return '$zhufeng' + time; } // 模拟CALL方法改变函数中的THIS function changeThis(context = window,...arg){ let _this = this, result = null, ran = queryRandomName(); context[ran] = _this; result = context[ran](...arg); delete context[ran]; return result; }; Function.prototype.changeThis = changeThis; }(); ·模拟一个apply方法· ~function(){ /*生成随机函数名:时间戳的方式*/ function queryRandomName () { let time = new Date().getTime(); return '$zhufeng' + time; } function changeThis (context = window, arg = []) { let _this = this, result = null, ran = queryRandomName(); context[ran] = _this; result = context[ran](...arg); delete context[ran]; return result; }; Function.prototype.changeThis = changeThis; }(); ·模拟一个bind方法· ~function(){ function changeThis(fn,...ary) { var that = this; return function (...arr) { that.apply(fn,ary.concat(arr)); } } Function.prototype.changeThis = changeThis; }(); 最后来道题吧 // 阿里的面试题 function fn1(){console.log(1);} function fn2(){console.log(2);} fn1.call(fn2); fn1.call.call(fn2); Function.prototype.call(fn1); Function.prototype.call.call(fn1);
call图解
- 小白扫盲自我修炼,新人定有不足的还请大佬不吝赐教。
- 觉得文章还不错的话就点个赞吧~~
- 友善发言的人运气不会太差哦
- 师承周啸天是也
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- js中改变this指向的三个常用方法bind,call和apply
- JavaScript改变this指向apply、call和bind方法
- JS中改变this指向的方法(call和apply、bind)
- JavaScript中call,apply,bind方法的总结(改变this指向)
- JS中改变this指向的方法(call和apply、bind)
- call,apply,bind方法改变this指向的原理
- js中this的改变指向的方法:call和apply、bind
- 改变【this】指向的三种方式(call、apply、bind)对比
- 函数中的this指向,以及 修改this指向的 call/apply/bind方法
- js的this指针指向谁,以及相关的call、apply、bind方法
- js call() apply() bind() -改变this指向
- JavaScript---浅谈函数this指向之 call()、apply()、bind()方法
- 函数内this指向的不同场景,以及如何改变this的指向(bind,call,apply)
- 改变this指向:call,apply,bind
- JavaScript中的call(),apply(),bind()方法 关于this指向
- js改变this指向方法call,apply;jq改变this指向方法$.proxy()
- 改变this指向(call、apply、bind)
- call,apply,bind改变this指向
- 改变this的三种方式:call,apply,bind简述
- Javascript中call,apply,bind方法的详解与总结