Reputation: 115
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.
Upvotes: 0
Views: 190
Reputation: 15912
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";
}
Upvotes: 1
Reputation: 22474
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 : "";
};
Upvotes: 1
Reputation: 479
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.
Upvotes: 1