1

Let's say I have a HTML/JS project which involves interaction with a canvas. Resizing, drawing, retrieving the current state, etc.

Obviously I should separate these into several functions. However, I'm unsure of the best way to go with this. There is only one canvas, so every function call will be acting on the same canvas every time.

With this in mind, would it better to pass in the canvas element (or a jQuery object, to be specific... not really relevant to the question though) as a parameter or not? For example:

function setInitialCanvasSize(canvas){
    canvas.width = 100;
    canvas.height = 100;
}

setInitialCanvasSize($("#canvas"));

vs

function setInitialCanvasSize(){
    $("#canvas").width = 100;
    $("#canvas").height = 100;
}

setInitialCanvasSize();

Which is better and why?

The first one feels like it should be better. But there's a small part of me just thinking "Why bother?", and to be honest I can't really come up with a satisfactory answer.

clb
  • 521
  • 1
  • 4
  • 3

2 Answers2

2

The first one is better for many reasons:

  1. Reusability: You can apply this behavior on any canvas as it's not directly coupled to a specific one. This may not be the best argument if you will ever only have one canvas to operate on though.

  2. Testability: The second example has hidden dependencies which makes it harder to setup unit testing. You have to setup the state of an entire DOM Document rather than simply creating an HTMLCanvasElement in memory.

  3. Performance: In the second example the canvas's DOM reference will have to be queried at least once for every operation while in the first one you could cache the canvas's DOM reference in a variable.

  4. Maintenance: At a large scale having hidden dependencies like in the second example makes the code much harder to understand and maintain.

Using the first approach doesn't mean that you have to repeat yourself every time though. You could use partial function application to bind the function to a specific canvas:

function setInitialCanvasSize(canvas){
    canvas.width = 100;
    canvas.height = 100;
}

let canvas = document.getElementById('canvas');

setInitialCanvasSize = setinitialCanvasSize.bind(null, canvas);

setInitialCanvasSize();
setInitialCanvasSize();

Obviously in a real-world application you probably shouldn't have global variables. Your application should rather expose a single global variable through which it makes it's entry point available.

plalx
  • 379
  • 1
  • 9
-1

Your intuition is right, the first one is "better" because it can be re-used for an arbitrary canvas. Therefore, if you ever have another canvas for which you want the dimensions set to 100, you already have a function set up for that purpose.

However, if you are confident that you won't ever want to use this function for a different canvas, then there's no real problem with your second implementation.

Beyond that, by the name of your function, "initSize", I infer that you only ever do this once, i.e. during initialization. If that's the case, you really don't need a function to do this work at all. Since the function (your second one) has no parameters and always executes the same two lines, I'd suggest removing the function altogether and simply explicitly execute the code which sets the width and height instead, right inline, without making any function call or having to define a function to do that work.

DDoomUs
  • 35
  • 1