Object literal reusable function - javascript

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;
}

Related

When does aPerson.firstname and aPerson.lastname actually change in this code snippet?

I'm going through some JavaScript koans to learn the language syntax and I'm confused by this set of tests:
it("should know that variables inside a constructor and constructor args are private", function () {
function Person(firstname, lastname)
{
var fullName = firstname + " " + lastname;
this.getFirstName = function () { return firstname; };
this.getLastName = function () { return lastname; };
this.getFullName = function () { return fullName; };
}
var aPerson = new Person ("John", "Smith");
aPerson.firstname = "Penny";
aPerson.lastname = "Andrews";
aPerson.fullName = "Penny Andrews";
expect(aPerson.getFirstName()).toBe("John");
expect(aPerson.getLastName()).toBe("Smith");
expect(aPerson.getFullName()).toBe("John Smith");
aPerson.getFullName = function () {
return aPerson.lastname + ", " + aPerson.firstname;
};
expect(aPerson.getFullName()).toBe("Andrews, Penny");
});
I get that the variables inside a constructor are private, and that's why "John Smith" still prints when calling getFullName() even after attempting to set aPerson.firstname, lastname, and fullName. But then a function is created called getFullName(), and then after that calling the function "Andrews, Penny" prints.
I would have expected "Smith, John" to print since this new function was created after the "failed" attempt to set firstname to "Penny" and lastname to "Andrews". Why does "Andrews, Penny" print?
Thanks
The key here is the new operator; var aPerson = new Person ("John", "Smith") creates a new Person, passing in John and Smith as the names used by the Person function, and assigning the new instance of the function to the variable aPerson.
Note the var fullName = firstname + " " + lastname inside of the Person function. This takes whatever is passed through as the function parameter at the time the Person function is called. At this point, this.getFullName will be equal to John Smith.
When you run aPerson.firstname = "Penny"
this only updates the new instance of the Person; it doesn't modify the original Person function. When you call aPerson.getFirstName(), the getFirstName() method returns what was originally set as firstname for Person (John), not what has been set for the new instance aPerson (Penny).
As such, the first time you call aPerson.getFullName(), the name is John Smith.
Your new function aPerson.getFullName = function () { } returns aPerson.lastname + ", " + aPerson.firstname. Unlike the previous function, this takes the last and first name from the new instance of Person (Penny Andrews).
As such, the second time you call aPerson.getFullName(), the name is Penny Andrews.
Hope this helps! :)
First, you need to understand this:
function Person(firstname, lastname)
{
var fullName = firstname + " " + lastname;
...
}
var aPerson = new Person ("John", "Smith");
Here, the only thing you created was an object with only methods on it, not even attributes, like firstname, lastname. (Parameters and variables declared with var aren't attached to your object)
So your object aPerson is like this:
{
getFirstName: function(), // => John
getLastName: function(), // => Smith
getFullName: function() // => John Smith
}
Then:
aPerson.firstname = "Penny";
aPerson.lastname = "Andrews";
aPerson.fullName = "Penny Andrews";
You assigned on your aPerson object new attributes. So, it becomes like this:
{
firstname: "Penny",
lastname: "Andrews",
fullName: "Penny Andrews",
getFirstName: function(), // => John
getLastName: function(), // => Smith
getFullName: function() // => John Smith
}
Next, you overriding getFullName with this:
aPerson.getFullName = function () {
return aPerson.lastname + ", " + aPerson.firstname;
};
As your can see, you use these new attributes.
Now, you should be able to understand your result.
If you do the replacement, you get this:
aPerson.getFullName = function () {
return aPerson.lastname + ", " + aPerson.firstname;
// Andrews , Penny
};
And voilà ! It's why you get your result ;)

Sharing 'this' between files

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;
}
};

Define getter / setter in object function

I'm learning JavaScript, and was wondering if it was possible to define getters and setters in object functions.
The main difference is the way of calling it, if defined as getFullName = function(), I should call the method as myObj.getFullName(), however, as for arrays, a getter allows for it to be called as a simple property myObj.fullName (without parenthesis).
As I saw in MDN reference (http://mzl.la/1CIUuIw), it is easily done in Object Literals:
var obj = {
get var(){
return "something";
}
}
However, I can't do it on object functions like so:
function obj(name, lname){
this.name = name;
this.lastName = lname;
get fullName(){
return this.name + " " + this.lastName;
}
}
Getting a "Unexpected identifier" error...
As get XX(){} is used for var obj = {}; But here you use a constructor to create new object. So you should use MDN - Object.defineProperty().
And if you want the fullName apply on all object create from obj, apply it on its prototype.
function obj(name, lname){
this.name = name;
this.lastName = lname;
}
Object.defineProperty(obj.prototype, 'fullName', {
get : function() {
return this.name + " " + this.lastName;
}
});
var aObj = new obj("first", 'lastN');
console.log(aObj.fullName);
UPDATE:
If you want a more straight way, and not scared to try new things, then ES2015's class notation can do it more easily:
// ES2015 - class
class obj {
constructor(name, lname) {
this.name = name;
this.lname = lname;
}
// Define getter method for fullName
get fullName() {
return this.name + " " + this.lastName;
}
}
var aObj = new obj('Billy', 'Hallow');
console.log(aObj.fullName);
Currently most browsers don't support that, if you want to use this in your site, you need to use js compilers like Babel to transpile it from ES2015 to ES5.
Babel also provide a playground for those who has interest in ES2015, you can copy above codes to the playground to see how it works.
Javascript uses prototype inheritance and its functions start with function keyword. By convention, object's first character is capitalised.
function Obj(name, lname){
this.name = name;
this.lastName = lname;
}
Obj.prototype.get = function() {
return this.name + " " + this.lastName;
}
var person = new Obj('luke', 'lim');
console.log(person.get()); // 'luke lim'
Just make a variable and assign the function to it.
function obj(name, lname){
this.name = name;
this.lastName = lname;
this.fullName = function(){
return this.name + " " + this.lastName;
};
}
Try to read something about Javascript closure if you want to know more about it.
Furthermore, this link, Javascript methods, is explaining EXACTLY what you need, which is adding a method to an object. And a getter is traditionally just a method.
function obj(name, lname){
this.name = name;
this.lastName = lname;
}
obj.prototype.getfullName = function(){
return this.name + " " + this.lastName;
}
use this as
a = new obj("My","Name");
a.getfullName() //"My Name"

Why aren't the properties of my object logged to the console?

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);

in javascript whay use " var that = this "

hi i am new with javascript
What is the benefit of using this line
var that = this
An example
function Person( firstname, lastname, age ) {
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
getfullname = function() {
return firstname + “ “ + lastname; }
var that = this;
this.sayHi = function() {
document.write( “Hi my name is “ + getfullname() + “ and I am “ + that.age + “years old.”);
} }
thanks
this is context sensitive. Using that makes sure that when sayHi is called it can use the this value from when getfullname was called.
Usually it's to fix the meaning of this to what it refers to at the time that is assigned. it wouldn't make any difference in your example, but it can do when a function is called from a different context.
In Javascript this is a rather fluid concept. It is not the same as this in OO languages like c#.

Categories

Resources