是什么?
核心思想: 借用方法
解释: apply,call,bind都是js给函数内置的一些api,调用他们可以为函数指定this的执行,同时也可以传参。
作用: 改变函数执行时的this指向
语法
注意:fun必须是函数
fun.call(thisArg, param1, param2, ...)
fun.apply(thisArg, [param1,param2,...])
fun.bind(thisArg, param1, param2, ...)
Object.prototype.toString.call(data)
区别
call和apply
传递参数不同:
-
apply是第2个参数,这个参数是一个数组:传给fun参数都写在数组中。 -
call从第2~n的参数都是传给fun的,2-n都是参数。巧记:
apply是以a开头,它传给fun的参数是Array,也是以a开头的。
call/apply与bind区别
执行方式:
- call/apply改变了函数的this上下文后马上执行该函数
- bind则是返回改变了上下文后的函数,不执行该函数
返回值:
- call/apply 返回
fun的执行结果 - bind返回一个属于指定对象的
fun方法
手写call、apply和bind
call、apply
- that是指定的this对象
- args 是参数对象
- 利用Symbol将this对象(原函数所在对象)绑定到传入的that对象上
- 执行结束删除临时属性
call
// call
// 第一个参数是指定的this,后面的参数是参数列表
function myCall (that = window, ...args) {
if (!this instanceof Function) throw new TypeError("Type Error")
if (that === null || that === undefined) that = window
const fn = Symbol('fn')
that[fn] = this
const res = that[fn](...args)
delete that[fn]
return res
}
const obj = {
age: 10,
getAge: function() {
console.log(this.age);
}
}
const stu = {
age: 18
}
Function.prototype.call = myCall
obj.getAge.call(stu) // 18
apply
// apply
// 第一个参数绑定的是 this, 第二个参数是个数组
function myApply(that = window, args = []) {
if (!this instanceof Function) throw new TypeError("Type Error");
if (that === null || that === undefined) that = window;
// 使用Symbol确保不会与原对象属性产生冲突
const fn = Symbol("fn");
that[fn] = this;
const res = that[fn](...args);
delete that[fn];
return res;
}
const obj = {
age: 10,
getAge: function () {
console.log(this.age);
},
};
const stu = {
age: 18,
};
Function.prototype.apply = myApply;
obj.getAge.apply(stu); // 18
bind
//bind 返回一个函数
function myBind(that = window, ...args) {
if (!this instanceof Function) throw new TypeError("Type Error");
if (that === null || that === undefined) that = window
const self = this;
return function F() {
// new
if (this instanceof F) {
return new self(...args, ...arguments);
}
return self.apply(that, [...args, ...arguments]);
};
}
age = 20
const obj = {
age: 10,
getAge: function () {
console.log(this.age);
},
};
const stu = {
age: 18,
};
Function.prototype.bind = myBind;
const stuAge = obj.getAge.bind(stu);
stuAge();
const getAge = obj.getAge.bind(null);
getAge()
相信通过手写call、apply和bind,能够很快速的认识到它们之间的区别