我有这个对象resources
:
var resources = { //Handles resources of all kinds.
number: 100,
money: 23000000,
science: 1000,
popularity: {
amount: 0,
upgProd: 0 //Amount produced from upgrades.
}
};
这看起来像普通对象。
但是,我正在尝试显示一定数量popularity
。每当我尝试显示它时,我会得到NaN而不是数字。
我尝试返回console.log(resources.popularity.upgProd);
但我仍然得到undefined
。我不知道为什么因为我定义变量但我仍然未定义...
在我的console.log()时,只有undefined
在IDE或控制台中没有错误。
update
函数,每1/7秒更新一次。此外,resources.popularity.upgProd
的第一个值为0,然后下一个值为NaN。
function update() {
buffer++;
if (buffer == 35) {
checkVisibilityOnBuildings();
checkVisiblityOnUpgrades();
checkVisibilityOnResources();
buffer = 0;
} // Every 5 seconds (35 ticks) visibility will be checked and updated.
/* Number increasing. A bit tedious but no other way to do it yet. */
resources.number +=
((BUILDINGS[0].numProdBase * BUILDINGS[0].count) + //Now it's easy! Just do UPGRADES[n+1] for the next building.
(BUILDINGS[1].numProdBase * BUILDINGS[1].count) +
(BUILDINGS[2].numProdBase * BUILDINGS[2].count) +
(BUILDINGS[3].numProdBase * BUILDINGS[3].count));
//Science gained per tick. Var used to make the "scienceProductionTotalDisp" work properly
var scienceTotalPerTick =
(BUILDINGS[2].sciProdBase * BUILDINGS[2].count) +
(BUILDINGS[3].sciProdBase * BUILDINGS[3].count);
resources.science += scienceTotalPerTick;
//Display vars for html so that rounding errors don't happen.
var numDisp = Math.floor(resources.number);
var sciDisp = Math.floor(resources.science * 100) / 100;
var popDisp = Math.floor(resources.popularity.amount * 100) / 100;
console.log(Number(resources.popularity.upgProd));
var moneyTotalPerTick = Math.pow(resources.number, (1/(player.moneyRatio))) + 1; //Cash flow per 143ms (7n for total / sec ish)
var popularityTotalPerTick = (Number(resources.popularity.upgProd)) + 0;
resources.popularity += popularityTotalPerTick;
console.log(resources.popularity.upgProd);
resources.money += moneyTotalPerTick;
getId('moneyProductionTotalDisp').innerHTML = numFormat(Math.floor(moneyTotalPerTick * 7));
getId('moneyDisp').innerHTML = numFormat(Math.round(resources.money * 100) / 100);
getId('numberDisp').innerHTML = numFormat(numDisp);
getId('scienceDisp').innerHTML = numFormat(sciDisp);
getId('popularityDisp').innerHTML = numFormat(popDisp);
getId('scienceProductionTotalDisp').innerHTML =
numFormat(Math.floor(scienceTotalPerTick * 700) / 100);
getId('popularityProductionTotalDisp').innerHTML =
numFormat(Math.floor(popularityTotalPerTick * 700) / 100);
谢谢!
答案 0 :(得分:1)
这是你的问题:
resources.popularity += popularityTotalPerTick;
受欢迎程度是一个对象,并不能做你想做的事。
由于您使用由值添加的对象的结果覆盖它,因此您将其分配为字符串[object Object]9
,其中最后一位数字是popularTotalPerTick中的任何内容。
由于您在NaN
中使用Number(x)
,因此获得console.log(Number(resources.popularity.upgProd));
(非数字)。你为什么这样做?
每次调用函数时,getId
是否都会在dom中查找元素?是否更改了对象,或者您是否每秒7次查询相同元素的DOM?
<小时/> 关于代码中其他内容的一些想法:
resources.number +=
((BUILDINGS[0].numProdBase * BUILDINGS[0].count) +
(BUILDINGS[1].numProdBase * BUILDINGS[1].count) +
(BUILDINGS[2].numProdBase * BUILDINGS[2].count) +
(BUILDINGS[3].numProdBase * BUILDINGS[3].count));
我假设BUILDINGS是一个包含所有建筑物的阵列,并且您想要计算阵列中所有建筑物的数量。有一个函数:reduce有两个参数:一个函数和一个起始值:
resources.number += // do you really want += here and not just = ?
BUILDINGS.reduce( (sum, item) => sum + (item.numProdBase * item.count), 0 );
如果您不熟悉箭头功能,可以将其替换为:
function (sum, item) { return sum + (item.numProdBase * item.count) }
var scienceTotalPerTick =
(BUILDINGS[2].sciProdBase * BUILDINGS[2].count) +
(BUILDINGS[3].sciProdBase * BUILDINGS[3].count);
我不确定为什么你只为两座建筑物而不是为所有建筑物而做,但你也可以在这里使用reduce,slice
var scienceTotalPerTick =
BUILDINGS.slice(2,4).reduce( (sum, item) => sum + (item.sciProdBase * item.count), 0);
请注意,要切片的参数是开始到 end ( end not included ),因此2,4给出了元素2和3 。
这部分代码......
getId('moneyProductionTotalDisp').innerHTML = numFormat(Math.floor(moneyTotalPerTick * 7));
getId('moneyDisp').innerHTML = numFormat(Math.round(resources.money * 100) / 100);
getId('numberDisp').innerHTML = numFormat(numDisp);
getId('scienceDisp').innerHTML = numFormat(sciDisp);
getId('popularityDisp').innerHTML = numFormat(popDisp);
我假设 getId 是一个通过 document.getElementById 或 document.querySelector 获取元素的函数,并且你这样做是为了每一帧,你每次都得到相同的元素。现在假设元素是一个盒子,我要求你从世界另一端的仓库中获取它。当您交付盒子时,我打开盒子,更换内容并将其发回世界另一端的仓库。当你回来时,我要求你再次获得同样的盒子,你现在必须再次前往世界的另一端......当你回来时,故事重复......
我的观点是,每次前往世界的另一端获取相同的盒子,或者在每次更新时从DOM获取相同的元素是非常浪费的。您可以在开始更新之前通过查找一次来缓存元素,并且可以将结果放在对象中:
function getElementsToUpdate() {
return {
moneyProductionTotalDisp: getId('moneyProductionTotalDisp'),
moneyDisp: getId('moneyDisp'),
// and so on...
}
}
如果将对象中的属性命名为与id相同,则可以将所有名称放在数组中,然后将其减少为对象。这样可以省去一些打字,而且由于拼写错误的名字很难找到错误:
function getElementsToUpdate() {
return [
'moneyProductionTotalDisp',
'moneyDisp',
'numberDisp',
'scienceDisp',
'popularityDisp',
// and so on....
].reduce(
(out, id) => { out[id] = getId(id); return out; }, {}
)
}
注意:此功能应在启动时运行一次,而不是每次更新帧。它返回一个带有元素的对象。
在代码的某处,我假设您使用setInterval来调用更新功能。由于 setInteval 可以获取将被赋予被调用函数的额外参数,因此您可以执行以下操作:
var timerHandle = setInterval( update, 1000/7, getElementsToUpdate() );
更新是您的功能, 1000/7 为您提供每秒7次的间隔,而 getElementsToUpdate 是制作的功能从DOM 一个时间获取元素的耗时费用。
您需要更改更新功能以获取参数(名称不重要,但应该简短且具有描述性,因此我使用 elem )。这是 getElementsToUpdate()返回的所有html元素的对象。
function update(elem) {
// ... your code ....
// Old code, that makes an expensive lookup into the DOM, and start a HTML parser.
// getId('numberDisp').innerHTML = numFormat(numDisp);
// New code, that gets the pre-looked up element and set the text.
elem.numberDisp.textContent = numFormat(numDisp);
}
<小时/> 我没有使用 .innerHTML 的粉丝,因为它不是插入的html。如果不是html,请始终使用 .textContent 。在这种情况下,如果您使用output - 元素并设置 .value 属性会更好。
答案 1 :(得分:0)
尝试使用console.log(resources["popularity"]["upgProd"])