gpt4 book ai didi

javascript - 即使值存在,属性也会返回未定义…?

转载 作者:行者123 更新时间:2023-12-03 02:11:59 38 4
gpt4 key购买 nike

我有这个对象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。我不知道为什么自定义变量以来却仍然未定义...
在IDE或控制台中没有错误,在我console.log()时只有 undefined

编辑:这是一些周围的环境...这是我的 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);


谢谢!

最佳答案

这是您的问题:

resources.popularity += popularityTotalPerTick;

受欢迎程度是一个对象,它并不能满足您的需求。

由于您用添加了值的对象的结果覆盖了它,因此您为其分配了一个字符串[object Object]9,其中最后一位是PopularTotalPerTick中的任何一位。

由于在NaN中使用Number(x),因此得到console.log(Number(resources.popularity.upgProd));(不是数字)。你为什么要这么做?

每次调用函数时,getId都会在dom中查找元素吗?对象是否已更改,或者您每秒要对DOM查询同一元素7次?


关于代码中其他内容的一些想法:

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);


我不确定为什么只对两座建筑物而不是对所有建筑物都这样做,但是您也可以在 slice中使用reduce

var scienceTotalPerTick =
BUILDINGS.slice(2,4).reduce( (sum, item) => sum + (item.sciProdBase * item.count), 0);


请注意,slice的参数开始到结束(不包括结束),因此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() );


其中update是您的函数,1000/7为您提供每秒7次的间隔,而getElementsToUpdate是使一次花费大量时间从DOM获取元素的函数。

您需要更改update函数以使用参数(名称并不重要,但应简短且具有描述性,因此我使用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);
}



当不是插入的html时,我不喜欢使用.innerHTML。如果不是html,请始终改用.textContent。在这种情况下,最好使用 output元素并设置.value属性。

关于javascript - 即使值存在,属性也会返回未定义…?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49526191/

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