call、apply、bind都是用来改变函数this的指向的
call、apply在改变函数this指向的同时,会调用函数,而bind则是返回一个新的函数,不会调用
call、bind 和 apply 之间的区别,则体现在对入参的要求上。前者只需要将目标函数的入参逐个传入即可,后者则希望入参以数组形式被传入。
了解了三者的作用机制,先看看例子
var student = {
name: 'xiaoming'
}
function showName() {
console.log(this.name);
}
showName.call(student); // xiaoming
结合 call 方法的特性,我们首先至少能想到以下两点:
call 是可以被所有的函数继承的,因为 JS 中每个函数的原型都指向Function.prototype对象(JS基于原型链的继承),所以 call 方法应该被定义在 Function.prototype 上;
call 方法做了两件事:
改变 this 的指向,将 this 绑定到第一个入参指定的的对象上去;
根据输入的参数,执行函数。
结合这两点,我们一步一步来实现 call 方法。首先,改变函数位置
var student = {
name: 'xiaoming',
function showName() {
console.log(this.name);
}
}
student.showName(); // xiaoming
然后根据这个思路我们有以下代码
var student = {
name: "xiaoming"
};
function showName() {
console.log(this.name);
}
Function.prototype.myCall = function(context, ...args){
context = context || window;
context.fn = this;
context.fn(...args);
delete context.fn;
}
showName.myCall(student)
这里context.fn = this;比较难理解,但是看后面调用showName.myCall(student)就比较好理解了
apply的实现原理差不多
var student = {
name: "xiaoming"
};
function showName() {
console.log(this.name);
}
Function.prototype.myCall = function(context, [...args]){
context = context || window;
context.fn = this;
context.fn([...args]);
delete context.fn;
}
showName.myCall(student)
bind有些不同 下回再说