Javascript: How can I use object properties in functions using the parameter? - javascript

I am a beginner to Javascript and I am trying to make a text-based game for practice. I have made objects for enemies like so:
export const spider = {
strength: 1,
health: 4,
gold: 1
};
I am now trying to make a function which can search for their stats when their name is entered in the field. It looks like this:
export const findStats = (target) => {
return target.health;
}
However, when I do this and test it I get 'undefined.' However, if I replace 'target.health' with 'spider.health' it works properly.
The error occurs when I try doing findStats("spider") which gives me the 'undefined results.'
Any help would be appreciated. Note: I did look around this site but found the threads too complex or not quite what I was looking for. I am a beginner so simple terms would be greatly appreciated!
Thanks for all your comments!
My issue is unlike to the one on the right as when I try it with my code is still returns 'undefined.' Here is the code that I have just tried using the other thread. Keep in mind I am a beginner so I am probably doing it very wrong but if you could help further I would be very happy.
export const findLocalStats = (target) => {
var bar = 'strength';
console.log(target[bar]);
}
Here are is my test command:
expect(findLocalStats("spider")).toEqual(1);
Furthermore, when I tried the code written in JSFiddle in my editor, it still gave the same error in the terminal which is 'undefined.'
export function findStats(target) {
return target.strength;
}
And the test command:
expect(findStats("spider")).toEqual(1);
And the exact error message:
findStats() gives the stats of the target wanted.
expect(received).toEqual(expected)
Expected value to equal:
1
Received:
undefined
Difference:
Comparing two different types of values. Expected number but received undefined.
Sorry if this is very tedious.
Note 2: I posted this question before but I have changed it to attempt to explain my issue better as I still do not understand the answers I was given and the links to duplicate questions - which I have tried to replicate. Furthermore, the duplicate that I was given was different. It used the object as the keyword, however I want to use it as a feed-in to a parameter so that it is versatile for more than one enemies if that makes sense. Thank you!

When you are calling findStats like this : findStats("spider") you are sending a string to the function as an argument. That's why when it tries to get the property health it says undefined.
You need to give the function an instance of your spider object. To create an instance you can use the Object.create() method like var killMe = Object.create(spider). This will create a new object based on the one you declared before. Then you can call your function like this : findStats(killMe)
You can find an exemple here : https://jsfiddle.net/10ex1xqt/

Related

Vanilla JS - hoisting a querySelected variable to Window

I've been researching and trying different solutions to this literally all day.
** EDIT: regarding duplicate post: As I wrote below, a set timeout function has been attempted and successful around the function call. Please, before you close my question, atleast ask that what you’re describing as a duplicate hasn’t already been attempted… or in this case. INCLUDED in my original post. I’m not looking for cred, I’m looking for help. **
I have a reusable function takes in 3 params:
What to wrap,
wrap in what type of element
and the id of the new wrapping element (so I can control access it later.)
Here's a codeSandbox version to help you help me! https://codesandbox.io/s/queryselector-to-globe-jbffk0?file=/index.html
Goal: I'd like to include a querySelector within the function that takes in the id to eliminate the extra step, to ensure the selector is defined after the item is created, and to keep a cleaner code-base. The problem is I keep fighting between a function that's surrounded by parens...
Var wrap = (function(params){...})(window); to potentially give global scope to the queryselector(object ref) I'm trying to create, and a standard es6 function I'm more familiar with... Var wrap = (params) => {...};
import "./styles.css";
const item = document.querySelector(".item");
var wrap = (function (toWrap, wrapper, id) {
wrapper = wrapper || document.createElement("div");
wrapper.setAttribute("id", `${id}`);
toWrap.parentNode.appendChild(wrapper);
// Non-working auto id something to
// window.id = document.querySelector(`${id}`);
return wrapper.appendChild(toWrap);
})(window);
// How can I "store the window.id" just as if it were manually written right here in global scope?
wrap(item, "div", "itemadded");
Note: the window thing I read at: http://markdalgleish.com/2011/03/self-executing-anonymous-functions/
Like I said, I can provide more working code/attempts to show I've made a ton of effort if anyone is wondering.
PS, I'll definitely mark the answer and give upvotes for help.
Thanks in advance!
If your still reading, I've tried simplifying even further, adding a timeout function to ensure that the function takes in toWrap correctly... idk what else to try... :(

Pass Component Name as Argument and then attach method (not working?)

