call 函数
语法
obj.call(thisObj,arg[,arg2[,arg3[,...agr]]]);
简介
修改obj的this指向为thisObj,后面的参数会当成obj的参数安装顺序传递进去。
我们先来看一下下面这段代码会输出什么:
function say(arg1, arg2) {
console.log(this.name, arg1, arg2);
}
const obj = {
name: "tom",
say: function () {
console.log(this.name);
}
};
say();
输出结果:
我们发现报错了,程序并没有找到name。
现在我们来改动一下,使用call函数来改变this的指向,看看会发生什么:
say.call(obj, "1", "2");
发现输出的结果变成了:
call把say函数的this变为了obj。
实现
下面我们来实现一个call函数
Function.prototype._call = function (context) {
// 判断是否是一个函数
// this指的是调用的函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
context = context || window;
context.fn = this;
const args = [...arguments].slice(1);
const result = context.fn(...args);
delete context.fn;
return result;
};
验证一下:
say._call(obj, "1", "2");
发现输出结果与期望的相同。
apply函数
语法
obj.apply(thisObj[,argArray]);
简介
apply与call函数的用法相同,只是参数的传递变成了数组形式。
say.apply(obj, ["1", "2"]);
输出的结果与调用call相同:
实现
Function.prototype._apply = function (context, args) {
// 判断是否是一个函数
// this指的是调用的函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
context = context || window;
context.fn = this;
let result = null;
if (args) {
result = context.fn(...args);
} else {
result = context.fn();
}
delete context.fn;
return result;
};
bind 函数
语法
obj.bind(thisObj,arg[,arg2[,arg3[,...agr]]]);
简介
bind函数会返回一个新函数,但是不会像call和apply一样立即执行函数,bind后面的参数会当成obj的参数安装顺序传递进去。
我们先来看两段代码
const s = say.bind(obj, "1", "2");
s();
const s = say.bind(obj);
s("1", "2");
发现这两段代码输出的结果是一样的。
实现
我们利用apply来实现一下bind函数:
Function.prototype._bind = function (context) {
// 判断是否是一个函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
const args = [...arguments].slice(1);
const fn = this;
const F = function () {},
fBound = function () {
return fn.apply(
this instanceof F && context ? this : context || window,
args.concat(...arguments)
);
};
F.prototype = this.prototype;
fBound.prototype = new F();
return fBound;
};