一、this的指向
this
的指向是在函数被调用时确定的,它指向调用该函数的对象。
在不同的情况下,this
的指向会有所不同,常见的情况包括:
- 全局环境下,
this
指向全局对象(在浏览器中指向window
对象)。 - 函数中的
this
,取决于函数的调用方式。如果函数被作为对象的方法调用,this
指向调用该方法的对象;如果函数被直接调用,this
指向全局对象。 - 使用构造函数创建对象时,
this
指向新创建的实例对象。 - 使用
call
、apply
、bind
方法可以手动指定函数中this
的指向。
二、手写apply、call、bind函数
1. 手写apply函数
apply
方法的作用是调用一个具有指定this
值的函数,并以一个指定的参数数组的形式传递参数。
Function.prototype.myApply = function (context, args) {
context = context || window;
const fn = Symbol();
context[fn] = this;
const result = context[fn](...args);
delete context[fn];
return result;
};
// 测试
function greet(name) {
return `Hello, ${name}!`;
}
const obj = { name: 'Alice' };
console.log(greet.myApply(obj, ['Bob'])); // 输出:Hello, Bob!
2. 手写call函数
call
方法的作用与apply
类似,区别在于参数的传递方式不同。
Function.prototype.myCall = function (context, ...args) {
context = context || window;
const fn = Symbol();
context[fn] = this;
const result = context[fn](...args);
delete context[fn];
return result;
};
// 测试
function greet(name) {
return `Hello, ${name}!`;
}
const obj = { name: 'Alice' };
console.log(greet.myCall(obj, 'Bob')); // 输出:Hello, Bob!
3. 手写bind函数
bind
方法创建一个新的函数,在调用时将其this
值设置为提供的值。
Function.prototype.myBind = function (context, ...args) {
const self = this;
return function (...newArgs) {
return self.apply(context, args.concat(newArgs));
};
};
// 测试
function greet(name) {
return `Hello, ${name}!`;
}
const obj = { name: 'Alice' };
const boundFn = greet.myBind(obj, 'Bob');
console.log(boundFn()); // 输出:Hello, Bob!
三、apply
、call
、bind的相同与不同之处
-
相同点:
apply
、call
、bind
都是用来改变函数执行时的上下文(this
指向)。- 它们都是Function对象的原型方法,可以在函数对象上直接调用。
-
不同点:
apply
和call
的作用是立即执行函数,只是传递参数的方式不同,apply
以数组形式传递参数,而call
是一个一个传递参数。bind
方法不会立即执行函数,而是返回一个新的函数,可以在后续调用时执行。bind
方法可以预先绑定函数执行时的参数,而apply
和call
只能在调用时传递参数。