目录
写在前面
今天的主题是手写实现某些常见的js函数。在JavaScript中,我们知道改变一个函数的this指向,一般来说有这样三个函数可以帮助我们做到这样的效果,分别是call、apply、bind。但是三个函数又有所区别,具体的区别我就不详述了,大家可以去call、apply、bind详细介绍看看详细的介绍。
call手写实现
var age = 16;
var gender = 'female';
var obj = {
age: 11,
gender: 'male'
}
function Test(a, b) {
console.log(this.age);
console.log(this.gender);
comsole.log(a);
comsole.log(b);
}
我们先来看看js的原生call函数的效果,请看下面代码:
Test(3, 5);
Test.call(obj, 22, 33);
其输出结果如下:
ok,下面我们来自己首先代码实现我们自己的call函数,show you the code:
Function.prototype.myCall = function (obj, ...args) {
obj.fn = this;
let res = obj.fn(...args);
delete obj.fn;
return res;
}
同样的,我们来调用我们的myCall函数:
Test.myCall(obj, 22, 33);
输出如下:
很显然,我们已经实现了call函数的功能,下面我们简单的分析一下实现的原理及思路:首先myCall函数是挂载在Function构造函数的原型上的,这没什么好解释的,大家都懂;其次,我们都知道调用myCall函数的第一个参数为this的指向,所以第一个参数单独写,然后怎样让函数的调用时this指向这个参数呢?这时我们可以利用对象的方法调用时,其方法的his指向此对象,所以我们把原函数当作一个方法挂载在第一个参数obj上,所以我们可以看到 obj.fn = this; 这行代码,此时就实现了改变this的指向,此时最最重要的部分已经被我们解决了,接下来的事情不多说了,水到渠成。
apply手写实现
先来看看apply的调用及调用后的效果:
Test.apply(obj, [36, 37]);
// 输出如下:
11
"male"
36
37
下面开始实现我们自己的apply:
Function.prototype.myApply = function(obj, args) {
obj.fn = this;
let res;
if (args && args.length) {
res = obj.fn(...args);
} else {
res = obj.fn();
}
delete obj.fn;
return res;
}
下面调用一下我们自己的myApply函数试试看效果:
Test.myApply(obj, [55, 56]);
// 输出如下:
11
"male"
55
56
可以看到,我们自己手写的myApply函数同样是达到了效果,原理同上就不在此赘述了。
bind手写实现
这里,我们直接手写我们自己的bind函数,就不再赘述原生的bind函数了,直接上code:
Function.prototype.myBind = function(obj, ...args) {
obj.fn = this;
return function() {
const newArgs = args.concat(...arguments);
let ret = obj.fn(...newArgs);
delete obj.fn;
return ret;
}
}
调用我们自己的myBind函数看看效果:
Test.myBind(obj, 66, 67)();
Test.myBind(obj, 77)(78);
// 分别输出如下:
11
"male"
66
67
11
"male"
77
78