1. 手写call
Function.prototype.myCall = function(context,...args){
// 如果context是null或者undefined,默认指向全局对象(浏览器是window,Node是globalThis)
context = context || globalThis
const fnSymbol = symbol('fn') // 创建一个独一无二的属性名
context[fnSymbol] = this // this指向调用myCall的函数,因为谁调用myCall,this就执行谁
const result = context[fnSymbol](...args)
delete context[fnSymbol]; // 删除临时属性,避免污染传入的 context 对象
return result
}
使用示例
function showAge(age){
console.log(`我叫 ${this.name}, 今年 ${age} 岁。`);
}
showAge.myCall({name: '张三'}, 18) // 我叫 张三, 今年 18 岁。
2.手写apply
Function.prototype.myApply = function(context,argsArray){
context = context || globalThis
const fnSymbol = symbol('fn')
context[fnSymbol] = this
// 判断是否有传入参数数组。如果有,则展开传递;如果没有,则直接调用
const result = argsArray ? context[fnSymbol](...argsArray) : context[fnSymbol]();
delete context[fnSymbol];
return result
}
使用示例
function showInfo(age, city) {
console.log(`我叫 ${this.name}, 今年 ${age} 岁,来自 ${city}。`);
}
showInfo.myApply({ name: 'Charlie' }, [30, '北京']); // 输出: 我叫 Charlie, 今年 30 岁,来自 北京。
3.手写bind
Function.prototype.myBind = function (context, ...bindArgs) {
const self = this;
function boundFn(...args) {
if (this instanceof boundFn) { //这里的this指的是你new boundFn时创建的新的对象
return new self(...bindArgs, ...args);
}
return self.apply(context, [...bindArgs, ...args]);//this是动态变动的,而self就是Greet
}
boundFn.prototype = Object.create(self.prototype);
return boundFn;
};
普通示例
const person = { name: "Tom" };
function greet(age, city) {
console.log(`Hi, I am ${this.name}, age ${age}, from ${city}`);
}
const bound = greet.myBind(person, 25);
bound("Guangzhou"); //Hi, I am Tom, age 25, from Guangzhou
new
// 餐厅预订系统的例子
function Reservation(restaurantId, customerName, partySize, date) {
this.restaurantId = restaurantId;
this.customerName = customerName;
this.partySize = partySize;
this.date = date;
this.status = 'pending';
}
Reservation.prototype.confirm = function() {
this.status = 'confirmed';
console.log(`${this.customerName}的${this.partySize}人预订已确认`);
};
// 为特定餐厅创建预配置的预订构造函数
const RestaurantAReservation = Reservation.bind(null, 'restaurant-a-id');
// 使用预配置的构造函数创建预订
const booking = new RestaurantAReservation('张三', 4, new Date('2023-06-15'));
booking.confirm(); // 输出: 张三的4人预订已确认
console.log(booking instanceof Reservation); // true
console.log(booking.restaurantId); // restaurant-a-id