javascript - JavaScript Bind (this) 不访问类
问题描述
如果不对类本身进行一些修改,我无法访问类的方法。
请参阅以下演示代码:
function myCallback() {
this.otherMethod();
}
class hiddenClass {
static hiddenFunction(callback) {
callback();
}
static otherMethod(){
console.log("success");
}
}
hiddenClass.hiddenFunction(myCallback);
在这个简单的示例中,我想在回调中访问 this.otherMethod()。显而易见的答案是更改callback()
为callback.bind(this)()
,但是在这种情况下, hiddenClass 将是一个库。
我怎么能调用这个其他方法?
作为参考,我正在尝试使用 node-cron 创建 cron 作业。如果数据库检查返回 true,我想销毁这些作业,检查作业的每个周期(在回调中)。作业有一个内部方法.destroy()
。我知道我可以将 cron 作业保存在一个变量中,然后调用variable.destroy()
,但是有没有办法在回调中执行它(因为这些作业是在 for 循环中创建的,我不想确定要从中销毁哪个作业在回调中)
cron.schedule(`5 * * * * *`, async function () {
schedule = await Schedule.findById(schedule._id);
if (!schedule) this.destroy() // Destroy the job if schedule is not found (this returns Window)
}
);
解决方案
您的推理是合理的,您需要将回调绑定到相关类。但是,可以通过修改对 hiddenFunction 的调用在您的示例代码中完成:
hiddenClass.hiddenFunction(myCallback.bind(hiddenClass));
这不需要修改库。
至于您的参考代码...
ES2015 之前的做法是创建匿名函数,通过调用当前循环迭代的值来绑定,举个简单的例子:
var schedules = [1,2,3,4,5];
for(var i=0;i<schedules.length;i++){
setTimeout(function(){console.log(schedules[i])}, 10);
}
/* => outputs:
5
5
5
5
5
*/
for(var i=0;i<schedules.length;i++){
// create an anonymous function with the first arg bound at call time
(function(j){
setTimeout(function(){console.log(schedules[j])}, 10);
}(i));
}
/* => outputs:
1
2
3
4
5
*/
但是,这在您的代码中是不可能的,因为您试图传递匿名回调并在所述函数中引用当前循环的迭代值,这要求匿名函数在将cron.schedule
自身传递给cron.schedule
.
该问题的解决方案是在循环中使用let
或const
绑定当前迭代的值。它们是块范围的,而不是词法范围的,因此它们在每次迭代时保留值,从而导致同一个匿名函数的 N 个闭包。我们可以在以下循环中演示两者之间的区别:
for(var foo of [1,2,3,4,5]){
const bar = foo;
(async function(){
await Promise.resolve().then(()=>console.log({bar, foo}));
}());
}
/* outputs:
{ bar: 1, foo: 5 }
{ bar: 2, foo: 5 }
{ bar: 3, foo: 5 }
{ bar: 4, foo: 5 }
{ bar: 5, foo: 5 }
*/
将它们结合在一起,您的循环调度程序将如下所示:
for(let schedule of schedules){
const me = cron.schedule(`5 * * * * *`, async function () {
// the value of `me` is bound to each iteration and you can refer to it as needed
schedule = await Schedule.findById(schedule._id);
if (!schedule) me.destroy();
});
}
推荐阅读
- django - Angular8:调用 localhost Rest Api 服务
- nginx - 将服务器中的文件列表作为 json 或文本返回,而不是默认的“索引”html 页面
- html - How can I vertically center a div on any resolution?
- azure - 在 Azure 的 Tomcat Web App 中定位标准输出日志
- coq - 如何使用 Proof General + Emacs 编译 Coq 文件?
- django - Django 教程和 Sqlite 命令行
- rust - 如何编写一个宏来匹配略有不同的匹配语句?
- c++ - 在我尝试使用 UTF-16- 字符串 (C++) 打开后,Ofstream 不起作用
- azure - 从 EventSender 迁移到 PartitionSender - 如何判断发件人是否已关闭?
- swift - 第一次用户在collectionview Swift 5中添加图像单元格时显示选择的图像而不是默认图像