唯心主义蠢货的[js知识总结] call apply bind改变this指向

手撸bind apply call 改变函数的this指向


call.(obj,arg1,arg2,arg3…)

call的用法:

首先传入一个对象,再传入对应的参数进行解构赋值,返回函数结果。

错误情况:call中没有传入参数,则默认obj为window

代码实现

  1. 函数调用.call来改变内部的this指向,所以我们可以在Function.prototype中再新增添一个方法作为我们自己的call
var value = 3;
var obj = {
	value:4
}
function test(  ) {
	console.log(this.value);
}
Function.prototype.newCall = function (  ) {
    console.log(this);
}
test.newCall(obj); // test
  1. 我们发现此时输出的this即为当前被调用的函数,所以如果我们在这个对象上添加一个fn属性,然后把函数赋给这个属性,然后调用这个属性,则可以直接在内部改变this指向
var value = 3;
var obj = {
	value:4
}
function test(  ) {
	console.log(this.value);
}
Function.prototype.newCall = function ( that ) {
	console.log(this);
	console.log(that);	
	that.fn = this;
	that.fn();
}
test.newCall(obj); // test  obj   4
  1. 再对这个函数进行完善,将添加到对象中的东西删除掉

    1. 考虑解构赋值的情况( ES6 的不定参数 …args,在函数中args以数组形式存在, …args为拓展参数)

      …[ 2,3,6,“ss”] => 2 3 6 “ss”

    2. 考虑错误处理的情况,当非object时或者

    3. 考虑返回值情况(js的函数默认返回值为undefined)

var value = 3;
var obj = {
	value:4
}
function test( a,b,c ) {
	console.log(a+b+c);
	console.log(this.value)
}
Function.prototype.newCall = function ( that,...args ) {
    if(that.toString() !== "[object object]"){
    	throw that+" is not an Object";
    }
    that = that || window; // that为空(undefined null)  则为window
    that.fn = this;
    const result = that.fn(...args);
    delete that.fn;
    return result;
    }
m = test.newCall(obj,1,2,3); // 6 4
console.log(m); // undefined

apply.(obj,[arg])

apply的用法

apply在用法上和call基本相同,唯一不同的是apply中第二个参数为一个参数数组

Function.prototype.newApply = function( that , arg){
    if(that.toString() !== "[object object]"){
    	throw that+" is not an Object";
    }
    that = that || window;  // that为空(undefined null)  则为window
    that.fn = this;
    arg = arg || [];
    const result = that.fn(...arg);
    delete that.fn;
    return result;
}

bind.(obj,arg1,arg2,arg3…)

bind的参数同call相同,但是bind是返回一个改变this指向后的函数实例;

所以利用闭包返回一个匿名函数,内部调用这个新函数

bind需要实现两种形式的赋值

  • 类似于bind(context,arg1,arg2…)的解构赋值
  • 返回函数实例,再进行调用
Function.prototype.newBind = function ( that,...argsA ) {
    if(that.toString() !== "[object object]"){
    	throw that+" is not an Object";
    }
	that = that || window;
	const Fn = this;
	return function ( ...argsB ) {
		let args = argsB.length == 0 ? argsA : argsB; // 如果B不存在 传入的为A的参数
		return Fn.apply(that,args);
	};
}

Fn为当前函数,然后使用apply将that新指向传入,又因为args在函数中是以数组的形式存在,所以即可实现

参考

  • https://blog.csdn.net/weixin_40803505/article/details/85254578
  • https://www.jianshu.com/p/5afd6674f352
  • https://zhuanlan.zhihu.com/p/69070129
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值