Maybe I'm not using the right terms/names for my searches but I have not been able to find anything on this topic. I would have thought this would be an easy thing to find. What I'm doing is passing a component name to a function and then trying to use the component's name by attaching a method to it. I have confirmed (via Dev Tools) that the name is correctly being passed but when I use the variable and attach the method the specific request does not work. If I 'hard-code' the exact component name to the method it works perfectly. This makes me think the (various) ways I've been trying to attach the method to the variable name is incorrect (see various attempts below). Can you offer some direction here? Thank you.
Passing to Function ...
const grid_name = "grid_GroupA";
console.log(grid_name); // Shows grid_GroupA
msg_max(newItem, grid_name);
Function (only listing relevant parts)
function msg_max(newItem, grid_target) {
console.log(grid_target); // Shows grid_GroupA
// grid_GroupA.data.add(newItem); // This works ...
// grid_target.data.add(newItem); // This does not work
// (grid_target).data.add(newItem); // This does not work
// [grid_target].data.add(newItem); // This does not work
// grid_target + '.data.add(newItem)'; // This does not work
Thank you ...
Edit ...
In my attempt to provide detail I hope I haven't confused the issue.
In essence, my question is if I can type this exact string
grid_GroupA.data.add(newItem);
and it works for my function, how can I place a variable with the exact string "grid_GroupA" in front of ".data.add(newItem);" and have it seen the same as the line of code that works? Maybe my lack of knowledge here is getting in the way but isn't the line of code that works just a string that is then used to 'find' the object? So, if that assumption is correct, how do I create that same string with the variable? If my assumption is wrong I am a willing learner so I will be all ears. Thank you.
I do not see how grid_target is an object. You are passing grid_name(which is a string) to the function, so grid_target will have no data property, because string doesn't have such a member.
P.S. snake_case is bad option for JavaScript, consider using cameCase instead

Getting deformation object in spark ar environment

I am trying to get deformation object to change it properties by JS, but I cannot even get it by any Spark module.
Spark AR have sample project with face distortion deformation.
https://developers.facebook.com/docs/ar-studio/tutorials-and-samples/samples/face-distortion/
You can even see in tutorial, that there is some morph object attached, which called faceDistortionPack. This object is located in assets, and I tried to get it by different ways in script, but couldn't make it. I want to write some js logic to manipulate deformations.
const Scene = require('Scene');
const Diagnostics = require('Diagnostics');
const faceMesh = Scene.root.find('facemesh_distortion');
Diagnostics.log(faceMesh); // FaceMesh: https://sparkar.facebook.com/ar-studio/learn/documentation/reference/classes/scenemodule.facemesh
Diagnostics.log(faceMesh.deformation); // null
Diagnostics.log(faceMesh.find('faceDistortionPack')); // Exception...
// ....
I want to get 'faceDistortionPack' object to access it properties, like 'nose_z', so I can change them by JS.
Although this is a pretty old question I thought I'd answer anyway if anyone struggles with this and comes across this thread.
First of all: There's an amazing collection of helpful tips, tutorials, snippets etc. called Spark AR Community. There you can find a GitBook with an alternative, better indexed and better working version of the official script object reference. I recommend using it if you're lost in the official reference or it's not working which happens quite often. There you can see, that the BlendShapesMesh, mentioned in the previous answer is deprecated as of Spark AR v85+, so that won't help anyone. ()
So, what you are trying to achieve, if I understand it correctly, is to access the faceMesh's Blendshapes and change their value through script. What you need to do is this:
Follow the instructions in this Tutorial: https://sparkar.facebook.com/ar-studio/learn/tutorials/face-distortion-retouching/
After you applied the Blendshapes, mess around a bit with adjusting the Blendshapes, so you understand what's happening.
Add a script to your assets. You're gonna want to access the faceMesh-Object's Blendshapes' weight Property through script. That can be done by using the getBlendshapes()-Method of the Mesh-Class.
Here's a code example:
//Require Modules
const Scene = require('Scene');
const Diagnostics = require('Diagnostics');
const Reactive = require('Reactive');
//Enable async/await [part 1]
(async function () {
//Load Assets as Promise
const loadAssets = await Promise.all(
[
Scene.root.findFirst("faceMesh0"), //Put name of your facemesh here, default is faceMesh0
]
).then(function(assets){
const faceMesh = assets[0]; //Assign the facemesh from the assets-Array of the promise to a variable you can work with better
const faceMeshShapes = faceMesh.getBlendShapes(); //Access all Blendshapes of the faceMesh-Object and store them in an Array
What you have now is a variable called faceMeshShapes, that's an object with an array of Blenshapes in it. You can console log it with Diagnostics.log(faceMeshShapes) and see that there's an array called "_value" in it, that's filled with all Blendshapes as objects, that have a weight-Property, which specifies the weight of the Blendshape with a scalarValue. You can consolelog this Value by converting it with the pinLastValue()-Method of the scalarValue-Class and you can assign different values by binding it to a custom value, that you convert to a scalarValue by using the val()-Method from the Reactive-Module.
Here's an example:
Diagnostics.log(faceMeshShapes._value[0].weight.pinLastValue()); //console log the Value of the weight property's scalarValue of the Blendshape that's stored at the index 0 of the _value-Array
faceMeshShapes._value[0].weight = Reactive.val(0.5) //set the weight to 0.5
Diagnostics.log(faceMeshShapes._value[0].weight.pinLastValue()); //console log the changed value of the weight property
So basically, that's how you can access every Blendshape's weight. The index should be according to the order in which they are listed in spar AR studio, beginning with 0 for the first BlendShape. Now you can do lots of things with this value, like binding it to an animation that animates it from 0-1 or to the mouth-openess using the face-tracking module and so on.
Last but not least, don't forget any semicolons and close all brackets.
});
})(); // Enable async/await [part 2]
P.S.: It can really help sometimes to understand what's happening and how to access stuff, by console logging a list of all properties of an object. Especially since the spark AR documentation is pretty weak on that part (and pretty weak in general). You can use the following function from MDN to do that. It's nothing fancy, but it does the job and has saved me a couple of times already :)
function listAllProperties(o) {
var objectToInspect;
var result = [];
for(objectToInspect = o; objectToInspect !== null;
objectToInspect = Object.getPrototypeOf(objectToInspect)) {
result = result.concat(
Object.getOwnPropertyNames(objectToInspect)
);
}
return result;
}
The link you posted isn't live any more.
I'm guessing the below links are more relevant now for others looking into this. I animated a series of blendShapes, and these links were useful. Basically cycling through the weights of each blendShape.
https://sparkar.facebook.com/ar-studio/learn/documentation/reference/classes/scenemodule.blendshapesmesh
https://sparkar.facebook.com/ar-studio/learn/documentation/reference/classes/scenemodule.blendshape

