基本使用
都是用来改变一个函数的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");
手动实现
-
context 为可选参数,如果不传的话默认上下文为 window;
-
context 创建一个 Symbol 属性,调用后即删除,不会影响context
-
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))
-
}
-
}