I'm trying to make a basic one-page address book without a database, and I wanted to assign ids to the contacts to make them easier to find. However, when I've tried to add contacts, nothing gets assigned. Any help would be appreciated!
function AddressBook() {
this.contacts = [];
this.currentId = 0;
}
AddressBook.prototype.addContact = function(contact) {
contact.id = this.assignID;
this.contacts.push(contact);
}
AddressBook.prototype.assignID = function() {
this.currentID += 1;
return this.currentId;
}
AddressBook.prototype.findContact = function(id) {
for (let i = 0; i < this.contacts.length; i++) {
if(this.contacts[i].id == id) { //uses loose equality to leave room for input error
return this.contacts[i];
}
};
return false;
}
function Contact(firstName, lastName, phoneNumber) {
this.firstName = firstName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
}
Contact.prototype.fullName = function() {
return this.firstName + " " + this.lastName;
}
In addition to calling assignId note that you have uppercase D in this.currentID += 1 but lowercase d in the line below that and in the constructor so you should make the uppercase D lowercase
You have defined assignID as a method, but you've used as a property.
To your code works, you need change addContact method like the below code:
AddressBook.prototype.addContact = function(contact) {
contact.id = this.assignID(); //<===== calling like a method not a property
this.contacts.push(contact);
}
However, note that currentId is a property of one instance. So, you code will ever put 1 to all IDs.
To fix it, you can change currentId to be one class property like this:
AddressBook.currentId
And in all places reference this property with the class name before:
AddressBook.prototype.assignID = function() {
AddressBook.currentId += 1; //<====== note that in your code you use ID as upper case, different that you have defined it
return AddressBook.currentId;
}
Using currentId as a class property, all instances of the class will share this property and each call for assignID() will update the shared property and make that the next instance of the class gets one new ID.
The final code should looks like:
function AddressBook() {
this.contacts = [];
}
AddressBook.currentId = 0;
AddressBook.prototype.addContact = function(contact) {
contact.id = this.assignID();
this.contacts.push(contact);
}
AddressBook.prototype.assignID = function() {
return ++AddressBook.currentId; //here, first currentId is incremented and after it is returned
}
AddressBook.prototype.findContact = function(id) {
for (let i = 0; i < this.contacts.length; i++) {
if(this.contacts[i].id == id) { //uses loose equality to leave room for input error
return this.contacts[i];
}
};
return false;
}
function Contact(firstName, lastName, phoneNumber) {
this.firstName = firstName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
}
Contact.prototype.fullName = function() {
return this.firstName + " " + this.lastName;
}
Related
I am trying to build a function that creates a person by receiving at first a full name and using methods to set the first, last and full name. Afterwards it would have methods that should be able to change each part of the name.
My current code looks like this:
var Person = function(firstAndLast) {
var name = firstAndLast;
this.getFirstName = function() {
return name.substr(0,name.indexOf(' '));
};
this.getLastName = function() {
return name.substr(name.indexOf(' ')+1);
};
this.getFullName = function() {
return name;
};
this.setFirstName = function() {
return name;
};
this.setLastName = function() {
return name;
};
this.setFullName = function() {
return name;
};
};
var bob = new Person('Bob Ross');
bob.setFullName();
Now I am completely stuck when it gets time to pass a new name, so that if I do something like:
bob.setFullName('George Carlin');
and then pass:
bob.getFullName();
I should get the answer 'George Carlin'.
yet this isn't happening.
Thanks as always.
So the problem was that I wasn't really understanding how the values where being passed, and that instead of working on a full name I should be working on the parts.
var Person = function(firstAndLast) {
var firstName = firstAndLast.split(' ')[0];
var lastName = firstAndLast.split(' ')[1];
this.setFirstName = function(firstNameNew) {
firstName = firstNameNew;
};
this.setLastName = function(lastNameNew) {
lastName = lastNameNew;
};
this.setFullName = function (fullNameNew) {
firstName = fullNameNew.split(' ')[0];
lastName = fullNameNew.split(' ')[1];
};
this.getFullName = function() {
return firstName + ' ' + lastName;
};
this.getFirstName = function() {
return firstName;
};
this.getLastName = function() {
return lastName;
};
};
var bob = new Person('Bob Ross');
I'm having trouble converting JSON to Javascript objects when the JSON data has nested objects. The top level 'Person' object gets recreated fine, but the 'Residence' object property does not
function Person(first, last) {
this.FirstName = first;
this.LastName = last;
this.Residence = {};
}
Person.Revive = function (data) {
return new Person(data.FirstName, data.LastName);
}
Object.defineProperty(Person.prototype, "FullName", {
get: function() { return this.FirstName + " " + this.LastName; }
});
Person.prototype.toJSON = function () {
this.__class__ = "Person";
return this;
});
function Residence(lat, long) {
this.Latitude = lat;
this.Longitude = long;
}
Residence.prototype.toJSON = function () {
this.__class__ = "Residence";
return this;
}
Residence.Revive = function (data) {
return new Residence(data.Latitude, data.Longitude);
}
Object.defineProperty(Residence.prototype, "Location", {
get: function () { return this.Latitude + ", " + this.Longitude; }
});
var p = new Person("Foo", "Bar");
p.Residence = new Residence(44, 33);
console.log("Full name = " + p.FullName);
console.log("Location = " + p.Residence.Location);
var serialization = JSON.stringify(p);
console.log(serialization);
var rawObj = JSON.parse(serialization, function (key, value) {
if (value instanceof Object && value.__class__ == 'Person') {
return Person.Revive(value);
}
if (value instanceof Object && value.__class__ == 'Residence') {
return Residence.Revive(value);
}
return value;
});
console.log("Full name = " + rawObj.FullName);
console.log("Location = " + rawObj.Residence.Location);
The JSON.parse function does get a key/value pair for the 'Residence' object, and a new Residence object is created and returned. However, the resulting 'rawObj.Residence' is just an empty object. Can anyone point out what I'm doing wrong?
The console output is as follows:
Full name = Foo Bar
Location = 44, 33
{"FirstName":"Foo","LastName":"Bar","Age":22,"Residence":{"Latitude":44,"Longitude":33,"__class__":"Residence"},"__class__":"Person"}
Full name = Foo Bar
Location = undefined
Fiddle: http://jsfiddle.net/CadGuy/yyq4dqtx/
var p = new Person("Foo", "Bar");
p.Residence = new Residence(44, 33);
Well, if you are constructing your Person objects like that, you'll have to revive them like this as well:
Person.Revive = function (data) {
var p = new Person(data.FirstName, data.LastName);
p.Residence = data.Residence;
return p;
};
Of course, it might be a good idea to make the residence an (optional?) parameter to Person in the first place.
CONTEXT
I have one Base class called Entity and User and Group are both derived from this object; If I instantiate a user with the ID of 12 for example, the next time I try to do that it returns the same object. I store these in a prototype items variable. To keep these item variables separate I have to declare the User And Group functions separately although they contain the same code.
CODE
Application.prototype.Entity = function() {
};
Application.prototype.Entity.prototype.print = function() {
var container = $("<div class='user-tag'></div>");
container.append("<a class='friend_list ellipsis_overflow' style='background-image:url(\"" + this.entity.pic.icon + "\");'"
+ "href ='user?id=" + this.entity.id + "'>" + this.entity.name + "</a>");
return container;
};
//HOW TO GET RID OF THIS "REPETITION"
Application.prototype.User = function(entity) {
this.entity = entity;
this.entity.pic = this.entity.pic || Application.prototype.default.pic;
if (this.items[this.entity.id]) {
return this.items[this.entity.id];
} else {
this.items[this.entity.id] = this;
}
};
Application.prototype.Group = function(entity) {
this.entity = entity;
this.entity.pic = this.entity.pic || Application.prototype.default.pic;
if (this.items[this.entity.id]) {
return this.items[this.entity.id];
} else {
this.items[this.entity.id] = this;
}
};
// END REPEAT
Application.prototype.Group.prototype = new Application.prototype.Entity();
Application.prototype.User.prototype = new Application.prototype.Entity();
//Application.prototype.User.prototype.constructor = Application.prototype.Entity;
//Application.prototype.Group.prototype.constructor = Application.prototype.Entity; - these don't seem to work
//THESE items VARIABLES HAVE TO REMAIN SEPARATE
Application.prototype.Group.prototype.items = {};
Application.prototype.User.prototype.items = {};
QUESTION
I specifically would like to rid my code of the repetition mentioned above, but if you see any other unnecessary code, please comment. Thanks!
Something like this?
function userAndGroupConstructor(entity) {
this.entity = entity;
this.entity.pic = this.entity.pic || Application.prototype.default.pic;
if (this.items[this.entity.id]) {
return this.items[this.entity.id];
} else {
this.items[this.entity.id] = this;
}
}
Application.prototype.User = function() {
return userAndGroupConstructor.apply(this, arguments)
}
Application.prototype.Group = function() {
return userAndGroupConstructor.apply(this, arguments)
}
You get distinct constructors with distinct prototypes, but avoid duplication.
You can do this:
Application.prototype.Group = Application.prototype.User;
Since Application.prototype.User contains the function reference, you can just assign it to Application.prototype.Group.
function Dude() {
this.firstName = '';
this.lastName = '';
};
var d = new Dude();
d.firstName = 'Ok mr';
d.firstName = 100;
How do I prevent / guard the assignment of 100 to firstName so that it will always be a string? Assigning a number, array another object should convert to a string.
Try to make the variables private and write getters and setters for them. In the setter you can check for the correct type. See this answer for checking the type.
function Dude() {
var firstName = '';
var lastName = '';
this.setFirstName = function(name) {
if(typeof name == 'string' || name instanceof String) {
firstName = name;
}
}
this.getFirstName = function() {
return firstName;
}
};
var d = new Dude();
d.setFirstName('Ok mr');
d.setFirstName(100);
console.log(d.getFirstName()); // returns "Ok mr"
But pay attention: When you use the value of an input element or pass the name in quotes it will be a string. No matter wether it represents a number or not.
Reference: http://javascript.crockford.com/private.html
function Dude() {
this.firstName = '';
this.lastName = '';
Dude.prototype.setFirstName(name) = function() {
if(typeof name != "string") this.firstName = name.toString();
else this.firstName = name;
};
Dude.prototype.setLastName(name) = function() {
if(typeof name != "string") this.lastName = name.toString();
else this.lastName = name;
};
}
var d = new Dude();
d.setFirstName("name");
d.setLastName(100);
These functions check whether the names are strings, if they aren't, the name will be converted to a string. This means it will then be assigned as string to either the firstName or lastName.
This is an interview questions, Asked to write a Man class to let the following code can run properly:
var me =new Man();
//method one:
me.attr("fullname", "tom");
//method two:
me.fullname = "jim";
console.info("my name is:" + me.attr("fullname"));
/*------[result is]------
my name is:tom
------------------*/
my answer is:
var Man=function(){
};
Man.prototype.attr=function(attr,val){
if(val){
this[attr]=val;
}
else{
return this[attr];
}
}
The results of my code to run is:
/*------[result is]------
my name is:jim
------------------*/
who can help me? thanks
You could make a second dictionary:
function Man() {
this.dictionary = {};
}
Man.prototype.attr = function(attr, val) {
if(arguments.length > 1) {
this.dictionary[attr] = val;
} else {
return this.dictionary[attr];
}
};
You could use a closed variable:
function Man() {
var dictionary = {};
this.attr = function(attr, val) {
if(arguments.length > 1) {
dictionary[attr] = val;
} else {
return dictionary[attr];
}
};
}
You could use a closed fullname variable, and ignore everything except 'fullname':
function Man() {
var fullname;
this.attr = function(attr, val) {
if(attr === 'fullname') {
if(arguments.length > 1) {
fullname = val;
} else {
return fullname;
}
}
};
}
You could also return "tom" every single time, or pretend all the attributes are "fullname", or both. You could ROT13 property names before assigning them. You could add underscores. You could create a property instead that throws away values beginning with "j". The possibilities are limitless, actually.
Use a property to save attributes.
var Man=function(){
this.attributes = {};
};
Man.prototype.attr=function(attr,val){
if(val){
this.attributes[attr] = val;
}
else{
return this.attributes[attr];
}
}