I am currently learning about 'creating objects using the factory pattern' in Javascript. I have written this bit of code. I want to call the vehicle.getInfo(); function by calling the getVehicle(); function.
function getVehicle (theYear, theMake, theModel) {
var vehicle = new Object();
vehicle.year = theYear
vehicle.make = theMake
vehicle.model = theModel
vehicle.getInfo = function () {
return 'Vehicle: ' + this.year + ' ' + this.make + ' ' + this.model;
console.log('Vehicle: ' + this.year + ' ' + this.make + ' ' + this.model);
};
console.log(vehicle); // at this level, is there a way to call getInfo function without the actual "console.log(vehicle.getInfo());"
};
getVehicle("2014", "Tata", "Zest");
In the getVehicle() function, I'd like to console.log what the vehicle.getInfo() method returns. But I'd like to do this, without using console.log(vehicle.getInfo());.
Is that possible?
Can you please help me?
Related
In an OOP way, I am defining a Person "class" as follows:
var Person = {
name: '',
age: 32,
gender: 'male',
interests: ['music', 'skiing'],
bio: function() {
alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
},
greeting: function() {
alert('Hi! I\'m ' + this.name + '.');
}
};
Now, I am instantiating the above class.
var person1= Object.create(Person);
person1.name = 'personname';
person1.greeting();
How can I mimic a constructor so that when Object.create(Person) creates a new object, the constructor code is automatically computed?
You would wrap up the code in a function, and call it there. Object.create will establish a relationship with the prototype, but won't call any additional code automatically.
function person(name) {
var person1 = Object.create(Person);
person1.name = name;
return person1;
}
person('personname').greeting();
You should also avoid uppercasing the first letter of variables unless they are functions which should be called using new. This is a naming convention used only for constructor functions.
You could make an real class for use with new.
var Person = function () {
var Person = function () {
this.name = ['', ''];
this.age = 32;
this.gender = 'male';
this.interests = ['music', 'skiing'];
};
Person.prototype.bio = function() {
return this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.';
};
Person.prototype.greeting = function() {
return 'Hi! I\'m ' + this.name + '.';
};
return Person;
}();
var p1 = new Person;
p1.name = ['Tom', 'Sawyer'];
console.log(p1.bio());
console.log(p1);
var Person = function(name) {
this.name = name || '';
this.age = 32;
this.gender = 'male';
this.interests = ['music', 'skiing'];
this.bio = function() {
alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
};
this.greeting = function() {
alert('Hi! I\'m ' + this.name + '.');
};
};
var person1= new Person('personname');
person1.greeting();
I'm trying implement a simple call to forEach to run the logMe function on all items in the automobiles array. The output is unexpected. All variables read "undefined."
function Automobile(year, make, model, type) {
this.year = year;
this.make = make;
this.model = model;
this.type = type;
}
Automobile.prototype.logMe = function(boolVal) {
if (boolVal == true) {
console.log(this.year + ' ' + this.make + ' ' + this.model + ' ' + this.type);
} else {
console.log(this.year + ' ' + this.make + ' ' + this.model);
}
}
var automobiles = [
new Automobile(2010, "Toyota", "Tacoma", "Pickup"),
new Automobile(2005, "Lotus", "Elise", "Roadster"),
new Automobile(2008, "Subaru", "Outback", "Wagon")
];
automobiles.forEach(Automobile.prototype.logMe.bind(true)); //the problem
automobiles[0].logMe(true); //test logMe function
The output:
undefined undefined undefined
undefined undefined undefined
undefined undefined undefined
1995 Honda Accord Sedan
The first argument to Function.bind() is the value for this within the function. In your sample, this is bound to true, which is why you get undefined for the property values.
forEach will pass the element as the first argument to the callback. Thus, instead of passing a bound method, you can define a lambda that calls logMe on its 1st argument.
automobiles.forEach(function(car, i, cars) {car.logMe(true);});
Function.prototype.bind creates a new function and you must pass in the value of this - the construct which calls the function.
If you want to create an array of functions that can be called later like this, you should be using bind like below, otherwise just call the function inside the forEach.
var caller = [];
automobiles.forEach(function(element) {
caller.push(Automobile.prototype.logMe.bind(element));
}, caller);
caller[0](true);
Demo below:
function Automobile(year, make, model, type) {
this.year = year;
this.make = make;
this.model = model;
this.type = type;
}
Automobile.prototype.logMe = function(boolVal) {
if (boolVal == true) {
console.log(this.year + ' ' + this.make + ' ' + this.model + ' ' + this.type);
} else {
console.log(this.year + ' ' + this.make + ' ' + this.model);
}
}
var automobiles = [
new Automobile(2010, "Toyota", "Tacoma", "Pickup"),
new Automobile(2005, "Lotus", "Elise", "Roadster"),
new Automobile(2008, "Subaru", "Outback", "Wagon")
];
var caller = [];
automobiles.forEach(function(element) {
caller.push(Automobile.prototype.logMe.bind(element));
}, caller);
caller[0](true); //test logMe function
In the following snippet of my code, I post to a link, from which it allows me to change the title, but will not call the function info() with the argument supplied, nor will it log in the console, please help with this code, thanks. Also, please note all the variables are defined and this code works 100% besides this, and it won't work with $.get rather than $.post either.
function info(text, state) {
$("<h4>"+text+"</h4>").appendTo("body");
if (state != "run") {
$("h2").text(text).fadeIn("slow").delay(30000).fadeOut();
}
$.post(buy, function(r) {
diff = event.timeStamp - last;
$(document).prop('title', 'Purchased '+info['itemName']+'!');
info('Purchased '+info['itemName']+' for '+info['expectedPrice']+' in '+diff+' milliseconds!');
console.log('Purchased '+info['itemName']+' for '+info['expectedPrice']+' in '+diff+' milliseconds!');
})
--EDIT--
If I put console.log above info, the code works excluding the info() function, so the problem is possibly there
Try (this pattern)
// var last = $.now();
function info(text, state) {
$("<h4>" + text + "</h4>").appendTo("body");
if (state != "run") {
$("h2").text(text).fadeIn("slow").delay(30000).fadeOut();
}
// missing closing `{` at OP
};
$.post(buy, function (_info) {
// `_info` : return json object
// `info` : function declaration name
// diff = $.now() - last;
$(document).prop('title', 'Purchased ' + _info['itemName'] + '!');
info('Purchased '
+ _info['itemName'] + ' for '
+ _info['expectedPrice'] + ' in '
+ diff + ' milliseconds!'
, "run");
console.log('Purchased '
+ _info['itemName'] + ' for '
+ _info['expectedPrice'] + ' in '
+ diff + ' milliseconds!');
});
jsfiddle http://jsfiddle.net/guest271314/7vxb7336/
I need to be able to add many functions to a Javascript class and I thought that you could do that with the className.prototype = function(){} but maybe I was not correct on this.
Car.prototype.toAnotherString = function () {
return this.model + " has done " + this.miles + " miles";
};
Question: Ist he prototype declared correctly in this class and can the class Car be declared some how with out the function name>
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
Car.prototype.toAnotherString = function () {
return this.model + " has done " + this.miles + " miles";
};
}
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
console.log( civic.toString() );
console.log( mondeo.toString() );
console.log( civic.toAnotherString() );
console.log( mondeo.toAnotherString() );
New Code:
So is this how the prototype should be added.
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
}
Car.prototype.toAnotherString = function () {
return this.model + " has done " + this.miles + " miles";
};
No, it's not: the line defining a method on Car.prototype should be placed separately:
function Car (model, year, miles) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
}
Car.prototype.toAnotherString = function () {
return this.model + " has done " + this.miles + " miles";
};
See, the major advantage of prototypes is ability to create a method function just once. But in your code, this line will be executed each time the Car constructor is called, creating a new instance of the function again and again. And that defeats the purpose of prototype.
But how this function will know about the object it's called for, you may ask? That's done with so-called function context trickery. See, when you call civic.toAnotherString(), inside toAnotherString this object will be referring to the same object as civic. And when you call mondeo.toAnotherString(), this will refer to the same object as mondeo.
But wait, there's more! You can call this method off one object, yet pass another one as its context (i.e., this):
civic.toAnotherString.call(mondeo); // or .apply(mondeo)
And, lo and behold, even though the method seems to belong to civic object, it'll actually act as though it was attached to mondeo one.
This - ability to switch this inside a method - is one of the most powerful JS features. I'd suggest studying this (really, no pun intended) tutorial on MDN up-to-bottom, as well as corresponding articles on Function.call, Function.apply and Function.bind.
Prototyping should be done outside of the initializing function, like this:
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
}
Car.prototype.toAnotherString = function () {
return this.model + " has done " + this.miles + " miles";
};
I am following an online tutorial and I am at a prototype section. My alert comes back with
function() { return this.brand + ' ' + this.model; }
Anyone know the reason?
function Car(model, brand) {
this.model = model;
this.brand = brand;
}
Car.prototype.fullName = function() {
return this.brand + ' ' + this.model;
}
var s = new Car("G5", "Pontiac");
var full = s.fullName;
alert(full);
s.fullName is the function itself. If you wanted to call this function you would have to write s.fullName().