3
\$\begingroup\$

Just experimenting with various Javascript techniques and was wondering if the code below is valid and if there are any disadvantages to using this technique to create html tags from JS object constructors? I know the usual technique is to add the html directly in the body and loop through an array to populate the elements.

So the two main questions;

  1. Is the code valid and are there any main reasons not to use this technique?

  2. Can the function call be integrated either into the constructor function (and called when a new object is created) or called from the new object parameter? (It somehow feels wrong to place on a separate line after every new object creator.

(function(){

function Photo(name, src){
this.name = name;
this.src = src;
    this.create = function(){
        var container = document.getElementById('thumbs_container'); 
        var img = document.createElement('img');
        img.src = this.src;
        img.alt = this.name;
        img.className = 'thumb';
        img.style.width = '200px';
        container.appendChild(img);
    }
}

var photo1 = new Photo('RED SQUARE', 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/25/Red.svg/2000px-Red.svg.png');

photo1.create();

var photo2 = new Photo('BLUE SQUARE', 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/000080_Navy_Blue_Square.svg/600px-000080_Navy_Blue_Square.svg.png');

photo2.create();

var photo3 = new Photo('YELLOW SQUARE', 'https://upload.wikimedia.org/wikipedia/commons/f/f2/Yellow_Square.JPG');

photo3.create();

})();
<div id = 'thumbs_container'></div>

\$\endgroup\$
  • \$\begingroup\$ I assume that your IIFE is intended to be executed, and have added () at the end of your code to call it. Otherwise, the code doesn't have any effect. \$\endgroup\$ – 200_success Nov 18 '15 at 0:29
4
\$\begingroup\$

I am going to answer the questions in reverse order and share some design thoughts at the end.


Can the function call be integrated either into the constructor function (and called when a new object is created) or called from the new object parameter? (It somehow feels wrong to place on a separate line after every new object creator.

Yes; it can.

The constructor function is just that; a function. In fact, it doesn't even need to be: if you move the logic from Photo.create into the constructor (which seems like a valid decision), then there is no point in this being it's own class.

To move the Photo.create logic into the constructor, just move it up a scope:

function Photo(name, src) {
    this.name = name;
    this.src = src;
    var container = document.getElementById('thumbs_container'); 
    var img = document.createElement('img');
    img.src = this.src;
    img.alt = this.name;
    img.className = 'thumb';
    img.style.width = '200px';
    container.appendChild(img);
}

However, as I stated above, this doesn't really need to be a class anymore; it's just one function.


Is the code valid and are there any main reasons not to use this technique?

No, the way you are doing this is just fine. However, as stated above, it does not need to be object-oriented for the implementation you have provided.

If your code is going to specific to what you have shown where you paint the picture as soon as you create, then this ought to be a function.


However, there is still a way that this can be improved. If you are familiar with regexes, then you know that there is such thing as compiling a regex before you actually use it. The reason for this is because compiling regexes can be a time and resource consuming process, so it's best to get it out of the way so it does not slow the the code in the middle of it.

You can do something similar here: if, in the constructor function, you..

  1. Create the element
  2. Define the container
  3. Define the class
  4. And define the width

then, you can just store this information for when you want to put the image on the DOM.

To use this, you would create a new Photo instance which would do the above in advance. Then, later in your code when you are ready to paint, you can specify (or re-specify) the source and name.

The constructor would look like this:

function Photo(name, src) {
    this.name = name || "";
    this.src = src || "";

    var container = document.getElementById('thumbs_container'); 
    var img = document.createElement('img');
    img.src = this.src;
    img.alt = this.name;
    img.className = 'thumb';
    img.style.width = '200px';

    // no painting yet

    this.create = function() {
        container.appendChild(img);
    }
}

Note how this code looks almost identical to the first code snippet in this answer. The only difference here is that you are preparing the system resources ahead of time; just like regexes. This will provide a speed boost in your code if used correctly.

var photo = new Photo(); // prepare resources for image

/* bunch of code all up until when it is needed to draw */

photo.create(); // put image/resources in DOM
|improve this answer|||||
\$\endgroup\$
3
\$\begingroup\$

Instead of using an object constructor with an IIFE, use a prototype constructor instead:

var Photo = function(name, src){
    this.name = name;
    this.src = src;
}
Photo.prototype.create = function(){
    var container = document.getElementById('thumbs_container'); 
    var img = document.createElement('img');
    img.src = this.src;
    img.alt = this.name;
    img.className = 'thumb';
    img.style.width = '200px';
    container.appendChild(img);
};

It has the same usage as your version (new Photo(name, src)).

Consider also instead of using #thumbs_container as your element, instead passing the parent element in the form of a selector string as a parameter.

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.