javascripthtmlhtml5-canvastypeerror

Uncaught TypeError: canvas.getContext(...) is not a function


I get the Uncaught TypeError: canvas.getContext(...) is not a function error whenever I try to call canvas.getContext(). Here's the code, why am I getting this error?

Here is the my code:

/**
 * @type {HTMLCanvasElement}
 */
const canvas = document.getElementById("canvas")
/**
 * @type {CanvasRenderingContext2D}
 */
const ctx = canvas.getContext("2d")

(window.addEventListener("resize", () => {
  canvas.width = window.innerWidth; canvas.width = window.innerHeight;
}))()

canvas.style.border = "2px solid black"
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Pythagoras Theorum Proof</title>
</head>
<body>
  <canvas id="canvas"></canvas>
  <script src="./script.js"></script>
</body>
</html>

(I need the JSDoc to identify canvas as HTMLCanvasElement and ctx as CanvasRenderingContext2D as I use VS Code and need help of its intelliscience)


Solution

  • I added a few semicolons and I also ensured that the addEventListener's return value is not call. You add an event listener for resize, which is cool. Don't call the result, because addEventListener does not return anything, see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener, that is, it returns undefined, which is not a function and therefore you cannot call it.

    const canvas = document.getElementById("canvas");
    const ctx = canvas.getContext("2d");
    window.addEventListener("resize", () => {
      canvas.width = window.innerWidth; canvas.width = window.innerHeight;
      console.log("resized");
    });
    
    canvas.style.border = "2px solid black";
    <canvas id="canvas"></canvas>

    EDIT

    Since in the comment section I was asked for a more thorough explanation and the initial version of this answer was more of an operative character, I have a theoretical debt of providing this explanation, so here it goes.

    This is where the original code breaks:

    const ctx = canvas.getContext("2d")
    
    (window.addEventListener("resize", () => {
      canvas.width = window.innerWidth; canvas.width = window.innerHeight
    }))()
    

    The reason for the problem is that without the ; after const ctx = canvas.getContext("2d"), the code looks like this for the compiler:

    const foo = wunder.bar()
    (some.func("something", () => {
        //some things
    }))()
    

    So, the compiler assumes that the wunder.bar() returns a function, which you call, passing the result of some.func(...), which is another function and you call it with the last paranthesis of ().

    Example:

    let wunder = {
        bar: () => {console.log("Das ist wunderbar")}
    };
    
    let some = {
        func: function(text, callback) {
            return function() {
                console.log('fantastic!');
            }
        }
    };
    
    function test(mode) {
        if (mode) {
            const foo = wunder.bar()
            (some.func("something", function(txt) {
            }))();
        } else {
            const foo = wunder.bar();
            (some.func("something", function(txt) {
            }))();
        }
    }
    <input type="button" value="error" onclick="test(1)">
    <input type="button" value="success" onclick="test(0)">

    Read more here: https://www.geeksforgeeks.org/semicolon-in-javascript/