gpt4 book ai didi

javascript - 不需要的 JavaScript 效果 : Prototype is sharing closure between instances

转载 作者:行者123 更新时间:2023-11-28 19:21:46 25 4
gpt4 key购买 nike

我正在制作一款带有定时关卡的游戏。一关时长2分钟,右上角显示倒计时器。马里奥风格。

跟踪已用时间的一种方法是让我的 Level 对象将 elapsed 作为成员变量。

Level.init = function(){
this.elapsed = 0; //member variable!
return this;
};

Level.update = function(){
this.countdown();
};

Level.countdown = function(){
this.elapsed += 1;
var remaining = (GAME_LENGTH*60) - (this.elapsed/TICKS);
var minutes = Math.floor(remaining/60);
var seconds = Math.floor(remaining%60);
this.countdown.html(minutes + ":" + ("0"+seconds).slice(-2));

if (this.elapsed/TICKS >= GAME_LENGTH*60) {
this.level_end();
}
};

当游戏引擎需要新的关卡时,它会以这种方式创建一个:

NewLevel = Object.create(Level).init();

但是,我认为使用闭包可能会更好; elapsed 仅由 countdown 函数使用,因此不需要是 Level 的成员变量。 Level 不需要知道 elapsed 存在。

//member variable this.elapsed has been removed
Level.init = function(){
return this;
};

Level.update = function(){
this.countdown();
};

//a closure is used to keep track of elapsed time
Level.countdown = (function(){
var elapsed = 0;
return function() {
elapsed += 1;
var remaining = (GAME_LENGTH*60) - (elapsed/TICKS);
var minutes = Math.floor(remaining/60);
var seconds = Math.floor(remaining%60);
this.countdown.html(minutes + ":" + ("0"+seconds).slice(-2));

if (elapsed/TICKS >= GAME_LENGTH*60) {
elapsed = 0;
this.end_level();
}
};
})();

但现在我有一个不同的问题。创建的所有 Level 副本都共享该 countdown 闭包,因为它位于原型(prototype)链中。当用户提前退出关卡,然后启动新关卡(废弃旧的 Level 对象并实例化新的 Level 对象)时,elapsed闭包中的变量不会重置。

换句话说,用户在还剩 30 秒时提前退出关卡。然后用户再次启动关卡,但现在倒计时器仍然显示 30 秒,而不是整整 2 分钟。

有没有一种优雅的方法来解决这个问题并仍然使用闭包?或者我必须恢复到以前的解决方案,忘记闭包,并将 elapsed 设为成员变量?

最佳答案

Is there an elegant way to fix this and still use a closure? Or must I revert to my previous solution, forget closures, and make elapsed a member variable?

它必须是特定于实例的;这并不意味着它必须是对象的属性。您可以在 init 方法中创建闭包:

//member variable this.elapsed has been removed
Level.init = function(){
//a closure is used to keep track of elapsed time
this.countdown = createCountdownMethod();
return this;
};

Level.update = function(){
this.countdown();
};

function createCountdownMethod(){
var elapsed = 0;
return function() {
elapsed += 1;
var remaining = (GAME_LENGTH*60) - (elapsed/TICKS);
var minutes = Math.floor(remaining/60);
var seconds = Math.floor(remaining%60);
this.countdown.html(minutes + ":" + ("0"+seconds).slice(-2));

if (elapsed/TICKS >= GAME_LENGTH*60) {
elapsed = 0;
this.end_level();
}
};
}

或者这可能更容易阅读:

//member variable this.elapsed has been removed
Level.init = function(){
var elapsed = 0;

//a closure is used to keep track of elapsed time
Level.countdown = countdown;
return this;

function countdown() {
elapsed += 1;
var remaining = (GAME_LENGTH*60) - (elapsed/TICKS);
var minutes = Math.floor(remaining/60);
var seconds = Math.floor(remaining%60);
this.countdown.html(minutes + ":" + ("0"+seconds).slice(-2));

if (elapsed/TICKS >= GAME_LENGTH*60) {
elapsed = 0;
this.end_level();
}
}
};

Level.update = function(){
this.countdown();
};

关于javascript - 不需要的 JavaScript 效果 : Prototype is sharing closure between instances,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28730901/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com