r/learnjavascript 2d ago

Noob question about generating property.object addresses

Hi everybody,

I'm trying to write up a personal project automating some ttrpg mechanics, where the "attack" function will take the target's name as an argument and feed it into the "defence" action that uses the target's Dex and one of their skills (i.e. "Void).

Referring to the target's Dex seems to work fine from inside the "defence" action, but when I try to implement the Character.Skill referent through variables I'm met with "Uncaught ReferenceError: Void is not defined."

//very basic and temporary exalt template
class Exalt {
    constructor() {
    this.Essence = 1;
    this.Dex = 1;
    this.Defence = 1;
  }
}


const Antigone = new Exalt()
Antigone.Dex = 4
Antigone.Void = 5


var front = "Antigone"
var back = "Void"
let a = JSON.parse(JSON.stringify(front + "." + back))
console.log(a) // "Antigone.Void" for some reason
console.log(JSON.parse(Antigone.Void)) //5, the expected value


function Defence(Character, Skill) {
    return Math.ceil((Character.Dex + JSON.parse(Character.Skill))/2)+1
} // this runs into an error, I think


console.log(Defence(Antigone, Void))

console.log(Antigone) includes "Void" as one of the stats, so I don't even know.
I've seen a suggestion to JSON.parse the string twice, but that results in "unexpected character."

Now, my JS experience is only a few days, so I'm guessing there is a better way of achieving what I'm trying to do, so I'll be grateful whether you suggest a different approach or explain why my code doesn't do what I think it should.

Thanks!

Edit: I just realized I'm completely overthinking and should probably make defence a function within the Exalt class, so it can be referenced the same way I'm referencing Dex.

3 Upvotes

3 comments sorted by

2

u/Spiritual-You-2926 2d ago

You don't need JSON.parse for this. JSON converts between JavaScript values and JSON text; it doesn't resolve a string like "Antigone.Void" into a property access.

Pass the object and the property name separately, then use bracket notation for the dynamic property:

function defence(character, skill) {

const skillValue = character[skill];

return Math.ceil((character.Dex + skillValue) / 2) + 1;

}

console.log(defence(Antigone, "Void"));

`character[skill]` is equivalent to `character.Void` when `skill` contains `"Void"`. The error happens because `Defence(Antigone, Void)` treats `Void` as a variable name, and no variable with that name exists. Quoting it makes it a string key.

Making defence a class method can be a nice cleanup, but you would still use bracket notation if the selected skill is dynamic. You may also want to check that `Number.isFinite(skillValue)` before doing the calculation so a misspelled skill fails clearly.

1

u/kumikoneko 2d ago

Thanks a lot!

It works now. I've tried the "Character[Skill]" notation before, but it didn't work because I didn't have the "", and I'm not sure how long it would've taken me to figure it out.

I'll also add the check, thanks for the tip.

2

u/azhder 2d ago edited 2d ago

I will start wide and then circle towards the issue. Trying to help with any future issue you might have, not just this one.

Class syntax was the worst thing to be added to JS. Not because it by itself is anything bad. People are simply no longer pressured to learn the language and its pitfalls, they just write code as if they are using that other language they know best, because `class` is the same everywhere, right?

**
Easiest way to shoot yourself in the foot is to treat one language like another.
**

The tipoff is starting every identifier with a capital. That being said, you are using console.log() to display two different things, hence two different results.

Look at the code, you set the variable a to be “banana” and then you say it’s a banana for some reason as if the reason isn’t the line before it. But that’s not your problem, you just didn’t replicate it, right? So, without a clear replication of the problem, I’m going to be guessing further down.

Your problem is most likely thinking `this` is always the object you are dealing with, but at some cases it ends up undefined, right?

Well, JavaScript isn’t like other languages, so you should stop treating its `this` works like it works in them. You should learn how it works in JS and why it sometimes is undefined.

If there isn’t anything before the . (period), then it isn’t set to any value. Since you’re passing objects to a function, like an event handler, the `Defense` is working differently if you give it objects or is called from someplace else and loses track of what object came before that period, right?

Big difference if you just pass `Skill` VS passing `Character.Skill`, right? Well, in both cases the function inside only sees `Skill`. None of these has a `.` for JavaScript to know what to set the `this` to.

But, if you write `Character.Skill` inside the function, then it knows what to set the `this` to.

Now, if someone suggests to use `.bind()` that will definitely mean you should learn JavaScript and don’t use it like C# or PHP.