
在深入探讨方法调用之前,理解JavaScript中this关键字的工作方式至关重要。当一个函数作为对象的方法被调用时,this关键字通常会指向该对象本身。这使得方法能够访问和操作对象的其他属性和方法。例如,在restaurant.order()方法中,this指向restaurant对象,从而可以访问this.starterMenu和this.mainMenu。
这是在JavaScript对象中实现方法间协作最直接、最推荐的方式。如果一个方法需要执行另一个方法的完整逻辑来获取数据或完成任务,可以直接使用this.otherMethod()进行调用。
考虑以下场景:orderDelivery方法需要知道具体的开胃菜和主菜名称,而这些信息可以通过调用order方法,并传入相应的索引来获取。
const restaurant = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: { open: 12, close: 22 },
fri: { open: 11, close: 23 },
sat: { open: 0, close: 24 },
},
// 接收开胃菜和主菜索引,返回对应的菜品名称数组
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
// 接收订单详情,并在内部调用 order 方法获取菜品名称
orderDelivery: function({ starterIndex, mainIndex, time, address }) {
// 使用 this.order() 调用内部的 order 方法,获取菜品名称
const [starterItem, mainItem] = this.order(starterIndex, mainIndex);
console.log(`Order received! ${starterItem} and ${mainItem} will be delivered to ${address} at ${time}`);
}
};
// 调用 orderDelivery,传入索引、时间、地址
restaurant.orderDelivery({
starterIndex: 2, // 对应 'Garlic Bread'
mainIndex: 1, // 对应 'Pasta'
time: '22:30',
address: 'Via del Sole, 21',
});
// 输出: Order received! Garlic Bread and Pasta will be delivered to Via del Sole, 21 at 22:30在这个示例中,orderDelivery方法通过this.order(starterIndex, mainIndex)直接调用了restaurant对象上的order方法。order方法返回一个包含菜品名称的数组,orderDelivery随后使用ES6的数组解构语法将其赋值给starterItem和mainItem变量,从而在日志中显示正确的订单信息。这种方式确保了订单逻辑的集中管理,避免了在orderDelivery中重复访问starterMenu和mainMenu的逻辑。
立即学习“Java免费学习笔记(深入)”;
在某些情况下,你可能不希望一个方法直接调用另一个方法,而是希望在外部先计算好所需的数据,然后将这些数据作为参数传递给目标方法。这种方式适用于当数据来源多样,或者调用方希望对数据进行预处理的场景。
const restaurantWithPrecomputedOrder = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: { open: 12, close: 22 },
fri: { open: 11, close: 23 },
sat: { open: 0, close: 24 },
},
order: function (starterIndex, mainIndex) {
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
},
// 接收预计算好的菜品数组
orderDelivery: function({ orderItems, time, address }) {
const [starterItem, mainItem] = orderItems; // 直接使用传入的菜品数组
console.log(`Order received! ${starterItem} and ${mainItem} will be delivered to ${address} at ${time}`);
}
};
// 在外部先调用 order 方法获取菜品
const myOrderItems = restaurantWithPrecomputedOrder.order(2, 1); // ['Garlic Bread', 'Pasta']
// 将预计算好的菜品数组传递给 orderDelivery
restaurantWithPrecomputedOrder.orderDelivery({
orderItems: myOrderItems, // 传递菜品数组
time: '22:30',
address: 'Via del Sole, 21',
});
// 输出: Order received! Garlic Bread and Pasta will be delivered to Via del Sole, 21 at 22:30这种方法将order方法的执行与orderDelivery方法解耦。orderDelivery不再关心菜品是如何选择的,它只负责处理已经准备好的菜品信息。这增加了灵活性,但可能需要调用者承担更多的数据准备责任。
在JavaScript中,你也可以将独立定义的函数作为对象的方法来使用。然而,为了确保这些外部函数在作为方法被调用时,其内部的this关键字能正确指向目标对象,就需要使用Function.prototype.bind()方法。bind()会创建一个新函数,这个新函数在被调用时,其this值会被永久绑定到bind()的第一个参数。
// 独立定义的订单函数
function genericOrder(starterIndex, mainIndex) {
// 这里的 this 必须在绑定后才能正确指向 restaurant
return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
}
// 独立定义的配送函数
function genericDelivery(parameters) {
// 这里的 this 必须在绑定后才能正确指向 restaurant
// 注意:此处的 genericDelivery 仍需直接访问 starterIndex 和 mainIndex
// 如果需要调用 genericOrder,则需要 this.order(parameters.starterIndex, parameters.mainIndex)
console.log(`Order received! ${this.starterMenu[parameters.starterIndex]} and ${this.mainMenu[parameters.mainIndex]} will be delivered to ${parameters.address} at ${parameters.time}`);
}
const restaurantWithBoundMethods = {
name: 'Classico Italiano',
location: 'Via Angelo Tavanti 23, Firenze, Italy',
categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
mainMenu: ['Pizza', 'Pasta', 'Risotto'],
openingHours: {
thu: { open: 12, close: 22 },
fri: { open: 11, close: 23 },
sat: { open: 0, close: 24 },
},
// ... 其他属性
};
// 使用 bind() 将外部函数绑定为 restaurant 对象的方法
restaurantWithBoundMethods.order = genericOrder.bind(restaurantWithBoundMethods);
restaurantWithBoundMethods.orderDelivery = genericDelivery.bind(restaurantWithBoundMethods);
// 现在可以像调用对象内部方法一样调用它们
const myOrder = restaurantWithBoundMethods.order(2, 1); // 调用绑定的 order 方法
restaurantWithBoundMethods.orderDelivery({
time: '22:30',
address: 'Via del Sole, 21',
mainIndex: 0, // 仍然需要直接传递索引
starterIndex: 2,
});
// 输出: Order received! Garlic Bread and Pizza will be delivered to Via del Sole, 21 at 22:30注意事项: 虽然bind()方法成功地将genericOrder和genericDelivery绑定到了restaurantWithBoundMethods对象,使得它们内部的this正确指向restaurantWithBoundMethods,但在这个特定的genericDelivery实现中,它并没有在内部调用genericOrder。它仍然直接使用传入的parameters.starterIndex和parameters.mainIndex来访问this.starterMenu和this.mainMenu。
如果目标是让orderDelivery(无论是内部定义还是外部绑定)内部调用order方法,那么orderDelivery的实现应该修改为:
// 修改后的 genericDelivery,内部调用 this.order
function genericDeliveryImproved(parameters) {
// 确保 this.order 已经被绑定到对象
const [starterItem, mainItem] = this.order(parameters.starterIndex, parameters.mainIndex);
console.log(`Order received! ${starterItem} and ${mainItem} will be delivered to ${parameters.address} at ${parameters.time}`);
}
// 重新绑定
restaurantWithBoundMethods.orderDelivery = genericDeliveryImproved.bind(restaurantWithBoundMethods);
// 再次调用,现在 orderDelivery 内部会调用 order
restaurantWithBoundMethods.orderDelivery({
time: '22:30',
address: 'Via del Sole, 21',
mainIndex: 1, // 对应 'Pasta'
starterIndex: 2, // 对应 'Garlic Bread'
});
// 输出: Order received! Garlic Bread and Pasta will be delivered to Via del Sole, 21 at 22:30这展示了即使使用bind(),方法间的内部调用逻辑依然需要明确地通过this.methodName()来实现。
以上就是如何在JavaScript对象方法中调用其他方法并管理this上下文的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号