0

I am noticing some behaviour in the code below that I can't explain. I'm hoping that someone can enlighten me about why this is happening.

The code example below is available on JSFiddle as well if that's easier to read. https://jsfiddle.net/0b5rh4cg/

Code:

function Book() {

};

function Book (title, author) {
    this.title = title;
  this.author = author;
};

Book.prototype = {
    title: "",
  ISBN: "isbn",
  length: 100,
  genre: "genre",
  covering: "covering",
  author: "author",
  currentPage: 0,

  toString: function toString() {
    console.log("toString Function");
    console.log('Title: ' + this.title + '\n' +
                            'ISBN: ' + this.ISBN + '\n' + 
                            'length: ' + this.length + '\n' + 
                'genre: ' + this.genre + '\n' + 
                'covering: ' + this.covering + '\n' + 
                'author: ' + this.author + '\n' + 
                'currentPage: ' + this.currentPage + '\n');
  }
};

var book1 = new Book();
book1.toString();

var book2 = new Book("First edition", "Random");
book2.toString();

Output of book1.toString() toString Function Title: undefined ISBN: isbn length: 100 genre: genre covering: covering author: undefined currentPage: 0

Output of book2.toString() toString Function Title: First edition ISBN: isbn length: 100 genre: genre covering: covering author: Random currentPage: 0

My confusion surrounds the author and title fields. In the null constructor, these fields default to "undefined" instead of the ones set out in the prototype for the Book class.

Thanks to anyone who helps with this.

Cheers, Cam.

1
  • JS doesn't support parameter polymorphism, the second book overwrites the first. Commented Sep 30, 2016 at 15:41

3 Answers 3

1

JavaScript is not like Java (or other programming languages) where you can have methods with the same name or multiple constructors if they have different number or type of parameters. In this case, you've replaced Book() with Book(title, author)

To achieve what you want, you can do something like this:

function Book (title, author) {
    this.title = title||"";
    this.author = author||"";
};

In this case, title and author will default to an empty String.

Or something like this:

function Book (title, author) {
    this.title = title && author ? title : "";
    this.author = title && author ? author : "";
};
Sign up to request clarification or add additional context in comments.

1 Comment

I see what your saying, Titus. Thanks for the information.
1

Properties you define in function constructor will always override the ones defined on the prototype.

Whe the JavaScript engine is providing a prototype value it will first look it up (hasOwnProperty) on the instance, than on it's prototype chain.

Because you implicitly declared title and author in the function constructor, the new operator crated the object with these two properties on it's instance space so the object looks like this:

Books { title:undefined, auto:undefined, proto:{ title: "", ISBN: "isbn", length: 100, genre: "genre", covering: "covering", author: "author", currentPage: 0, proto: Object } }

So when the property is first ask the JavaScript engine will return the ones on the instance that were initialized as undefined, because no arguments where passed when created with new.

2 Comments

This is really great information. Thanks @fistuks!
Most welcome, for further knowledge i suggest you read aout the prototype chain on the MDN: link
1

In your initial Book function

function Book (title, author) {
  this.title = title;
  this.author = author;
};

you are passing in nothing, so the parameter enters the function with a value of undefined. Since you are declaring both title and author you are still assigning a value to both of them, which in this case is undefined.

The first lookup on the Book object hits your declared properties which both have a value, so you get the returned values of undefined. Since there is a value for both of these properties of Book the lookup stops and does not propagate up the prototype chain as you are most likely expecting.

If you would like to set default values when you are not passing in parameters to the called function, then just add this to your function.

function Book (title, author) {
  this.title = title || "";
  this.author = author || "author";
}

1 Comment

Thanks for filling in the remaining pieces of the puzzle @SoEzpZ. This answer with the other two provides a very detailed and complete answer to the original question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.