Home > Back-end >  JavaScript Type Problem: How do I assign the return value of a function to a variable, but not the f
JavaScript Type Problem: How do I assign the return value of a function to a variable, but not the f

Time:01-08

I am currently working with RPG maker MZ and try to write my first plugin. Now i do have not much experience with JavaScript, only with Java, and i think this error arises from the weaker typing system compared to java. I think that the source of the problem is, that my var filteredList gets a function as its value where it actually should had actually gotten the return value of the function. so my question would be: how do i assign filteredList the correct value?

In the game, the function was supposed to replace the standard way of determine Loot from enemies. The code with the problem is the following:


 let actualDropList = new Array;
    commonItemList.forEach(matchedElement => {
            commonItemDataList.push($dataItems[matchedElement]);
            console.log($dataItems[matchedElement]);
} 
    });
    let CommonDropWorth = this.enemy().meta.HellsCommonDropBase /*  (enemy.dataObject.meta.HellsCommonDropFlat * (this.enemy.level-1))*/;
    var filteredList =  commonItemDataList.filter((Item => Item.price <= CommonDropWorth));
    var cleanFilteredList = function(){
        return commonItemDataList.filter((Item => Item.price <= CommonDropWorth));

    };
    while (filteredList.length > 0){
        let item;
        if (filteredList.length > 1){
            item = filteredList[Math.floor(Math.random()*filteredList.length)];
            CommonDropWorth = CommonDropWorth - item.price;
        }
        else if(filteredList.length = 0){
            item = filteredList[0];
            CommonDropWorth = CommonDropWorth - item.price;
        }
        actualDropList.push(item);
        filteredList = cleanFilteredList.apply;
    }
    return actualDropList;

the idea here was that each opponent has a "CommonDropWorth", which indicates the total value of common drops that this opponent drops. higher value = more drops. a while loop selects random items until the total value of the drops is close to the value of the "commondropWorth". items that have a smaller value than the commondropworth are filtered out by the function stored in the "cleanFilteredList" variable. now the variable "filteredList" is supposed to assign the return value of the function, but instead the function itself is assigned to it, and due to the type safety tabs this problem is not shown in the IDE. This leads to the following Error: TypeError Cannot read property 'price' of undefined. So my question is: how do i assign the var filteredList the return value of the function and not the function itself? Important: The filteredList must be updated every time the commonDropWorth reduces, because otherwise it would make it possible to drop Items that are more worth.

P.s, to avoid other unnessesary questions in the future: how can i ensure that my code does not try to asign objects of the wrong type? (Transparency note: i think my post was made invisible, as i made some errors during creation and some of the already given answers disappeared. This is technically a repost, but because of the circumstances, i didnt know how to get an answer on my first post.)

CodePudding user response:

I think there is something wrong with your handling of lengths of the array.

while (filteredList.length > 0){
    let item;
    if (filteredList.length > 1){
        item = filteredList[Math.floor(Math.random()*filteredList.length)];
        CommonDropWorth = CommonDropWorth - item.price;
    }
    else if(filteredList.length = 0){
        item = filteredList[0];
        CommonDropWorth = CommonDropWorth - item.price;
    }
    actualDropList.push(item);
    filteredList = cleanFilteredList.apply;
}
return actualDropList;

Three problems that I can see:

1. Wrong splitting of cases as 1 vs >1, instead of splitting as 0 versus >0

I think you have intended to split up the cases where the length is 1, from the cases where length is >1. This is not necessary, as the >1 part of the program will work just fine for the ==1 case.

2. Failing to handle the length == 0 case

The handling of length == 0 needs to make sure not to select one of the (zero!) items. Remember, when length == 0, you are not allowed to read item #0, just as when length = 10, you are not allowed to read item #10.

3. I am not sure the ".apply" function works in the way you use it.

Usually there are parentheses after .apply?

I usually put the filter in directly where it is needed, unless the function is unusually complicated. Here the boilerplate of creating a named function, and then applying it, is probably too much effort and opportunity for error, I think.

Try this, which fixes items 1 to 3 above.

while (filteredList.length >= 1){
    const item = filteredList[Math.floor(Math.random()*filteredList.length)];
    CommonDropWorth = CommonDropWorth - item.price;
    actualDropList.push(item);
    filteredList = commonItemDataList.filter((Item => Item.price <= CommonDropWorth))
}
 

return actualDropList;

Remember that you can be confident that the block inside the while loop begins with filteredList.length being 1 or more. (I prefer to call it >=1 than >0, because it helps me remember that it means "if I have at least one item on the list, I can select an item from the list".

Therefore you can get rid of the if (filteredList.length = 0). Incidentally, that should have been an == not a single =, but it doesn't matter because you are deleting it.

  • Related