call()方法
使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数
call() 方法接受的是一个参数列表
语法:function.call(thisArg,arg1,arg2,…)
简单来说:call()方法就是用来改变 this 指向的
call 和 apply 实现的思路主要都是:
- 判断是否是函数调用,若非函数调用抛异常
- 通过新对象(context)来调用函数
- 给 context 创建一个 fn 设置为需要调用的函数
- 结束调用完之后删除 fn
function person(name, age, gender) {
console.log(this.name);
console.log(name, age, gender);
}
var jinjianceng = {
name: "jinjianceng"
}
Function.prototype.myCall = function (context) {
// 先判断调用 myCall 是不是一个函数
// 这里的 this 就是调用 mycall 的
if (typeof this !== "function") {
throw new TypeError("Not a Function");
}
// 不传参数默认为 window
context = context || window;
// 保存 this
// 这里的 this 指向的被绑定的函数
context.fn = this;
// 保存参数
// Array.from 把伪数组对象转为数组
// slice(1) 的原因是 arguments[0] = this
let args = Array.from(arguments).slice(1);
// 调用函数
// 复制函数
let result = context.fn(...args);
// 因为不能改写对象,所以需要把 context.fn 删除掉
delete context.fn;
return result;
}
person.myCall(jinjianceng, "jinjianceng", "18", "female")
// jinjianceng
// jinjianceng 18 female
person.myCall(null, "jinjianceng", "18", "female")
//
// jinjianceng 18 female
apply()方法
调用一个具有给定 this 值的函数,以及以一个数组 (或类数组对象)的形式提供参数
apply() 方法接受的是一个参数数组
语法:func.apply(thisArg,[argsArray])
function person(name, age, gender) {
console.log(this.name);
console.log(name, age, gender);
}
var jinjianceng = {
name: "jinjianceng"
}
Function.prototype.myApply = function (context) {
// 判断 this 是不是函数
if (typeof this !== "function") {
throw new TypeError("Not a Function");
}
let result;
// 默认没有 this 时是window
context = context || window;
// 保存 this
context.fn = this;
// 是否传参
if (arguments[1]) {
result = context.fn(...arguments[1]);
} else {
result = context.fn();
}
delete context.fn;
return result;
}
person.myApply(jinjianceng, ["jinjianceng", "18", "female"])
// jinjianceng
// jinjianceng 18 female
person.myApply(null, ["jinjianceng", "18", "female"])
//
// jinjianceng 18 female
bind()方法
创建一个新的函数,在 bind() 被调用后,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用
语法:function.bind(thisArg[,arg1[,arg2[,…]]])
function person(name, age, gender) {
console.log(this.name);
console.log(name, age, gender);
}
var jinjianceng = {
name: "jinjianceng"
}
Function.prototype.myBind = function (context) {
// 判断是否是一个函数
if (typeof this !== "function") {
throw new TypeError("Not a Function");
}
// 保存调用 bind 的函数
const _this = this;
// 保存参数
const args = Array.prototype.slice.call(arguments, 1);
// 返回一个函数
return function F() {
if (this instanceof F) {
// 判断是不是 new 出来的
// 返回一个空对象,且使创建出来的实例的 __proto__ 指向 _this 的 prototype,且完成函数柯里化
return new _this(...args, ...arguments);
} else {
// 如果不是 new 出来的改变 this 指向,且完成函数柯里化
return _this.apply(context, args.concat(...arguments));
}
}
}
person.myBind(jinjianceng, "jinjianceng", "18")("female")
// "jinjianceng"
// "jinjianceng" "18" "female"
person.myBind(null, "jinjianceng", "18")("female")
//
// jinjianceng 18 female