Create objects inside a module javascript - javascript

I am learning design patterns in javascript but I have a problem creating a module. I am creating a Person object inside of module and I have combined it with a constructor pattern, just beacuse I am learning it too, but nothing happens.
Can anybody help me, I don't undertand my mistake here
var myModule = (function () {
function Person(id, name) {
this.id = id;
this.name = name;
}
Person.prototype.toString = function () {
return "\nID: " + this.Id + "\nName: " + this.name;
};
return {
newPerson: function (id, name) {
return new Person(id,name);
console.log(Person.toString());
}
};
})();
var x = myModule;
x.newPerson(1, "John");

You should use
var myModule = (function () {
function Person(id, name) {
this.id = id;
this.name = name;
}
return {
newPerson: function (id, name) {
return new Person(id,name);
}
};
})();
var x = myModule;
console.log(x.newPerson(1, "John"));
Forget the toString(), most consoles can fetch the object, and display it in a much better way.
In your case you want to log the toString() of the Person constructor, which would result a string something like this:
"function Person(id, name) {
this.id = id;
this.name = name;
}"
but it does not run, because you put it after the return statement in the newPerson() function, and the return statement stops execution and returns with the results.

Related

Calling prototype function with .call()

I'm watching a course on JS design patters and in one of the examples there is this code:
var Task = function (name) {
this.name = name;
this.completed = false;
}
Task.prototype.save = function () {
console.log('saving Task: ' + this.name);
};
var UrgentTask = function (name, priority) {
Task.call(this, name);
this.priority = priority;
};
UrgentTask.prototype = Object.create(Task.prototype);
UrgentTask.prototype.save = function () {
console.log('do special stuff before saving');
//why use Task.prototype.save and not Task.save directly.
Task.prototype.save.call(this);
};
var ut = new UrgentTask('This is urgent', 1);
ut.save();
My question is why inside the UrgentTask.prototype.save function do i have to use Task.prototype.save and not Task.save directly with the .call() method?
and why if i use Task.save it returns can't read property 'call' of undefined??

Pass an object's function to another of its functions

This is what I have:
var Person = function(fname, lname) {
this.fname = fname;
this.lname = lname;
};
Person.prototype = {
getFullName: function() {
return this.fname + " " + this.lname;
},
doStuff: function(stuff) {
return stuff();
}
};
var john = new Person("John", "Doe");
The doStuff function works with other functions, but doing the following returns undefined undefined:
console.log(john.doStuff(john.getFullName));
What's wrong with what what I have and how can I change it to make it work?
Thanks.
It's because this doesn't refer to the object.
You could use the .bind() method in order to set the value of this:
john.doStuff(john.getFullName.bind(john));
However, that's not very flexible, therefore you could just bind it within the doStuff method:
doStuff: function(stuff) {
return stuff.apply(this);
}
If you know foo.doStuff's arg always wants to be called on foo, you can write this in doStuff
// ...
doStuff: function (stuff) {
return stuff.apply(this, Array.prototype.slice.call(arguments, 1));
}

Get the public properties of a class without creating an instance of it?

