So I'm getting this error; Object # has no method 'carName'
But I clearly do.
Pastebin
I've also tried referencing the car's "model" property with
player.car.model
but that doesn't work, I get a type error. Any ideas? Do you need more info?
function person(name, car) {
this.name = name;
this.car = car;
function carName() {
return car.model;
}
}
var player = new person("Name", mustang);
var bot = new person("Bot", mustang);
var bot2 = new person("Bot 2", mustang);
function makeCar(company, model, maxMPH, tireSize, zeroToSixty) {
this.company = company;
this.model = model;
this.maxMPH = maxMPH;
this.tireSize = tireSize;
this.zeroToSixty = zeroToSixty;
}
var mustang = new makeCar("Ford", "Mustang GT", 105, 22, 8);
var nissan = new makeCar("Nissan", "Nissan 360z", 100, 19, 6);
var toyota = new makeCar("Toyota", "Toyota brandname", 95, 21, 7);
It does not have the method. It has a function that is local to the variable scope of the constructor.
To give each object the function, assign it as a property...
function person(name, car) {
this.name = name;
this.car = car;
this.carName = function() {
return this.car.model;
};
}
Or better, place it on the prototype of the constructor...
function person(name, car) {
this.name = name;
this.car = car;
}
person.prototype.carName = function() {
return this.car.model;
};
Also, mustang isn't initialized when you're passing it to the person constructor.
Related
Can Cat obtain data from fluffy and garfield?
class Cat {
constructor(name, weight) {
this.name = name;
this.weight = weight;
}
}
fluffy = new Cat('fluffy', 15);
garfield = new Cat('garfield', 25);
Say I wanted to define a method that lists the names of all Cats.
Cat.listNames()
//['fluffy', 'garfield']
I searched through Cat.prototype, and couldn't find any useful methods or references to the child or even the child's .__proto__.
maybe this works
class Cat {
Static CatList = [];
constructor(name, weight) {
this.name = name;
this.weight = weight;
Cat.CatList.push(this);
}
static listNames() {
console.log(Cat.CatList);
}
}
Here's a solution to get Cats names:
class Cat {
constructor(name, weight) {
this.name = name;
this.weight = weight;
Cat.CatNames.push(this.name);
}
}
Cat.CatNames = [];
Cat.listNames = function() {
return Cat.CatNames;
}
var fluffy = new Cat('fluffy', 15);
var garfield = new Cat('garfield', 25);
console.log(Cat.listNames()); // ["fluffy", "garfield"]
var Car = function(name, year) {
this.name = name;
this.year = year;
this.print = function() {
console.log(name+" "+year);
}
}
var tesla = new Car("tesla", 2018);
tesla.print();
tesla = JSON.parse(JSON.stringify(tesla));
console.log(tesla);
tesla.print(); // Uncaught TypeError: tesla.print is not a function
How can i add the print function to the object after the parse? Is there an elegant solution for this?
You could create a prototype for printing and call the method with an object for binding.
function Car(name, year) {
this.name = name;
this.year = year;
}
Car.prototype.print = function() { // add prototype
console.log(this.name + " " + this.year); // take this as reference to the instance
};
var tesla = new Car("tesla", 2018);
tesla.print();
tesla = JSON.parse(JSON.stringify(tesla));
console.log(tesla);
Car.prototype.print.call(tesla); // borrow method from class, take own object
A clean approach is to add a function deserialize as prototype which takes an object and assign all properties to the instance.
function Car(name, year) {
this.name = name;
this.year = year;
}
Car.prototype.print = function() {
console.log(this.name + " " + this.year);
};
Car.prototype.deserialize = function(object) {
Object.entries(object).forEach(([k, v]) => this[k] = v);
};
var tesla = new Car("tesla", 2018);
tesla.print();
tesla = JSON.parse(JSON.stringify(tesla));
console.log(tesla);
var tesla2 = new Car;
tesla2.deserialize(tesla);
tesla2.print();
The JSON data format does not support functions (which would be very unhelpful if you generated some JSON from a JavaScript object and then tried to parse it with C#!).
A sensible approach to this would be to change the Car constructor function so that it can accept an object as the first argument.
var Car = function(name, year) {
if (typeof name === "object") {
// use properties of `name` to set everything in this object
} else {
// Treat name and year as a string and number just like you are now
}
...
Then you can:
tesla = new Car( JSON.parse(JSON.stringify(tesla)) );
… which will also generate an object with the correct prototype.
I want to set the weapon with "setWeapon" by creating the "weapon" property too. Example call: "archer.setWeapon (bow);"
function Weapon(name,damage) {
this.name = name;
this.damage = damage;
}
Weapon.prototype.toString = function () {
return this.name + this.damage + " damage"; // method to show weapon
};
var bow = new Weapon('Golden bow, ', 20); // create weapon
function Character() {
this.health = 100;
this.basicDamage = 10;
this.toString = function () {
return this.name + this.type; // add and show weapon bow
};
Character.createArcher = function () { // create hero
var hero = new Character;
hero.name = "Legolas";
return hero;
};
Character.setWeapon = function () {
var weapon = new Character();
weapon.type = Weapon;
return weapon;
};
var archer = new Character.createArcher();
archer.setWeapon(bow); // set the selected weapon
console.log(archer.toString());
One way is to extend prototype of Character with setWeapon and setters just sets the value - they don't return values. You can write getWeapon() for that. This way you pass actual weapon and assign to the archer. Hope that helps. (Weapon is an object so you can access archer.weapon.type)
var bow = new Weapon('Golden bow, ', 20); // create weapon
Character.prototype.setWeapon = function (weapon) {
var me = this;
me.weapon = weapon; // set the weapon
};
var archer = new Character.createArcher();
archer.setWeapon(bow); // set the selected weapon
console.log(archer.toString()); // add to string also property weapon
To keep it short and let the example speak for itself.
I create a object and print it out (it's OK), I create more objects (of the same type) and print out the first object again, now it shows the data of the last object created.
Then I create a a different object from a different class and print the original first object out again and it returns the data from the newly created object.
JSFiddle
var uiElements = [];
uiElements.borders = [];
uiElements.buttons = [];
uiElements.text = [];
var mainStats = [];
mainStats.money = 0;
mainStats.pots = [];
mainStats.herbs = [];
var xOffSet = 10;
var yOffSet = 10;
$(document).ready(function() {
createUI();
});
function createUI()
{
mainStats.herbs.types = [];
mainStats.herbs.types[0] = "Blue";
mainStats.herbs.types[1] = "Blood vine";
mainStats.herbs.types[2] = "Heg flower";
mainStats.herbs[mainStats.herbs.types[0]] = createHerb(mainStats.herbs.types[0], "herb", 60, 0.2, 10, "Basic blue herb", 1, true);
//CORRECT
alert(mainStats.herbs[mainStats.herbs.types[0]].name +" "+ mainStats.herbs[mainStats.herbs.types[0]].tier)
mainStats.herbs[mainStats.herbs.types[1]] = createHerb(mainStats.herbs.types[1], "herb", 200, 0.4, 40, "Blood red tree vine", 1, true);
mainStats.herbs[mainStats.herbs.types[2]] = createHerb(mainStats.herbs.types[2], "herb", 390.4, 0.2, 202.5, "Crescent shape flower", 1, true);
mainStats.herbs.types[3] = "Black rose";
mainStats.herbs[mainStats.herbs.types[3]] = createHerb(mainStats.herbs.types[3], "herb", 60, 0.2, 10, "Very dark rose", 2, true);
mainStats.pots.types = [];
mainStats.pots.types[0] = "Earthen";
//mainStats.pots[mainStats.pots.types[0]] = [];
//mainStats.pots[mainStats.pots.types[0]].color = "#654321";
//WRONG
alert(mainStats.herbs[mainStats.herbs.types[0]].name +" "+ mainStats.herbs[mainStats.herbs.types[0]].tier)
createPot(mainStats.pots.types[0], 1, 1, null);
//VERY WRONG
alert(mainStats.herbs[mainStats.herbs.types[0]].name +" "+ mainStats.herbs[mainStats.herbs.types[0]].tier)
}
function createPot(name, tier, growthAccelerator, herb)
{
this.name = name;
this.tier = tier;
this.growthAccelerator = growthAccelerator;
this.herb = herb;
this.timeLeft = 0;
return this;
}
function createHerb(name, type, timeToBloom, seedsReturned, salesPrice, description, tier, enabled)
{
this.name = name;
this.type = type;
this.timeToBloom = timeToBloom;
this.seedsReturned = seedsReturned;
this.salesPrice = salesPrice;
this.description = description;
this.tier = tier;
this.enabled = enabled;
return this;
}
function rx(num)
{
return num+xOffSet;
}
function ry(num)
{
return num+xOffSet;
}
You don't create objects but just call the functions so their this refers to the global (window) object so that the properties there are overwritten each time and you print out the modified stuff
Create objects with the new keyword like this (by convention, you would then rename createPot just Pot)
var newObj = new createPot(mainStats.pots.types[0], 1, 1, null);
alert(newObj.name);
...
I was messing with some js on codecadamy and got a bit sidetracked trying to make something work.
In essence I was creating a few objects that are loaded into a controller object and set as properties of it with two functions that print the properties and compare a string to the name property of each object in the controller.
I noticed I can do it if I make the objects in the prototype style and specify a normal function to handle setting the properties like so:
var friends = {};
friends.setUp = function() {
this.friends = [];
for(var i in arguments) {
arguments[i].setUp();
this.friends.push(arguments[i]);
}
};
friends.list = function() {
for(var i in this.friends) {
console.log(this.friends[i]);
}
};
friends.search = function(name) {
for(var i in this.friends) {
if(this.friends[i].firstName === name) {
return this.friends[i];
}
}
};
var bill = {};
bill.setUp = function() {
this.firstName = "Bill";
this.lastName = "Gates";
this.number = "(206) 555-5555";
this.address = ['One Microsoft Way','Redmond','WA','98052'];
};
var steve = {};
steve.setUp = function() {
this.firstName = "Steve";
this.lastName = "Jobs";
this.number = "(206) 555-5555";
this.address = ['1 Infinite Loop','Cupertino','CA','95014'];
};
var mike = {};
mike.setUp = function() {
this.firstname = "Mike";
this.lastname = "Ryd";
this.number = "(800) 555-5555";
this.address = ['redacted'];
};
friends.setUp(bill, steve, mike);
friends.list();
var result = friends.search("Steve");
console.log(result);
However if I do it with constructors It does not work, example:
function bill() {
this.firstName = "Bill";
this.lastName = "Gates";
this.number = "(206) 555-5555";
this.address = ['One Microsoft Way','Redmond','WA','98052'];
};
function steve() {
this.firstName = "Steve";
this.lastName = "Jobs";
this.number = "(206) 555-5555";
this.address = ['1 Infinite Loop','Cupertino','CA','95014'];
};
function mike() {
this.firstname = "Mike";
this.lastname = "Ryd";
this.number = "(800) 555-5555";
this.address = ['redacted'];
};
function friends() {
this.friends = [];
for(var i in arguments) {
this.friends.push(arguments[i]);
}
};
friends.list = function() {
for(var i in this.friends) {
console.log(this.friends[i]);
}
};
friends.search = function(name) {
for(var i in this.friends) {
if(this.friends[i].firstName === name) {
return this.friends[i];
}
}
};
var bill = new bill();
var steve = new steve();
var mike = new mike();
var friends = new friends(bill, steve, mike);
friends.list();
var result = friends.search("Steve");
console.log(result);
I was wondering if this is a limitation of using constructors or am I messing up the syntax somewhere? Thank you!
This doesn't appear to have anything to do with constructors with an unknown number of arguments, but rather you are not assigning methods on your objects appropriately. They need to be put on the prototype so that they will be inherited by all objects that are created by this particular constructor. So in your code, these:
friends.list = function() {...}
friends.search = function() {...}
needs to be changed to:
friends.prototype.list = function() {...}
friends.prototype.search = function() {...}
Like this:
friends.prototype.list = function() {
for(var i = 0; i < this.friends.length; i++) {
console.log(this.friends[i]);
}
};
friends.prototype.search = function(name) {
for(var i = 0; i < this.friends.length; i++) {
if(this.friends[i].firstName === name) {
return this.friends[i];
}
}
};
Then, this code should work fine:
var bill = new bill();
var steve = new steve();
var mike = new mike();
var friends = new friends(bill, steve, mike);
friends.list();
var result = friends.search("Steve");
console.log(result);
And, then the code works as you would expect here: http://jsfiddle.net/jfriend00/ba4me8ua/
FYI, you'll noticed that I changed the way you iterate through the arguments object items to be more array-like and avoid any chance of getting any non-numeric properties in the iteration.