Trying to populate string with values from object properties - getting "undefined" - javascript

I am trying to solve the below Javascript kata on Codewars but getting "undefined". Can please someone show me the light on what exactly is "undefined". I am struggling to understand what is missing form my code below. Cheers.
Link to challange: https://www.codewars.com/kata/training-js-number-5-basic-data-types-object
I've searched through FreeCodeCamp JS OOP and Basic tutorials / lessons to find similar problems. Searched through StackOverflow, Reddit, and Googled many websites for similar challanges.
Code below:
function animal(name, legs, color) {
this.name = name;
this.legs = legs;
this.color = color;
}
var dog = new animal("dog", 4, "white");
// similar variables set such for other animal objects.
animal.prototype.toString = function animalToString() {
var sent = "This " + this.color + " " + this.name + " has " + this.legs + " legs.";
return sent;
}
return animal.prototype.toString.call();
Expected: This white dog has 4 legs., instead got: undefined

Try this:
function animal(obj){
var newAnimal = {
name: obj.name,
legs: obj.legs,
color: obj.color
};
return "This " + newAnimal.color + " " + newAnimal.name + " has " + newAnimal.legs + " legs.";
}
The purpose of this kata I believe is to introduce you to javascript objects. The issue is thrown when you changed the inputs of the function "animal". If you look at the sample tests in the lower right corner, the inputs being fed into the function you are trying to make should accept only one parameter which is an object with properties name, legs, and color. You changed this input into three separate parameters instead of just one.
Or you could skip the assignment altogether and just access the input directly like so:
function animal(obj){
return "This " + obj.color + " " + obj.name + " has " + obj.legs + " legs.";
}

1) Based on 'instructions'
Give you a function animal, accept 1 parameter obj like this: {name:"dog",legs:4,color:"white"} and return a string like this: "This white dog has 4 legs."
function animal({name, legs, color}) {
return `The ${color} ${name} has ${legs} legs.`;
}
2) Based on what you're supposed to learn
function animal({name, legs, color}) {
this.name = name;
this.legs = legs;
this.color = color;
}
animal.prototype.toString = function animalToString() {
return `The ${this.color} ${this.name} has ${this.legs} legs.`;
}
var dog = new animal({name:"dog", legs:4, color:"white"});
dog.toString();

function animal(obj){
return `This ${obj.color} ${obj.name} has ${obj.legs} legs.`
}

You can try this
function animal(obj){
var a={name:"dog",legs:4,color:"white"}
return "This" + " " + a.color + " " +a.name + " " + "has" + " " + a.legs + " " + "legs.";
}

Related

Why I am getting undefined on using document.write()?

Why I am getting undefined in browser while using document.write() ?
<script type="text/javascript">
function Person (name) {
this.name = name;
this.greeting = function() {
document.write("Hello " + name + " Go rock the industry!!");
};
}
var person1 = new Person("Sara");
var person2 = new Person("Bob");
document.write(person1.name + "<br>");
document.write(person1.greeting() + "<br>");
document.write(person2.name + "<br>");
document.write(person2.greeting() + "<br>");
</script>
In browser I get this output:
Sara
Hello Sara Go rock the industry!!undefined
Bob
Hello Bob Go rock the industry!!undefined
You are trying to use document.write on a function that does not return a value, rather performs document.write itself. Person.greeting() should return a value so you can use it when calling document.write(person2.greeting()).
It should be something like this:
function Person (name) {
this.name = name;
this.greeting = function() {
return ("Hello " + name + " Go rock the industry!!");
▲
};
}
You need to update the greeting function to return a string instead of calling document.write() itself.
Currently, the greeting function is calling document.write() and then implicitly returning the value undefined.
When you evaluate the expression
personX.greeting() + "<br/>"
it evaluates to
undefined + "<br/>"
and, according to the rules of JavaScript string concatenation, undefined is first cast to the string "undefined" and then concatenated with the next value.
Edit:
If you're interested in exploring property getter functions, you could also refactor as
function Person (name) {
this.name = name;
Object.defineProperty(this, 'greeting', {
get: function() {
return "Hello " + this.name + " Go rock the industry!!";
}
});
}
var person1 = new Person("Sara");
var person2 = new Person("Bob");
document.write(person1.name + "<br>");
document.write(person1.greeting + "<br>");
document.write(person2.name + "<br>");
document.write(person2.greeting + "<br>");
Notice how we can then access the computed value personX.greeting as if it were just a string property.
Depending on your environment, etc., if you can use ES2015+ syntax, you could achieve the same result with
class Person {
constructor(name) {
this.name = name;
}
get greeting() {
return `Hello ${this.name} Go rock the industry!!`
}
}
let person1 = new Person('Sara');
let person2 = new Person('Bob');
document.write(person1.name + "<br>");
document.write(person1.greeting + "<br>");
document.write(person2.name + "<br>");
document.write(person2.greeting + "<br>");