Let's imagine that we have a JavaScript class:
var Person = (function () {
function Person(name, surname) {
this.name = name;
this.surname = surname;
}
Person.prototype.saySomething = function (something) {
return this.name + " " + this.surname + " says: " + something;
};
return Person;
})();
I want to iterate its methods and properties. I have no problem with the methods.
var proto = Person.prototype,
methods = Object.keys(proto);
// iterate class methods ["saySomething"]
for (var i = 0; i < methods.length; i++) {
// do something...
}
My problem comes when I want to iterate its properties:
var proto = Person.prototype,
targetInstance = new Person(), // this is my problem!
properties = Object.getOwnPropertyNames(targetInstance),
// iterate class properties ["name", "surname"]
for (var i = 0; i < properties.length; i++) {
// do something...
}
The only way that I have found is to create an instance and use Object.getOwnPropertyNames. I want to use this code as part of a framework so I will not have control over the classes defined by other developers. I want to avoid the need of creating an instance because if the constructor had some sort of validation like:
function Person(name, surname) {
if(typeof name === "undefined" || typeof surname === "undefined"){
throw new Error()
}
this.name = name;
this.surname = surname;
}
I wouldn't be able to use the code above. Do you know if it is possible to get the public properties of a class without creating an instance of it?
The properties don't exist until an object constructs them.
If your class looked like:
var Person = (function () {
Person.prototype.name = null;
Person.prototype.surname = null;
function Person(name, surname) {
this.name = name;
this.surname = surname;
}
Person.prototype.saySomething = function (something) {
return this.name + " " + this.surname + " says: " + something;
};
return Person;
})();
you would see name and surname too, but of course you can't count on the objects looking like that.
Do you know if it is possible to get the public properties of a class without creating an instance of it?
If you are talking about runtime them no, not without ugly hacks like toString (which gives you a string representation of the function body).
However you can get these at compile time using the TypeScript language service and then do code generation to assist the runtime (https://github.com/Microsoft/TypeScript/wiki/Using-the-Language-Service-API).
Neither of these are trivial.

Error for JS OOP beginner training

I'm new in programming and I'm learning JavaScript OOP, trying to make a game with tanks. I have some code but it doesn't work properly and I need some help to understand how it works. Please check it and tell me how to solve the problem because I want to add a few more kinds of tanks but before that I need to fix the code.
var Tank = (function () {
function Tank(name) {
this._name = name;
}
Tank.prototype.getWeight = function () { return this._weight; }
Tank.prototype.getName = function () { return this._name; }
return Tank;
}());
var SmallTank = (function () {
this.prototype = Object.create(Tank.prototype);
function SmallTank(name) {
Tank.apply(this._name);
}
SmallTank.prototype._weight = 2;
return SmallTank;
}());
var myTank = new SmallTank("Aleks Tank");
console.log(myTank.getWeight());
It seems that you're just trying to do some kind of inheritance; typically you do this by assigning a parent instance to the prototype of the child.
I think you will want something like this:
var SmallTank = (function () {
function SmallTank(name) {
Tank.call(this, name);
this._weight = 2;
}
SmallTank.prototype = new Tank();
return SmallTank;
}());
Alternatively you can assign Object.create(Tank.prototype).
Here is another way of doing what it looks like you are attempting to do, following the Mozilla guide:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
var Tank = function (name) {
this.name = name;
};
Tank.prototype.getName = function () { return this.name; };
var SmallTank = function (name) {
Tank.call(this, name);
this.weight = 2;
};
SmallTank.prototype = Object.create(Tank.prototype);
SmallTank.prototype.constructor = SmallTank;
SmallTank.prototype.getWeight = function () { return this.weight; };
var myTank = new SmallTank("Aleks Tank");
console.log(myTank.getName());
console.log(myTank.getWeight());

What am I doing wrong when combining objects with the module pattern

This Possible duplicate did not help me, I failed on an interview because of a similar question.
The idea is to create a person Object that is a father of teacher and grandfather of Manager using module pattern and inheritance.
Something like that Manager->Teacher->Person
My code looks like that(My Plunk):
(function(undef)
{
/**Waiting till document is ready before applying next functions*/
$(document).ready(function(){
var person = new APP.Person('Aria Stark','223232');
document.write(person.getDetails());
})();
var APP = {};
APP.Person =(function() {
function Person(name, ID) {
this.name = name;
this.ID = ID;
}
Person.prototype.getDetails = function() {
return " name: " + this.name + " ID: " + this.ID;
};
return Person;
});
APP.Teacher =(function () {
function Teacher(name, ID, salary, hatColor) {
APP.Person.call(this, name, ID);
this.salary = salary;
this.hatColor = hatColor;
}
Teacher.prototype = new APP.Person();
Teacher.prototype.getDetails = function() {
return APP.Person.call(this) + " Salary: " + this.salary + " Hat: " + this.hatColor;
};
return Teacher;
});
APP.Manager =(function () {
function Manager(name, ID, salary, hatColor, car) {
APP.Teacher.call(this, name, ID, salary, hatColor);
this.car = car;
}
Manager.prototype = new APP.Teacher();
Manager.prototype.getDetails = function() {
return APP.Teacher.call(this) + " Car: " + this.car;
};
return Manager;
});
})();
I get an error on the first line:
var person = new APP.Person('Aria Stark','22323');
The error is: Uncaught TypeError: object is not a function
Can someone help me with with that? I'm also open to hear other improvements to this code.
This is how you create (and call) a self-executing function or IIFE:
(function () {})();
Simply writing (function () {}) does not call the function, it actually has no real effect in this case. With your way APP.Person will be a function, that returns another function (the constructor for Person) when called - it will not operate well with new.
Also, for the documentready, you don't want to execute the result of the .ready call, just pass the function as a parameter, it will be called when the event triggers:
$(document).ready(function(){
}); //removed () from here
Plunk with these changes
All your objects are declared like this:
APP.X=(function() {
function Y() {}
Y.prototype.method= function() {};
return Y;
});
That is not wrong in itself, though it is a bit odd. What you want to have is this:
APP.X=(function() {
function X() {}
X.prototype.method= function() {};
return X;
})(); // actually call the anonymous function you used to encapsulate variables
Then again, why do you bother with an IIFE? You might just as well do this:
APP.X = function () {}
X.prototype.method= function() {};
Encapsulating them brings absolutely nothing, there is nothing private you are hiding from the outer scope.
Also, my post might be better suited for CodeReview than StackOverflow, but your inheritance model has significant issues. Your Teacher.prototype is an instance of Person created with no parameters. Only under highly restrictive circumstances will that be safe.
A better model would be this one:
Teacher = function(){
Person.call(this /*, person parameters*/);
}
Teacher.prototype = Object.create(Person.prototype);
There are many good answers on SO dealing with this specific issue, here is one from me.
There is no need of jQuery to create these things. Well, I have not very good exposer on this, but I tried to show the things you want to know:
// Creating Person Class
var Person = function(name, id){
this.name = name;
this.id = id;
};
Person.prototype.getInfo = function(){
return "name: " + this.name + ", id: " + this.id;
};
// Instance of Person
var x = new Person("Ashish", 1);
x.getInfo();
// Creating Teacher Class
var Teacher = function(name, id, salary, hatColor){
Person.call(this, name, id);
this.salary = salary;
this.hatColor = hatColor;
};
// Inheriting Persons methods
Teacher.prototype = new Person();
// Adding new method to it
Teacher.prototype.getFullDetails = function(){
return this.getInfo() + ", salary: " + this.salary + ", Hatcolor: " + this.hatColor;
}
// Instance of Teacher Class
var teacher = new Teacher("John", 2, 15000, "red");
teacher.getInfo(); //output: "name: John, id: 2"
teacher.getFullDetails(); // output : "name: John, id: 2, salary: 15000, Hatcolor: red"
console.log(teacher.salary); // output : 15000
So, above you can see:
- A Person class is created with 2 properties and one method.
- and then we created a Teacher class and inherited the method from Person class in it.
- and then added another method called getFullDetails() in it which accesses the method coming from Person class.
And this is what you are doing in the DOM.ready:
alert(x.getInfo()); // in my example:
In your example:
var APP = {};
APP.Person = function Person(name, ID) {
this.name = name;
this.ID = ID;
}
APP.Person.prototype.getDetails = function () {
return " name: " + this.name + " ID: " + this.ID;
};
var person = new APP.Person('Aria Stark', '223232');
alert(person.getDetails());

Categories

Resources