问题描述
在C ++之类的语言中,能够检测对象何时超出范围在许多用例(例如,智能指针,文件访问,互斥锁,分析)中非常有用。而且我这里不是在谈论内存管理与垃圾回收,因为这是一个不同的话题。
考虑像这样的简单C ++示例
class Profiler {
uint64 m_startTime;
Profiler::Profiler() :
m_startTime(someTimeFunction()) {
}
Profiler::~Profiler() {
const uint64 diff = someTimeFunction() - m_time;
printf("%llu ms have passed\n",diff);
}
}
我们可以做这样的事情
{
Profiler p; // creation of Profiler object on the stack
// Do some calculations
} // <- p goes out of scope and you will get the output message reporting the number of ms that have been passed
这个干净的示例演示了作用域的强大功能。作为程序员,我不必担心手动调用方法。规则很简单:一旦对象超出范围,就会调用析构函数,而我可以利用它。
但是在Javascript中,我至少没有办法模仿这种行为。在过去,let
和const
并不是该语言的一部分,这本来就没用,甚至很危险,因为人们永远不会真正知道var
何时超出范围
但是,当添加块作用域时,我希望程序员可以控制对象何时超出范围。例如,一种特殊方法(如contructor()
)在超出范围时会被调用。但是AFAIK尚未完成。为什么没有添加任何原因?
现在,我们必须手动调用一个函数,该函数无法满足所述用例的块作用域定义的整个目的。
这将是与上述C ++代码等效的Javascript:
class Profiler {
constructor() {
this.m_time = new Date().getTime();
}
report() {
const diff = new Date().getTime() - this.m_time;
console.log(`${diff} ms have passed`);
}
}
用例就是这个
{
const p = new Profiler;
// Do some calculations
p.report();
}
显然不那么理想。因为如果我不小心将p.report();
放在代码块的末尾,则报告是不正确的。
如果仍有办法,请告诉我。
[编辑]
我想到的最接近的东西是这种“黑客”。我使用了async
,但是很明显,如果块中的所有代码都是同步的,可以忽略掉它。
// My profiler class
class Profiler {
constructor() {
this.m_time = new Date().getTime();
}
// unscope() is called when the instance 'goes out of scope'
unscope() {
const diff = new Date().getTime() - this.m_time;
console.log(`took ${diff} ms`);
}
};
async function Scope(p_instance,p_func) {
await p_func();
p_instance.unscope();
};
await Scope(new Profiler(),async () =>
{
console.log("start scope")
await sleep(100);
await Scope(new Profiler(),async () =>
{
await sleep(400);
});
await sleep(3000);
console.log("end scope")
});
console.log("after scope")
导致
start scope
took 401 ms
end scope
took 3504 ms
after scope
这是我所期望的。但是再次
await Scope(new Profiler(),async () =>
{
});
远不如简单
{
const p = new Profiler();
}
但是至少我能做我想做的事。如果还有其他更好的解决方案,请告诉我。
解决方法
析构函数将是实现它的一种方法,但不幸的是Javascript不支持它。超出范围后自动获得概要文件报告的原因可能是因为它的析构函数是在C ++中调用的。到目前为止,JavaScript中没有析构函数。如您所愿,手动进行操作是实现C ++所需行为的最简单方法。
不同的语言带来了不同的语法和功能。有时您需要适应差异。 C ++代码在您的情况下不太容易出错,但是我认为没有一种简单的方法可以实现所需的行为