简体   繁体   中英

The difference between the JS objects result

I was wondering why the first object instantiation returns the correct "numPages" and why the second one returns the same as "undefined". Hopefully someone could help me to clarify this doubt. Thanks in advance!

 // The constructor function function Book(title, author, numPages) { this.title = title; this.author = author; this.numPages = numPages; } // A method on the object Book.prototype.read = function() { this.currentPage = this.numPages; console.log('You read ' + this.numPages + ' pages'); } // Instatiation and object // Returns numPages = 325 var book = new Book("Harry Potter", "JK Rowling", 574); // Returns numPages as "undefined" var book = new Book({ title: "Robot Dreams", author: "Isaac Asimov", numPages: 325 }); book.read(); 

In the first case you pass 3 separate parameters which are assigned to the fields of the object.

In the second case you pass one parameter as object with properties title, author, numPages to the first parameter. So only first one is assigned and it is an object.

If you print the values after their assignment, you can see that in the first case all values are passed, but in the second case only {} is passed into the constructor as the first parameter. And it is assigned to the title property. Now title is a reference to the passed object.

 function Book(title, author, numPages) { this.title = title; this.author = author; this.numPages = numPages; console.log(' title - ' + this.title); console.log(' author - ' + this.author); console.log(' numPages - ' + this.numPages); } Book.prototype.read = function() { this.currentPage = this.numPages; console.log('You read ' + this.numPages + ' pages'); } console.log('First book'); var book = new Book("Harry Potter", "JK Rowling", 574); console.log('Second book'); var book = new Book({ title: "Robot Dreams", author: "Isaac Asimov", numPages: 325 }); 

This line of your code

var book = new Book({
   title: "Robot Dreams",
   author: "Isaac Asimov",
   numPages: 325
});

is equivalent to

var book = new Book({
   title: "Robot Dreams",
   author: "Isaac Asimov",
   numPages: 325
}, undefined, undefined);

If you want 2 cases to work you can have factory methods on the Book itself

 function Book(title, author, numPages) { this.title = title; this.author = author; this.numPages = numPages; console.log(' title - ' + this.title); console.log(' author - ' + this.author); console.log(' numPages - ' + this.numPages); } Book.create = function (title, author, numPages) { return new Book(title, author, numPages); } Book.createFromObject = function ({title, author, numPages}) { return new Book(title, author, numPages); } Book.prototype.read = function() { this.currentPage = this.numPages; console.log('You read ' + this.numPages + ' pages'); } console.log('First book'); var book = Book.create("Harry Potter", "JK Rowling", 574); console.log('Second book'); var book = Book.createFromObject({ title: "Robot Dreams", author: "Isaac Asimov", numPages: 325 }); 

In the second case, you pass an object with properties title , author and numPages . However, this whole thing represents the first argument in your constructor, title . So when you create your object, the arguments in the constructor have values:

title // {title: "Robot Dreams", author: "Isaac Asimov", numPages: 325}
author // undefined
numPages // undefined

After that, you save those values in your object. As you can see, numPages is undefined , so when you later invoke the read() method, you get that value.

Solution

If you want to be able to create the object both ways, you need to check whether the first argument passed is an object and extract the values from it first. Notice how I also check whether it's not null . That because typeof null returns "object" :

 // The constructor function function Book(title, author, numPages) { if (typeof title === "object" && title !== null) { numPages = title.numPages; author = title.author; title = title.title; // pretty confusing } this.title = title; this.author = author; this.numPages = numPages; } Book.prototype.read = function() { this.currentPage = this.numPages; console.log('You read ' + this.numPages + ' pages'); } var book = new Book("Harry Potter", "JK Rowling", 574); book.read(); var book = new Book({ title: "Robot Dreams", author: "Isaac Asimov", numPages: 325 }); book.read(); 

By adding this check, when the object receives arguments like this:

title // {title: "Robot Dreams", author: "Isaac Asimov", numPages: 325}
author // undefined
numPages // undefined

It's smart enough to extract the values and assign them to their corresponding variables, so they are turned into:

title // "Robot Dreams"
author // "Isaac Asimov"
numPages // 325

After that, the values are stored correctly in your object and read() prints the right thing.

your examlpe like following

book1 and book2 is different.

book1 pass three parameter(string,string,integer).

book2 pass one parameter(object).

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

Book.prototype.read = function () {
this.currentPage = this.numPages;
console.log('You read ' + this.numPages + ' pages');
}


var contentOne = "Harry Potter"
var contentTwo = "J.K. Rowling"
var contentThree = 574
var book1 = new Book(contentOne,contentTwo, contentThree);

var bookContent = {
title: "Robot Dreams",
author: "Isaac Asimov",
numPages: 325
};
var book2 = new Book(bookContent,null,null);

book1.read();
book2.read();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM