JavaScript Object and methods but getName is not a function - javascript

I'm learning JavaScript and write a simple demo, but failed. Could you help me out why getName is not a function? Thanks.
var newPerson = function(name) {
this.name = name;
getName: return function() {
return this.name;
}
};
var personOne = newPerson("Diego");
var personTwo = newPerson("Gangelo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Gangelo

It looks like you're trying to return an object with some exposed methods. In that case, this is what I would have done.
var newPerson = function (name) {
this.name = name;
var self = this;
return {
getName: function () {
return self.name
}
}
}
var personOne = new newPerson("Diego");
var personTwo = new newPerson("Gangelo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Gangelo
Edit: thanks to Pootie
Alternatively you could just do this.
var newPerson = function (name) {
this.name = name;
this.getName = function () {
return this.name;
}
}
var personOne = new newPerson("Diego");
var personTwo = new newPerson("Gangelo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Gangelo
Next time, use console.log() instead of document.write() because it's easier to debug.

I would have done it like this
var Person = function(name) {
this.name = name;
this.getName = function() {
return this.name;
}
};
var personOne = new Person("Diego");
var personTwo = new Person("Gangelo");
document.write(personOne.getName()); // prints Diego
document.write(personTwo.getName()); // prints Gangelo

Since you said you liked my example I thought I'd post my personal preference. No need to return an object like the other examples do since the function itself is an object. Everything in JS is an object as a matter of fact.
See this fork of the other answer: https://jsfiddle.net/6xpgjh94/
var newPerson = function (name) {
var self = this;
self.name = name;
self.getName = function(){
return self.name
};
}
var personOne = new newPerson("Diego");
var personTwo = new newPerson("Gangelo");
console.log(personOne.getName()); // prints Diego
console.log(personTwo.getName()); // prints Gangelo

Well if we're introducing Object-Oriented Programming, I might as well show you how JavaScript does it best:
// The ECMAScript 5 way
function Person(name) {
this.name = name;
}
Person.prototype.getName = function getName() {
return this.name;
};
var personOne = new Person("Diego");
var personTwo = new Person("Gangelo");
console.log(personOne.getName());
console.log(personTwo.getName());
This next one uses ES6 Classes and is part of the new JavaScript standard.
Note this syntax is still in the "experimental stage" as far as browser implementation goes, and may not work on your browser.
// The ECMAScript 6 way
class Person {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
let personOne = new Person("Diego");
let personTwo = new Person("Gangelo");
console.log(personOne.getName());
console.log(personTwo.getName());

Related

Javascript context in inner class object

Prior to using ES6 we could instantiate a "class" like so...
var Animal = function(){}
and then...
var dog = new Animal()
the context within the "class" will be the class (instance) itself
var Animal = function( name ){
this.name = name;
this.getName = function(){
// the context here (this) is the class (Animal)
return this.name; // works well
}
}
The question is, if I wouldn't want to pollute the root scope and use sub-objects, for various uses, then the context would become the object in which the function is being kept
var Animal = function( name ){
this.utilities = {
this.getName : function(){
// the context here is the 'utilities' object so...
return this.name // wouldn't work
}
}
}
of course we could always use something in the form of
dog.utilities.getName.call(dog)
but this would be kind of long and uncomfortable...
is there a way to create the 'utilities' object and apply the context to all of its functions to point back to the root scope? without having to use call and apply every time? (an answer without using ES6 would be great...)
One way to ensure that this is what you want it to be in the various utilities functions is to use arrow functions for them, since arrow functions close over the this where they're defined:
class Animal {
constructor(name) {
this.name = name;
this.utilities = {
getName: () => { // This is an arrow function
return this.name; //
} //
};
}
}
const dog = new Animal("dog");
console.log(dog.utilities.getName()); // "dog"
This is basically the ES2015+ version of the old var t = this; solution:
function Animal(name) {
var t = this;
this.name = name;
this.utilities = {
getName() {
return t.name;
}
};
}
var dog = new Animal("dog");
console.log(dog.utilities.getName()); // "dog"
In both cases, this means that you're creating new function objects for each individual instance of Animal (the code will be shared between those objects, but the objects are distinct). That's fine unless there are going to be a lot of Animal instances.
Alternately, you could have a helper that you pass the instance to:
const Animal = (function() {
class Utilities {
constructor(animal) {
this.a = animal;
}
getName() {
return this.a.name;
}
}
class Animal {
constructor(name) {
this.name = name;
this.utilities = new Utilities(this);
}
}
return Animal;
})();
const dog = new Animal("dog");
console.log(dog.utilities.getName()); // "dog"
or
var Animal = (function() {
function Utilities(animal) {
this.a = animal;
}
Utilities.prototype.getName = function getName() {
return this.a.name;
};
return function Animal(name) {
this.name = name;
this.utilities = new Utilities(this);
}
})();
var dog = new Animal("dog");
console.log(dog.utilities.getName()); // "dog"
...which lets utilities reuse its function objects via Utilities.prototype.
You could probably use the following:
var utilities = function (context) {
return {
getName: function () {
console.log(context.name)
}
}
}
var Animal = function( name ){
this.name = name
this.utilities = utilities.call(null, this)
}
var dog = new Animal('dog')
dog.utilities.getName()
But, if you are okay doing this: dog.getName() instead of dog.utilities.getName() then you might have a cleaner solution (IMO) as follows:
var Animal = function( name ){
this.name = name
}
var utilities = {
getName: function () {
console.log(this.name)
}
};
Object.assign(Animal.prototype, utilities)
var dog = new Animal('dog')
dog.getName()
Let me know if that works. Thanks.
NEW ANSWER:
var UTILITIES = {
getName: function () {
console.log(this.self.name)
}
}
var Animal = function (name) {
this.name = name
this.utilities = Object.create(UTILITIES, {
self: {
value: this
}
})
}
var dog = new Animal('dog')
dog.utilities.getName()
Variation includes the use of a 'self' attribute which points to the instance of interest. Now, this could look more intuitive.
You can use getter methods. I find them very useful for cases where I need formatted value. This way, the utilities/ logic is only known to this class and is not exposed outside.
function Person(fname, lname) {
var _fname = fname;
var _lname = lname;
Object.defineProperty(this, 'fullName', {
get: function(){
return _fname + ' ' + _lname
}
});
Object.defineProperty(this, 'firstName', {
get: function(){
return _fname
},
set: function(value) {
_fname = value;
}
});
Object.defineProperty(this, 'lastName', {
get: function(){
return _lname
},
set: function(value) {
_lname = value;
}
});
}
var person = new Person('hello', 'world');
console.log(person.fullName);
person.firstName = 'Hello';
console.log(person.fullName);
person.lastName = 'World'
console.log(person.fullName);

Create an instance of object internally

I have tried to create an instance of object internally like the following:
var oo = function(){
return new func();
}
var func = function(){
this.name;
this.age;
};
func.prototype = {
setData: function(name, age){
this.name = name;
this.age = age;
},
getData: function (){
return this.name + " " + this.age;
}
}
When usage, I got an error oo.setData is not a function.
oo.setData("jack", 15);
console.log(oo.getData());
What's wrong in my code?
This happens because oo is not a "func", oo returns a new func. You could set the data using
oo().setData('jack',15);
But then you have no way of accessing it.
You could also use
var newfunc = oo();
newfunc.setData('jack',15);
newfunc.getData();
oo is a function to create a object.
var oo = function(){ //the oo variable is used to create func() objects
return new func();
}
var func = function(){ //function
this.name;
this.age;
};
func.prototype = { //define properties to func
setData: function(name, age){
this.name = name;
this.age = age;
},
getData: function (){
return this.name + " " + this.age;
}
}
//create instance
var myObject = oo();
//or
var myObject = new func();
//Use
myObject.setData("jack", 12);
//Get a property
console.log(myObject.getData())

Accessing this variable from method instance

How do you access the this object from another object instance?
var containerObj = {
Person: function(name){
this.name = name;
}
}
containerObj.Person.prototype.Bag = function(color){
this.color = color;
}
containerObj.Person.prototype.Bag.getOwnerName(){
return name; //I would like to access the name property of this instance of Person
}
var me = new Person("Asif");
var myBag = new me.Bag("black");
myBag.getOwnerName()// Want the method to return Asif
Don't put the constructor on the prototype of another class. Use a factory pattern:
function Person(name) {
this.name = name;
}
Person.prototype.makeBag = function(color) {
return new Bag(color, this);
};
function Bag(color, owner) {
this.color = color;
this.owner = owner;
}
Bag.prototype.getOwnerName = function() {
return this.owner.name;
};
var me = new Person("Asif");
var myBag = me.makeBag("black");
myBag.getOwnerName() // "Asif"
Related patterns to deal with this problem: Prototype for private sub-methods, Javascript - Is it a bad idea to use function constructors within closures?

JavaScript Closures Manipulation

I'm doing some Node.js and I want to use the closure representation to create my objects. I think I'm missing something, because something simple like this isn't working:
var Room = function(foo) {
this.name = foo;
this.users= [];
return {
getName : function() {
return this.name;
}
}
}
var room = new Room("foo");
console.log(room.getName());
I also have tried without the parameter.. and still not working.
var Room = function() {
this.name = "foo";
this.users= [];
return {
getName : function() {
return this.name;
}
}
}
var room = new Room();
console.log(room.getName());
However, something like this works:
var Room = function(foo) {
this.name = foo;
this.users= [];
}
var room = new Room("foo");
console.log(room.name);
I can't understand why this isn't working.
--Edited
Thanks to Amadan I have found the right way to do it:
var Room = function() {
var name = "foo";
var users= [];
return {
getName : function() {
return name;
}
}
}
var room = new Room();
console.log(room.getName());
This way "name" and "users" are encapsulated.
return in a constructor will overwrite this. So the right way to do this is:
var Room = function(foo) {
this.name = foo;
this.users= [];
this.getName = function() {
return this.name;
}
}
or
var Room = function(foo) {
return {
name: "foo",
users: [],
getName : function() {
return this.name;
}
}
}
The first one does everything on the original this; the second one replaces this with everything you need.

Why does one need to call the function in an Object (constructor) in order to use a method that uses .this (JavaScript)

var setAge = function (newAge) {
this.age = newAge;
};
// now we make bob
var bob = new Object();
bob.age = 30;
bob.setAge = setAge;
bob.setAge(50);
console.log(bob.age);
This works, but when I try to do this
var setAge = function (newAge) {
this.age = newAge;
};
var bob = new Object();
bob.age = 30;
bob.setAge(50);
console.log(bob.age);
it returns "bob.setAge() is not a function" in the compiler?
The second example doesn't work because you haven't defined setAge, as you have here bob.setAge = setAge;. You created a new Object(), not a new custom-defined object. You're using sorta hybrid code... this is how you could do "classes"
var MyObject = function (age) {
this.age = age;
var that = this;
this.setAge = function (newAge) {
that.age = newAge;
}
};
var foo = new MyObject(10);
alert(foo.age);
foo.setAge(20);
alert(foo.age);
You have created an object 'Bob', but that object does not have the method 'setAge' until you assign it.
You may want to look into doing something like this in your design:
function Person(){
this.age = 30;
this.setAge = function(age){
this.age = age;
return this;
}
}
var bob = new Person;
bob.setAge(20);
console.log(bob.age);

Categories

Resources