JavaScript Variable calls function, but stays undefined

I'm extremely new to JavaScript and am attempting to make a very simple game of 'Rock, Paper, Scissors' that is played through the console.
Here is a jsfiddle.net link to the full thing.
The main issue so far is that, every single round, the game will result in a Tie (another one is that incorrect inputs in humanTurn() lead to an error further down the line, but that's not relevant to this topic which I feel is more pressing).
Both humanTurn() and computerTurn() seem to work fine when called individually, however when called within gameRound(), the two console.log()'s (lines 36 and 38) don't seem to be returning a value of any kind, and in the console these show up as ƒ toLocaleUpperCase() { [native code] }. I tried searching for what this could mean, and the only conclusion I've been able to come up with so far is that no value is actually being stored inside of the two variables, AIChoice and HUChoice, and I cannot fathom a reason for why this would be happening.
Any and all help is greatly appreciated!
computerTurn().toLocaleUpperCase and userTurn().toLocaleUpperCase are both functions and since they are on the String prototype, they are both the same function. If you compare them, they will always be equal.
You need to actually call the function in order to get the values you want:
let AIChoice = computerTurn().toLocaleUpperCase();
console.log(AIChoice);
let HUChoice = humanTurn().toLocaleUpperCase();
console.log(HUChoice);

Having trouble understanding a reflection test in Javascript Koans

There is already an answer posted to the test itself, which can be found here, but I can't seem to figure out why that answer is correct.
The part of the test that is giving me trouble is:
var keys = [];
var fruits = ['apple', 'orange'];
for(propertyName in fruits) {
keys.push(propertyName);
}
ok(keys.equalTo(['__', '__', '__']), 'what are the properties of the array?');
The (apparently) correct answer, as noted in the above linked question is
ok(keys.equalTo(['0', '1', 'fruits.prototype'), 'what are the properties of the array?');
I tried inserting the answer - fixed the syntax error - and my test still fails.
In the same test file, another test is nearly identical and the answer is what I would expect it to be:
test("property enumeration", function() {
var keys = [];
var values = [];
var person = {name: 'Amory Blaine', age: 102, unemployed: true};
for(propertyName in person) {
keys.push(propertyName);
values.push(person[propertyName]);
}
ok(keys.equalTo(['name','age','unemployed']), 'what are the property names of the object?');
ok(values.equalTo(['Amory Blaine',102,true]), 'what are the property values of the object?');
});
The only difference I can see between these two tests is that the second is using an object rather than an array.
I ran the code from the first test by itself (outside of the unit testing framework) and output the value of keys, which it showed as ["0","1"] - what I would expect. Where is this hidden third value, and how can I access it?
So, I guess I ultimately have two questions:
Why is the answer from the other question not working for me?
What is different about the first test and the second test?
Disclaimer: I'm pretty sure this is right, but haven't bothered testing it. Could you try my answer out, since you've got the tests running?
Looking at the files on GitHub, there is a helper script called koan.js. I'm assuming it gets loaded before the tests because I am too lazy to run them myself :P. (It's in the support directory.)
In this file, there is a method called equalTo defined on all arrays:
Array.prototype.equalTo = function(compareTo) { ... }
So the answers to your questions:
Because the answer to the other question was wrong. Completely misguided. Etc.
Because the method is defined on Array rather than Object.
Seems a little bit underwhelming.
If you define a function like this on the prototype, it will be inherited by all arrays. Try defining something like that in the console and then evaluate [].equalTo. And then, for more fun, try something like:
for (x in []) console.log(x)
Since this method is defined on the prototype, the loop iterates over it as well. So the answer is to the test is probably 0, 1, 'equalTo'. However, if you use the for loop with the hasOwnProperty check, it will naturally not iterate over the method.
This is really an object lesson about no using for in to iterate over arrays :). You never know what's going to sneak in... Coincidentally, this is why prototype.js fell out of favor despite actually being a nice framework.

Categories

Resources