都是用来改变一个函数的this指向,用法略有不同。
call:后面的参数为调用函数的参数列表
function greet(name) {
console.log(this.animal,name);
}
var obj = {
animal: 'cats'
};
greet.call(obj,'猫咪');
apply:第二个参数为调用函数的参数数组
function greet(name) {
console.log(this.animal,name);
}
var obj = {
animal: 'cats'
};
greet.apply(obj,['猫咪']);
bind:当绑定函数被调用时,bind传入的参数会被插入到目标函数的参数列表的开始位置,传递给绑定函数的参数会跟在它们后面。
var fun = function (name1,name2){
console.log(this);
console.log(name);
}.bind({a:1},"name1");
fun("name2");
Function.prototype.myCall = function (context) {
if (typeof this !== 'function') {
return undefined; // 用于防止 Function.prototype.myCall() 直接调用
}
context = context || window;
const fn = Symbol();
context[fn] = this;
const args = [...arguments].slice(1);
const result = context[fn](...args);
delete context[fn];
return result;
}
apply实现类似call,参数为数组
Function.prototype.myApply = function (context) {
if (typeof this !== 'function') {
return undefined; // 用于防止 Function.prototype.myCall() 直接调用
}
context = context || window;
const fn = Symbol();
context[fn] = this;
let result;
if (arguments[1] instanceof Array) {
result = context[fn](...arguments[1]);
} else {
result = context[fn]();
}
delete context[fn];
return result;
}
1.判断是否为构造函数调用
2.注意参数要插入到目标函数的开始位置
Function.prototype.myBind = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
const _this = this
const args = [...arguments].slice(1)
return function F() {
// 判断是否用于构造函数
if (this instanceof F) {
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}