is there a way to get info from a variable that is defined inside a function?

I am trying to figure out if there is a way to access the information stored inside a variable that I defined inside a function? I am kinda confused on how to do what I am trying to do here...
note: this isn't the full code, but the piece of the code I need help with.
let question1 = new Question("What is California State Flower?", "1. Rose. 2. Tulip. 3. Poppy");
firstQuestion();
function firstQuestion(){
let someAnswer = prompt(question1.questionName + " " + question1.questionString);
}
if (someAnswer == "poppy"){
I am trying to use the if statement to figure out if a question answer is correct, but I can't do that because someAnswer was defined inside the function.... and i'm not sure if there is a way to do this without using a function?
Update:
Ok, I got that piece working, but now my code's if/else statement isn't working. if i put in the wrong answer, it says I have the right answer. I don't really see any logical reason for that...
//store score total
let pointsCount = 0;
//questions
class Question {
questionName: string;
questionString: string;
constructor(questionName:string, questionString:string){
this.questionName = questionName;
this.questionString = questionString;
}
}
//question one
let question1 = new Question("What is the California State Flower?", "1. Rose. 2. Tulip. 3. Poppy.");
let firstAnswer = firstQuestion();
function firstQuestion(){
return prompt(question1.questionName + " " + question1.questionString);
}
if (firstAnswer === "Poppy" || "poppy"){
pointsCount ++;
alert("You got it!" + " " + "You now have" + " " + pointsCount + " " + "points!");
} else {
alert("Wrong!" + " " + "You now have" + " " + pointsCount + " " + "points!");
}
//question two
let question2 = new Question("What is the California State Bird?","1. Quail. 2. Eagle. 3. Penguin.")
let secondAnswer = secondQuestion();
function secondQuestion(){
return prompt(question2.questionName + " " + question2.questionString);
}
if (secondAnswer === "quail" || "Quail"){
pointsCount++;
alert("You got it!" + " " + "You now have" + " " + pointsCount + " " + "points!");
} else if (secondAnswer !== "quail" || "Quail") {
alert("Wrong!" + " " + "You now have" + " " + pointsCount + " " + "points!");
}
You're close; you're not returning anything from your firstQuestion function, so nothing's ever really going to happen when you run this.
let question1 = new Question("What is California State Flower?", "1. Rose. 2. Tulip. 3. Poppy");
let answer = firstQuestion();
function firstQuestion(){
// return whatever the user enters in the prompt
return prompt(question1.questionName + " " + question1.questionString);
}
if (answer.toLowerCase() == "poppy"){
// call .toLowerCase on your answer to ensure you've covered capitalization edge-cases
}
Maybe this is what you need
let someAnswer;
function firstQuestion(){
someAnswer = prompt(question1.questionName + " " + question1.questionString);
}

How can I add another offer to the function

I am a Javascript learner. I am practicing Javscript object properties and methods.
I want to add another offer to Black pen suppose it will be "10%", how should I go further. Please help.
Is this the correct way of writing code?
function pen(color, size, price) {
this.color = color;
this.size = size;
this.price = price;
}
var pen1 = new pen("Red", "Medium", 20);
var pen2 = new pen("Black", "Large", 35);
var pen3 = new pen("Pink", "Small", 20);
pen.prototype.offer = function() {
return "12%";
}
console.log("You have choosen " + pen1.color + " pen with " + pen1.size + " size. And its price is Rs." + pen1.price);
console.log("You have choosen " + pen2.color + " pen with " + pen2.size + " size. And its price is Rs." + pen2.price);
console.log("You have choosen " + pen3.color + " pen with " + pen3.size + " size. And its price is Rs." + pen3.price + " with " + pen3.offer() + " offer");
You can modify pen2 offer function
pen2.offer = function(){ return parseInt(pen.prototype.offer()) + 10 +"%" ; }
Probably by now you have already got your answer.Here is just another way to explore the prototype
Let use assume that pen is a stationary item.A stationary item can also be a book , a ruler ,a scale and so on.So it is safe to assume that stationary can be a parent object
And pen,ruler,book etc can be child of stationary. & child object can inherit properties.In javascript it is prototype based inheritance.
function Stationary(){
//See there is no options provided here
}
// Adding showItem & offers method to Stationary prototype property
Stationary.prototype.showItem = function(){
console.log("You have choosen " +this.item +" with " +this.color + " having "+ this.size + " size "+". And its price is Rs."
+ this.price +" with "+this.offers(this.offer) +" offer");
}
Stationary.prototype.offers = function(offer){
if(offer){
return offer;
}
else{
return "No offer";
}
}
// Creating an object with some property
var _p1Options ={
item:"Pen",
color:"Indigo",
size:"Large",
price:25,
offer:'12%'
}
//Creating a function which will accept the options
function Item (options){
this.item = options.item || "default";
this.color = options.color || "default";
this.price = options.price || "default";
this.size = options.size || "default";
this.offer = options.offer || "default";
}
//Setting Item's prototype to Stationary's constructor
// It will allow us to inherit all the properties
Item.prototype = new Stationary();
//Create a _p1 object with Item constructor
var _p1 = new Item(_p1Options);
//Item does not have showItem property,it will inherit from Stationary
console.log(_p1.showItem());
So to answer your question you can just create an object like _p1Options & assign property values(including offer) you want instead of hard coding the return value.
Check this jsfiddle for more

How to choose what argument a variable is assigned to in a function? -Javascript

Given a normal function as such;
function descriptions(awesome, cool, alright){
return (awesome || "no one") + " is awesome. " + cool + " is cool. " +
+ alright + " is alright";
}
descriptions("jane", "jack", "jefferson");
//returns "jane is awesome. jack is cool. jefferson is alright."
I would like to use the same function, but would only like to pass it the final two arguments like so:
descriptions(cool : "john", alright : "jane"); //I would like a statement similar to this that works.
//should return "no one is awesome. jack is cool. jefferson is alright."
How would the above be done?
Something different syntactically but similar semantically might be achieved using object destructuring
function descriptions({ awesome = 'no one', cool, alright }) {
return awesome + " is awesome. " + cool + " is cool. " +
+ alright + " is alright";
}
Then you just invoke it with an object with corresponding properties:
descriptions({ cool: 'a', alright: 'b'});
You can do this by passing an object:
function descriptions(info) {
// Avoid TypeError if no argument is passed
if (!info) {
info = {};
}
return (info.awesome || "no one") + " is awesome. " + (info.cool || "no one") + " is cool. " + (info.alright || "no one") + " is alright.";
}
// Use:
console.log(descriptions({
awesome: "Strong Bad",
cool: "The Cheat",
alright: "Strong Sad"
}));
Yes you can certainly achieve this!
You can use a clever trick many developers use to set a variable to a default value if one is not provided.
function descriptions(awesome, cool, alright){
awesome = awesome || "";
if (awesome === "")
{
return "no one" + " is awesome. " + cool + " is cool. " +
+ alright + " is alright";
}
else{
return awesome + " is awesome. " + cool + " is cool. " +
+ alright + " is alright";
}
}
console.log(descriptions(undefined, "jack", "jefferson"));
Here is the working code. You could also pass an empty string.
In ECMAScript 6, this can sort of be done if you change your parameters to receive an object and take advantage of destructuring assignment.
function descriptions({awesome: awesome = "no one", cool: cool = "", alright: alright = ""} = {}) {
return awesome + " is awesome. " +
cool + " is cool. " +
alright + " is alright";
}
var res = descriptions({ cool: "john", alright: "jane" });
document.body.textContent = res;
So we have someone of an emulation of named parameters. Only thing extra needed by the caller is the curly braces.
Of course browser support is limited, but transpilers are available.
You could use a different approach:
var coolLevels = {
isCool: ["Jack", "John"]
, isAlright: ["Jane", "Jefferson"]
, isAwesome: []
}
function describe(people, coolLevel, phrase) {
return people.filter(function(person){
return Boolean(coolLevel.indexOf(person))
}).join(", ") + phrase
}
function descriptions(people){
var awesome = describe(people, coolLevels.isAwesome, ' is awesome.')
var cool = describe(people, coolLevels.isCool, ' is cool.')
var alright = describe(people, coolLevels.isCool, ' is alright.')
return awesome + cool + alright
}
demo: https://jsbin.com/kahawuhelu/edit?js,console,output
That is not possible in any variety of ECMAScript (including JavaScript).
It is theoretically possible to do things like use conditional, custom logic:
function(a,b,c){
if(arguments.length === 1) {
// we're in object mode;
b = a.b
c = a.c
a = a.a || 'default';
}
}
But that is not a built in part of the language.
This is NOT possible, for example:
function foo(a,b,c){return a/(b || 1) + c;}
foo({c:1,b:2,a:3})
There is also the possibility to conditionally define values based on number of arguments:
function say (a,b,c) {
if(arguments.length === 2) {
c = b;
b = a;
a = 'cat';
}
console.log('a ' + a + ' likes a ' + b + ' and a ' + c)
}
say('dog', 'bone', 'walk') // a dog likes a bone and a walk
say('mouse', 'bowl of milk') // a cat likes a mouse and a bowl of milk
You can pass undefined, null or "" as the first parameter. E.g:
descriptions(null, "jack", "jefferson");
Since you already use awesome || "no one", any falsy value will be good enough.
Another approach would be changing the function to receive an object:
function descriptions(options) {
return (options.awesome || "no one") + " is awesome. " + options.cool + " is cool. " +
options.alright + " is alright";
}
descriptions({ cool: "jack", alright: "jefferson" });
Now, depending on your browser support, you can use ES6 destructuring parameters:
const descriptions = ({ awesome = 'no one', cool, alright }) => (
`${awesome} is awesome. ${cool} is cool. ${alright} is alright`
);
descriptions({ cool: 'jack', alright: 'jefferson' });

How to call a method in class from its replaced implementation?

Hai,
I am trying to understand few concepts in JavaScript. Consider the following code:
function Person(name, age)
{
this.name = name || "no name";
this.age = age || "age not specified";
this.printStr = function()
{
console.log("< " + this.name + ", " + this.age + " >");
};
}
p = new Person("pranav", 26);
p.printStr = function()
{
console.log("this works. also ...." + this.name);
};
p.printStr();
I want to call the implementation of 'printStr' in Person class from within the implementation of 'printStr' function in 'p'.
such that the output should be:
< pranav, 26 >
this works. also ....pranav
Any ideas? :)
The way your code is set up now, you can't do it. When you call Person as a constructor, the object that ends up being p gets set to this. So when you define printStr in the constructor, p gets an attribute called printStr. You then over-write it when you assign the second function.
Two options: A non-answer is to do what pablochan did - have the internal one be called oldPrintStr. Another option is to use the prototype inheritance:
function Person(name, age)
{
this.name = name || "no name";
this.age = age || "age not specified";
}
Person.prototype.printStr = function() {
console.log("< " + this.name + ", " + this.age + " >");
};
Then you can do this:
p = new Person("pranav", 26);
p.printStr = function()
{
Person.prototype.printStr.apply(this);
console.log("this works. also ...." + this.name);
};
p.printStr();
As far as I know there is no real subclassing in JS so to do this you should probably save the old function and then replace it.
p = new Person("pranav", 26);
p.oldPrintStr = p.printStr;
p.printStr = function()
{
p.oldPrintStr();
console.log("this works. also ...." + this.name);
};
p.printStr();
unless you save Person's printStr you can always create a temp Person object solely to extract printStr and call it:
p.printStr = function()
{
print("this works. also ...." + this.name);
(new Person()).printStr.apply(this);
};
but I guess you'll be better off if you make Person's original printStr accessible via prototype:
Person.prototype.printStr = function()
{
print("< " + this.name + ", " + this.age + " >");
};
then you have no need for temp object or saving old function and can do:
Person.prototype.printStr.apply(this);

Categories

Resources