Ely
Ely

Reputation: 11174

Instantiating object in a function gives "Uncaught TypeError: undefined is not a function"

I tried to look most of the suggested search results concerning the error message I receive, but unfortunately none is talking about a case that is similar to mine. So I believe this is not a duplicate.

(In particular I don't use jQuery, I don't want to use it. Besides, the accepted answer given is correct and it does not involve jQuery, it elaborates the understanding of hoisting in JavaScript.)

I wonder Why the code below (2nd code snippet) does not work? I can't figure that out.


This code works. I instantiate Cell objects outside the drawGrid function.

 'use strict';

 var dim = 20;
 var side_length = 25;

 var canvas = document.getElementById('world');
 canvas.width = 500;
 canvas.height = 500;
 document.body.appendChild(canvas);

 if (canvas.getContext) {
   var ctx = canvas.getContext('2d');
   drawGrid(ctx);
 }

 var Cell = function(x, y, alive, context) {
   this.x = x;
   this.y = y;
   this.alive = alive;
   this.ctx = context;
 };

 Cell.prototype.draw = function() {
   if (this.alive === true) {
     this.ctx.beginPath();
     this.ctx.arc(this.x + side_length / 2, this.y + side_length / 2, 10, 0, 2 * Math.PI);
     this.ctx.fill();
   }
 };

 for (var i = 0; i < dim; i++) {
   for (var j = 0; j < dim; j++) {
     var x = i * canvas.width / dim,
       y = j * canvas.height / dim;
     new Cell(x, y, true, ctx).draw();
   }
 }

 function drawGrid(ctx) {
   for (var i = 0; i < dim; i++) {
     for (var j = 0; j < dim; j++) {
       var x = i * canvas.width / dim,
         y = j * canvas.height / dim;
       ctx.strokeRect(x, y, side_length, side_length);
     }
   }
 }
<canvas id='world'></canvas>


This code does not work. I instantiate the Cell objects inside the drawGrid function.

 'use strict';

 var dim = 20;
 var side_length = 25;

 var canvas = document.getElementById('world');
 canvas.width = 500;
 canvas.height = 500;
 document.body.appendChild(canvas);

 if (canvas.getContext) {
   var ctx = canvas.getContext('2d');
   drawGrid(ctx);
 }

 var Cell = function(x, y, alive, context) {
   this.x = x;
   this.y = y;
   this.alive = alive;
   this.ctx = context;
 };

 Cell.prototype.draw = function() {
   if (this.alive === true) {
     this.ctx.beginPath();
     this.ctx.arc(this.x + side_length / 2, this.y + side_length / 2, 10, 0, 2 * Math.PI);
     this.ctx.fill();
   }
 };


 function drawGrid(ctx) {
   for (var i = 0; i < dim; i++) {
     for (var j = 0; j < dim; j++) {
       var x = i * canvas.width / dim,
         y = j * canvas.height / dim;
       ctx.strokeRect(x, y, side_length, side_length);
       new Cell(x, y, true, ctx).draw();
     }
   }
 }
<canvas id='world'></canvas>

Upvotes: 0

Views: 132

Answers (1)

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382514

The problem is here:

 if (canvas.getContext) {
   var ctx = canvas.getContext('2d');
   drawGrid(ctx);
 }

 var Cell = function(x, y, alive, context) {

You're assigning Cell after you call drawGrid. So, inside drawGrid, Cell is undefined.

Simple fix 1, use a standard function declaration to have the assignment hoisted along the variable declaration :

 function Cell(x, y, alive, context) {

Simple (more readable) fix 2: just move the call to drawGrid at the end.

Upvotes: 3

Related Questions