Home > OS >  Cannot read property 'toFixed' of undefined
Cannot read property 'toFixed' of undefined

Time:10-01

im a beginner at javascript and would appreciate some help

The question:

pete's pizza place is famous for great pizza at reasonable prices. Make a program that will help pete compute the price on the orders. make sure you add on 13% tax and that you display the answer to 2 decimal places. Pete's pricing is as follows:

  • small: $5 for cheese 0.75 per topping
  • medium: $7 for cheese 1.00 for each topping
  • Large: $10 for cheese 1.25 for each additional topping

Pete only has 10 available toppings, so if an employee types in more than 10, there must be some mistake. Assume they wanted 10.

Here is my code and the error:


let order, cost, small, medium, large, topping;
order = prompt("What size pizza?");
order = parseInt(prompt("How many additional toppings?"));

if (small==5.00){
  cost = 5.00 * 1.13;
  document.write ("$5.65");
}
else {
  topping>=1==0.785 topping
}
document.write("Total $" cost topping.toFixed(2));

The last line (document.write("Total $...) has this error:

Uncaught TypeError: Cannot read property 'toFixed' of undefined

CodePudding user response:

Re: "toFixed is undefined"

  • This error is because you never assign a value to the topping variable.
  • So topping is undefined in JavaScript.
  • And you cannot use any methods/properties/members of undefined variables, so what you're doing is the same as undefined.toFixed(2), which is incorrect.

Everything else:

  • You're using let when you could be using const instead.
  • You're declaring variables far in-advance of when they're actually used (especially topping), which makes it harder to follow (as well as making it harder to quickly determine when a variable (like topping) is in a valid state or not.
  • You have unassigned (and therefore "undefined") variables: small, medium, and large.
  • You're overwriting your order variable.
  • You aren't performing any input invalidation and error-handling with your prompt and parseInt calls.
  • You should always specify the radix parameter when using parseInt otherwise leading zeroes will cause the string to be interpreted as Octal instead of Decimal.
    • You also need to use isNaN to verify that parseInt was successful.
  • You're using == with IEEE floating number values (e.g. small == 5.00) which will fail unexpectedly due to how floats work (as 5.000000001 == 5.00 is false).
    • For the same reason, you should not use non-integer number values to represent currency/money values in JavaScript. Instead you should represent money values as integer-cents and only format them as decimal numbers in the "presentation" part of your program.
  • The expression topping>=1==0.75 topping is meaningless - nor does it actually do anything useful. I'm unsure what exactly it's meant to be...
  • You should never use document.write - it's a holdover from the 1990s that should never have been added. Instead you can display text on a page by setting the textContent of an element (such as <output>) or the .value property of a <textarea> or <input type="text"> (don't forget to make it readonly).
  • Your "Total $" cost topping.toFixed(2) expression makes incorrect assumptions about JavaScript's type-coercion when concatenating strings vs. adding numbers together.
    • Instead you need to perform the arithmetic addition first (either as a parenthesized expression, or use a new variable to store the intermedia result) and only afterwards should you format it as a string and concatenate it with the "Total" part.
    • Also consider using the Intl library (it's built-in to JavaScript) to format currency values instead of hard-coding dollar-signs.

A correct implementation:

I've broken the solution's logic up into sub-functions, while the entrypoint is the pizzaProgram function.

You can run this program directly by clicking "run snippet" and answering the prompts.

const PIZZA_SIZE = {
    'SMALL' : 1,
    'MEDIUM': 2,
    'LARGE' : 3
};

function pizzaProgram() {
    
    const pizzaSize = promptForPizzaSize();
    if( !pizzaSize ) return;
    
    const toppings = promptForToppingCount();
    if( !toppings ) return;

    // cost is in integer cents.
    const costBeforeTax = getPizzaCostBeforeTax( pizzaSize, toppings );
    const costAfterTax  = costBeforeTax * 1.13;

    const costFormatted = "Total cost: $ "   ( costAfterTax / 100 ).toFixed(2);
    alert( costFormatted );
}

// Returns either a PIZZA_SIZE value, or null
function promptForPizzaSize() {
    
    // Loop until valid input is received:
    while( true ) {
        
        const inputSize = prompt("What size pizza? Enter 1 for Small, 2 for Medium, or 3 for Large. Or enter 'q' to cancel.");
        switch( inputSize ) {
        case '1': return PIZZA_SIZE.SMALL;
        case '2': return PIZZA_SIZE.MEDIUM;
        case '3': return PIZZA_SIZE.LARGE;
        case 'q': return null;
        }
    }
      
}

// Returns either an integer or null
function promptForToppingCount() {
    
    // Loop until valid input is received:
    while( true ) {
        
        const inputToppings = prompt("How many additional toppings? Or enter 'q' to cancel.");
        if( inputToppings === 'q' ) return null;

        const toppings = parseInt( inputToppings, /*radix:*/ 10 );
        if( !isNaN( toppings ) && toppings >= 0 && toppings <= 10 )
        {
            return toppings;
        }
    }
}

// Returns integer USD cents
function getPizzaCostBeforeTax( size, toppings ) {

    // Preconditions:
    if( typeof size     !== 'number' ) throw new Error("size must be a number");
    if( typeof toppings !== 'number' ) throw new Error("toppings must be a number");

    // Logic:

    if( size === PIZZA_SIZE.SMALL ) {
        return 500   ( 75 * toppings );
    }
    else if( size === PIZZA_SIZE.MEDIUM ) {
        return 700   ( 100 * toppings );
    }
    else if( size === PIZZA_SIZE.LARGE ) {
        return 1000   ( 125 * toppings );
    }
    else {
        throw new Error("This branch should never be taken.");
    }
}

pizzaProgram();

CodePudding user response:

This is the actual problem that's causing the bug you're specifically asking about:

topping>=1==0.75 topping 

This compares topping to 1 == 0.75 topping and evaluates to true if topping is greater than or equal to that. It does not set topping, and it can also never be true.

You probably want something like this:

topping = 0.75 * topping;

You are also calling toFixed on topping rather than (as you probably intend) the entire value. This should be something like:

document.write("Total $"   (cost topping).toFixed(2));

You have a lot of other problems in your code that will still cause it not to work. For example, you're checking to see if small == 5.00 which will never be true, because you never set that variable. You use the value order for both the size of the pizza and the number of toppings, then never use that value again. (order is a bad name for this variable in any case, because it is not the order, it is the size or the number of toppings.)

On top of that are matters of style such as when you should use const or whether you should use document.write at all—your code will work fine if you get some of these wrong, but it doesn't follow professional conventions.

This looks like a homework problem, and Stack Overflow is not a service for getting your homework done for you. So I have refrained from providing solutions to all these problems. But this should get you closer.

  • Related