Below, I have constructed an object called person and I want to log its first and last name(combined with some strings) to the console, but it does not work. I would be glad if somebody could help me out. Thank you in advance.
function person(last, first, birth, marriage) {
this.lastName = last;
this.firstName = first;
this.birthDate = birth;
this.married = marriage;
}
var lovely = new person("Doughnut", "Glazed", "7-8-1990", true);
var callPerson = function(){
console.log("Hey " + person.firstName + " " + person.lastName);
}
callPerson(lovely);
You have a scoping issue:
var callPerson = function(person /* argument needs to be here */){
console.log("Hey " + person.firstName + " " + person.lastName);
}
So person is the function, not the object lovely.
Minor code style remark: classes are typically capitalized, exactly to avoid this kind of confustion. Use function Person () {/**/} instead.
It is not being logged because, in callPerson, the variable person refers to the function (constructor) person, since this name is not overridden in the scope of the function. This means you are not referring to some specific instance, but the class. Passing one instance as parameter doesn't change this since the function does not expect it; in effect, the passed parameter is not used in any means.
Think of this as attempting to log a class property, not one instance's.
Changing callPerson in the following way should solve your issue. Note that now the fields accessed are from the parameter p.
var callPerson = function(p){
console.log("Hey " + p.firstName + " " + p.lastName);
}
Where is the argument lovely storing it should have an parameter to store and use
function person(last, first, birth, marriage) {
this.lastName = last;
this.firstName = first;
this.birthDate = birth;
this.married = marriage;
}
var lovely = new person("Doughnut", "Glazed", "7-8-1990", true);
var callPerson = function(obj){
console.log("Hey " + obj.firstName + " " + obj.lastName);
}
callPerson(lovely);
Related
I'm working on creating an object that will have many methods, and trying to avoid my files being incredibly long. The problem is some of methods refer to other information in the object. I'd like to be able to do something like this:
index.js
var User = function(first, last){
this.firstname = first;
this.lastname = last;
};
User.prototype.name = require('./methods/name.js')
methods/name.js
module.exports = {
full: function(){
return this.firstname + " " + this.lastname;
},
formal: function(){
return "Mr. " + this.lastname;
}
};
It makes sense why this doesn't work in this situation, but is there a different solution to be able to reference the other file? The only I can think of is using fs and eval() instead of require, but that seems like a hack to me, or the obvious of have a long file. Is there something better?
I'm planning on having about 35 objects on the prototype with each having an average of 4 methods on it. Suggestions? Thanks.
The problem doesn't have anything to do with it being in separate files. You would get the same problem all in one file if you defined User like this:
var User = function(first, last){
this.firstname = first;
this.lastname = last;
};
User.prototype.name = {
full: function(){
return this.firstname + " " + this.lastname;
},
formal: function(){
return "Mr. " + this.lastname;
}
};
Since when you call someuser.name.full() the this will be bound to someuser.name not someuser.
If you don't need to namespace those functions and only did so because you were unsure how else to extend the prototype from another file, you can use Object.assign:
Object.assign( User.prototype, require('./methods/name.js') );
Then you'll be able to call someuser.full() or someuser.formal() and of course this will have the correct value.
You can bind those functions like this:
User.prototype.name = require('./methods/name').bind(this)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
Also—lose the .js in your require path.
This should keep your code modular
// index.js
var userMethods = require('.methods/name.js');
var User = function(first, last){
this.firstname = first;
this.lastname = last;
};
User.prototype.name = userMethods.full;
User.prototype.formalName = userMethods.formal;
var Abbey = new User('Abbey', 'Jack');
console.log(Abbey.firstname); // Abbey
console.log(Abbey.lastname); // Jack
console.log(Abbey.name()); // Abbey Jack
console.log(Abbey.formalName()); // Mr. Jack
// methods/name.js
module.exports = {
full: function(){
return this.firstname + " " + this.lastname;
},
formal: function(){
return "Mr. " + this.lastname;
}
};
Please find the below code for more information.
var person = {
firstname:"john",
lastname:"doe",
greet: function(){
return "hello " + this.firstname + " " + this.lastname;
}
}
console.log(person.greet());
How can I make above object literal function greet() dymanic? Like I can pass params values for example person.greet('jessie','jay') will return hello jessie jay
Is it better to use constructor method (instances) in order to make function dynamic and reusable? I found that object literal is just to organize code.
I'll suggest you to use Constructor function. This pattern is called as Factory pattern. The function here acts as class and for each person a new object can be created.
function Person(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
Person.prototype.greet = function () {
return 'Hello ' + this.firstname + ' ' + this.lastname;
};
var jon = new Person('Jon', 'Skeet');
var tushar = new Person('Tushar', 'Jadhav');
console.log(jon.greet()); // Hello Jon Skeet
console.log(tushar.greet()); // Hello Tushar Jadhav
First, you should think about what person and greet actually is or should be. If person is an object and greet a method that operates on the data of that object, the way you've written person is fine.
If you consider person to be some kind of namespace or module you will use to organize your code, you will write greet as a pure function that doesn't depend on and modify any variables out of its scope. In this case you won't have person instance data as firstname and lastname on person.
var person = {
greet: function(person){
return "hello " + person.firstName+ " " + person.lastName;
}
};
var jenny = { firstName : 'Jennifer', lastName : 'IdowntKnow' };
person.greet(jenny);
A combination of both will be very confusing in this case
var person = {
firstname:"john",
lastname:"doe",
greet: function(firstName, lastName){
/* .. */
}
};
person.greet('Jennifer', 'IdowntKnow');
// hmm, what happens here? Person switched to Jennifer now? What about john? weird code...
The question if you should use a constructor function is more about performance or if you need features like prototypal inheritance.
greet: function(fname, lname){
return "hello " +fname + " " + lname;
}
if you also want to update firstname and lastname
greet: function(fname, lname){
this.firstname =fname;
this.latname =lname;
return "hello " +fname + " " + lname;
}
i am a newbie to js.
i am trying to use constructor function to create an object.
here is my code
function player(name,age,rank)
{
this.name=name;
this.age=age;
this.rank=rank;
this.sayEverything=function()
{
return "The name of the player is " + this.name + "the age is " + this.age + "the rank is " + this.rank;
}
Now i am adding a new property like this
player.matchReady=true;
now i create an object like this
var kaka=new player("kaka",22,3,false);
And when i write this
document.write('kaka is match ready-->' + kaka.matchReady);
it gives me this output
kaka is match ready-->undefined
Why is it giving me undefined??
haven't i added a new property correctly??Please tell me.
Thanks.
Instead of player.matchReady=true;
Do, player.prototype.matchReady = true;
This way all players will have match ready default on true;
also you might want to put your function into the prototype.
player.prototype.sayEverything=function()
{
return "The name of the player is " + this.name + "the age is " + this.age + "the rank is " + this.rank;
}
You can regard prototype as the scaffolding on which you outline all properties and functions an object should have when it's instantiated. All these default values will be the same for all objects.
When you add functions within functions all these functions get duplicated in memory when you instantiate a new object.
When possible and when there is no need for scoping, try to add generic functions like your sayEverything()(please rename that to toString() to keep in line with convention) to the prototype.
That way all the player objects can use the same function. Which is more memory efficient.
You cannot add a property to a class. You can always add the property as its prototype.
like this:
function player(name, age, rank) {
this.name = name;
this.age = age;
this.rank = rank;
this.sayEverything = function () {
return "The name of the player is " + this.name + "the age is " + this.age + "the rank is " + this.rank;
}
}
player.prototype.matchReady = true;
var kaka = new player("kaka", 22, 3, false);
alert('kaka is match ready-->' + kaka.matchReady);
working example: jsfiddle
Blog on prototype
If you add it to the prototype, all player will have the field.
player.prototype.matchReady = true;
If you only want a specific player to have the field, add it to that player variable:
var kaka = new player("kaka",22,3,false);
kaka.matchReady = true;// kaka has to come first
In the below example you can see what is private ,public,static and privileged variable or method .When ever you write property on Method itself like static variable,that variable wont be available for the instances.
Also whenever you are writing constructor function you should follow the Naming convention to help you differentiate from other function
/ Constructor
function Player(name) {
// Private
var dob= "17/04/1986";
// Privileged
this.getDOB = function () {
return dob;
};
// Public
this.name = name;
}
// Public
Player.prototype.getName = function () {
return this.name;
};
// Static property
Player.town = "South Park";
Lastly ... the first line ... var phonebookEntry = {} is this an Object literal or constructor syntax ... I don't think it's an literal, but then if it's constructor --- isn't this the right syntax for object constructor ===> var myObj = new Object(); <=== I'm confused ... or else there's a third syntax/way for creating objects...
var phonebookEntry = {};
phonebookEntry.name = 'Oxnard Montalvo';
phonebookEntry.number = '(555) 555-5555';
phonebookEntry.phone = function() {
funtion works, it has no any parameter...
console.log('Calling ' + this.name + ' at ' + this.number + '...');
};
phonebookEntry.phone();
This line:
phonebookEntry.phone = function() {
console.log('Calling ' + this.name + ' at ' + this.number + '...');
};
creates a Function object and assigns it to the phone attribute of phonebookEntry. The function is not called at that point. Later (the next line, actually):
phonebookEntry.phone();
calls the function, passing no arguments and binding this to phonebookEntry within the body of the function. Thus, during that call, this.name is an alias for phonebookEntry.name and similarly for the number property.
name and number are properties of phonebookEntry. They don't need to be passed as arguments.
This creates the function within an object:
phonebookEntry.phone = function() {
console.log('Calling ' + this.name + ' at ' + this.number + '...');
};
This calls the function:
phonebookEntry.phone();
It is able to utilize this to describe the parent object(phonebookEntry) and is then able to grab other information such as name, number, or any other information stored within that object.
Is this a good/safe cross-browser way to implement method overriding in JavaScript? :
function Person(firstName, lastName)
{
this.firstName = firstName;
this.lastName = lastName;
};
Person.prototype.sayHi = function()
{
return "Hi, my name is " + this.firstName;
};
function Employee(firstName, lastName, position)
{
Person.call(this, firstName, lastName);
this.position = position;
};
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.sayHi = function()
{
return this.constructor.prototype.sayHi() + " I'm a " + this.position;
}
I could also write:
Employee.prototype.sayHi = function()
{
return Person.prototype.sayHi() + " I'm a " + this.position;
}
but with this solution I'm refering to direct method, or
Employee.prototype.sayHi = function()
{
return this.__proto__.sayHi() + " I'm a " + this.position;
}
but this one is awful and not crossbrowser.
EDIT: I assumed Object.create is crossbrowser as I can use a shim
You should not rely on the constructor property of the prototype to call parent functions because normally, that property should point to the children constructor.
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
There are a few other ways to access parent functions safely, like referring to the parent prototype directly like you are trying to do in your second example, however there's something wrong with the way you are doing it.
If you call sayHi without using call or apply, this will point to Person.prototype during the function call and that's not what you want.
You should call sayHi by setting the context object to the current employee instance, like this:
Employee.prototype.sayHi = function() {
return Person.prototype.sayHi.call(this) + " I'm a " + this.position;
};
Another way of doing this would be to store a reference to the parent prototype in the children prototype.
Employee.prototype.super = Person.prototoype;
Employee.prototype.sayHi = function() {
return this.super.sayHi.call(this) + " I'm a " + this.position;
};
Another interesting approach I've seen is to wrap every function of the children prototype in a function that dynamically sets a reference to the parent function on the object instance, so that you can only use this.parent() to call the function. However I would not recommend this solution since it will reduce performances and increase memory usage.
I have created a jsFiddle to demonstrate that concept.
No.
Employee.prototype = Object.create(Person.prototype);
Object.create is not supported by older browsers, but you can shim it.
Employee.prototype.sayHi = function() {
return this.constructor.prototype.sayHi() + " I'm a " + this.position;
}
I wouldn't use that. You expect this.constructor to be the Person from which you inherited from, but that might not be the case. Actually it would be good practise to set the Employee.prototype.constructor = Employee, which would cause recursion with a stack overflow to your method.
Instead, you should explicitly refer to the function you want to use:
return Person.prototype.sayHi.call(this) + " I'm a " + this.position;
If you want it dynamically, you'd use
return Object.getPrototypeOf(Employee.prototype).sayHi.call(this) + " I'm a " + this.position;
but notice that Object.getPrototypeOf is not supported in older browsers. So if you need a cross-browser and DRY way, use the module pattern:
(function(proto, super) {
proto.sayHi = function() {
return super.sayHi.call(this) + " I'm a " + this.position;
};
…
})(Employee.prototype, Person.prototype);
or the revealing prototype pattern:
Employee.prototype = (function(super) {
var proto = Object.create(super);
proto.sayHi = function() {
return super.sayHi.call(this) + " I'm a " + this.position;
};
…
return proto;
})(Person.prototype);