constructor within a constructor in javascript? - javascript

I want a constructor within a constructor- I've searched stackoverflow and googled extensively......
I have a constructor RentalProperty:
function RentalProperty(numberOfUnits, address, dateAcquired, acCost, isFinanced,
loanAmount){
this.numberOfUnits = numberOfUnits;
this.address = address;
this.dateAcquired = new Date(dateAcquired);
this.acCost = acCost;
this.isFinanced = isFinanced;
this.loanAmount = 0;
this.newValue = 0;
this.equity = function(){
if (this.newValue === 0){
return (this.acCost - this.loanAmount);
} else {
return (this.newValue - this.loanAmount);
}
};
}
Each instance of RentalProperty will have a series of unit objects that I would like to be unit1, unit2, unit3, etc. However some instances of RentalProperty will have only one unit while others may have six, twelve, or more. The way I'm doing it here doesn't seem right as there is a lot of repetition of code and I will need to make a large number of unit objects that may not be used for a particular instance of RentalProperty:
RentalProperty.prototype.unit1 = {
unitNumber : "1",
monthlyRent: 0,
leaseStart: new Date(0),
leaseEnd: new Date(0),
numBeds: 0,
isSec8: false,
tenantPortion: 0,
sec8Portion: 0
};
RentalProperty.prototype.unit2 = {
unitNumber : "2",
monthlyRent: 0,
leaseStart: new Date(0),
leaseEnd: new Date(0),
numBeds: 0,
isSec8: false,
tenantPortion: 0,
sec8Portion: 0
};
RentalProperty.prototype.unit3 = {
unitNumber : "3",
monthlyRent: 0,
leaseStart: new Date(0),
leaseEnd: new Date(0),
numBeds: 0,
isSec8: false,
tenantPortion: 0,
sec8Portion: 0
};
I tried various combinations of syntax (I've been pulling my hair out for hours) to put a unit constructor within the RentalProperty constructor with code such as:
....
this.unit["for(i=0, i < this.numberOfUnits, i++){return i;}"] = {
unitNumber : "i",
monthlyRent: 0,
leaseStart: new Date(0),
leaseEnd: new Date(0),
numBeds: 0,
isSec8: false,
tenantPortion: 0,
sec8Portion: 0
};
....hoping that this would create the correct number of units using the value of the this.numOfUnits property of RentalProperty but it gives me "missing operand".
I have also tried:
....//'new Object' added
this.unit[for(i=0, i < this.numberOfUnits, i++){return i;}] = new Object{
unitNumber : "i",
monthlyRent: 0,
leaseStart: new Date(0),
leaseEnd: new Date(0),
numBeds: 0,
isSec8: false,
tenantPortion: 0,
sec8Portion: 0
};
....
....//trying to make another constructor
function Units(){
unitNumber = "1";
monthlyRent = 0;
leaseStart = new Date(0);
leaseEnd = new Date(0);
numBeds = 0;
isSec8 = false;
tenantPortion = 0;
sec8Portion = 0;
}
var yale = new RentalProperty()
var yale.unit33 = new Units();
....but when I try to make an instance of the new Units class with the RentalProperty instance before it in dot notation it says 'Unexpected Token'.
I have only been learning to code for 2 months (approx one month each of html and javascript) so I'm pretty sure this is a noob question. Any help would be much appreciated..... This is also my first stackoverflow question so please accept my apologies if my formatting is off.

It seems like you want
this.units = []; // an array which
for (var i=0; i < this.numberOfUnits; i++) { // in a loop
this.units[i] = { // is filled with objects
unitNumber : i,
monthlyRent: 0,
leaseStart: new Date(0),
leaseEnd: new Date(0),
numBeds: 0,
isSec8: false,
tenantPortion: 0,
sec8Portion: 0
};
}
Of course instead of the object literal you also can use new Units(i) or something to create the unit objects.
If you don't want an array, but make numbered properties on your object (I'd discourage from that) it would be
this["unit"+i] = …

You are overcomplicating things. As long as there is a Unit constructor already defined you can just do:
function RentalProperty(numberOfUnits){
this.numberOfUnits = numberOfUnits;
this.units = [];
for (var i = 0; i < numberOfUnits; ++i) {
this.units.push(new Unit(i));
}
}
This constructor can be globally scoped, as in
function Unit(unitNumber) {
this.unitNumber = unitNumber;
}
or you can also make it a property of RentalProperty:
RentalProperty.Unit = function(unitNumber) {
this.unitNumber = unitNumber;
}
in which case you would create units with new RentalProperty.Unit(i).

Just consider a completely independent constructor for Unit
RentalProperty.Unit = function Unit(i) {
if (undefined === i) i = 1;
this.unitNumber = '' + i;
this.monthlyRent = 0;
this.leaseStart = new Date(0);
this.leaseEnd = new Date(0);
this.numBeds = 0;
this.isSec8 = false;
this.tenantPortion = 0;
this.sec8Portion = 0;
};
I put it as a property of RentalProperty to keep everything neat.
Next generate all your units in your RentalProperty constructor, or however..
this.units = [];
var i;
for (i = 0; i < this.numberOfUnits; ++i) {
this.units.push(new RentalProperty.Unit(i));
}
Doing it this way also means you can set up a prototype chain for Unit, should you desire to, and you can confirm that a unit u is indeed a Unit using u instanceof RentalProperty.Unit.

The question has been answered several times but here is the full code.
function Unit(rentProp){
this.unitNumber = ""+(rentProp.units.length+1);
this.rentalProperty=rentProp
//all of the foolowing props could go on prototype
//because the constructor fills them only with default values
//later you'll assign new values to them with
//someUnitInstance.monthlyRent=...
this.monthlyRent = 0;
this.leaseStart = null;
this.leaseEnd = null;
this.numBeds = 0;
this.isSec8 = false;
this.tenantPortion = 0;
this.sec8Portion = 0;
}
function RentalProperty(numberOfUnits, address
, dateAcquired, acCost, isFinanced
,loanAmount){
this.numberOfUnits = numberOfUnits;
this.address = address;
this.dateAcquired = new Date(dateAcquired);
this.acCost = acCost;
this.isFinanced = isFinanced;
this.units=[];
};
//default values on prototype, assuming you're not using
//hasOwnProperty later to iterate through properties because
//defaults (on prototype) won't show up
RentalProperty.prototype.loanAmount = 0;
RentalProperty.prototype.newValue = 0;
RentalProperty.prototype.equity = function(){
if (this.newValue === 0){
return (this.acCost - this.loanAmount);
} else {
return (this.newValue - this.loanAmount);
}
};
RentalProperty.prototype.addUnit = function(){
this.units.push(new Unit(this));
}
var r=new RentalProperty();
r.addUnit();
r.addUnit();
console.log(r.units);

Related

Javascript foreach not executing for all objects

I currently have an object that adds itself to an array whenever a new one is created. Eventually, I want to remove all of the references in the array so I can add new ones.
I've created an object method (this.removeFromArray()) that looks for itself in the array and splices itself out. removeAll() runs a for loop that makes each object in the array run removeFromArray(), so I expect that when I try to read out the items in the array, I should get nothing.
Instead, depending on the amount of objects created, I get one or two left behind. How can I fix this and have all objects in the array cleared out?
var objArray = [];
function obj(name) {
objArray.push(this);
console.log("Created "+name);
this.name = name;
this.removeFromArray = function() {
objArray.splice(
objArray.findIndex(function(e) {
return e == this;
}),
1
);
}
}
function removeAll() {
for (var i = 0; i <= objArray.length - 1; i++) {
objArray[i].removeFromArray();
}
}
var foo = new obj("foo");
var bar = new obj("bar");
var cat = new obj("cat");
var dog = new obj("dog");
var bird = new obj("bird");
removeAll();
for (var i = 0; i <= objArray.length-1; i++) { //Check the values in the array for leftovers
console.log(objArray[i].name);
}
//Expected nothing in the console but the creation messages, got foo and bar instead
If you want to simply delete all the created object, edit removeAll() function like below:
Note that you have to create a variable for objArray.length, not directly put the objArray.length to for() loop.
function removeAll() {
var len = objArray.length;
for (var i = 0; i <= len - 1; i++) {
objArray.splice(0,1);
}
}
better way to achieve this would be to utilize inheritance through prototype. it is better than creating a function inside the constructor object.
var objArray = [];
function Obj(name) {
this.name = name;
objArray.push(this);
}
Obj.prototype.removeFromArray = function() {
var i = -1,
len = objArray.length,
removed = null;
while (++i < len) {
if (objArray[i] === this) {
removed = objArray.splice(i, 1);
removed = null; //nullify to free memory, though not that necessary
break;
}
}
};
Obj.prototype.removeAll = function() {
var len = objArray.length,
removed = null;
//note that i started from the last item to remove to avoid index out of range error
while (--len >= 0) {
removed = objArray.splice(len, 1);
removed = null; //nullify to free memory, though not that necessary
}
};

array.push only the last variable in a for loop javascript

i'm actually asking myself why the following code is not working properly i found the solution but it's a bit tricky and i don't like this solution
Here is the code and the problem:
function powerSet( list ){
var set = [],
listSize = list.length,
combinationsCount = (1 << listSize),
combination;
for (var i = 1; i < combinationsCount ; i++ ){
var combination = [];
for (var j=0;j<listSize;j++){
if ((i & (1 << j))){
combination.push(list[j]);
}
}
set.push(combination);
}
return set;
}
function getDataChartSpe(map) {
var res = {};
for (var i in map) {
console.log("\n\n");
var dataSpe = {certif: false,
experience: 0,
expert: false,
grade: 1,
last: 100,
name: undefined
};
var compMatchList = [];
for (var j in map[i].comps_match) {
var tmp = map[i].comps_match[j];
compMatchList.push(tmp.name)
}
var tmpList = powerSet(compMatchList);
var lol = [];
lol.push(map[i].comps_match);
for (elem in tmpList) {
console.log("mdr elem === " + elem + " tmplist === " + tmpList);
var tmp = tmpList[elem];
dataSpe.name = tmpList[elem].join(" ");
lol[0].push(dataSpe);
}
console.log(lol);
}
return res;
}
now here is the still the same code but working well :
function powerSet( list ){
var set = [],
listSize = list.length,
combinationsCount = (1 << listSize),
combination;
for (var i = 1; i < combinationsCount ; i++ ){
var combination = [];
for (var j=0;j<listSize;j++){
if ((i & (1 << j))){
combination.push(list[j]);
}
}
set.push(combination);
}
return set;
}
function getDataChartSpe(map) {
var res = {};
var mapBis = JSON.parse(JSON.stringify(map));
for (var i in map) {
var compMatchList = [];
for (var j in map[i].comps_match) {
var tmp = map[i].comps_match[j];
compMatchList.push(tmp.name)
}
var tmpList = powerSet(compMatchList);
mapBis[i].comps_match = [];
for (elem in tmpList) {
tmpList[elem].sort();
mapBis[i].comps_match.push({certif: false,
experience: 0,
expert: false,
grade: 1,
last: 100,
name: tmpList[elem].join(", ")});
}
}
return mapBis;
}
Actually it's a bit disapointig for me because it's exactly the same but the 1st one doesn't work and the second one is working.
so if anyone can help me to understand what i'm doing wrong it'll be with pleasure
ps: i'm sorry if my english is a bit broken
In the first version, you build one dataSpe object and re-use it over and over again. Each time this runs:
lol[0].push(dataSpe);
you're pushing a reference to the same single object onto the array.
The second version of the function works because it builds a new object each time:
mapBis[i].comps_match.push({certif: false,
experience: 0,
expert: false,
grade: 1,
last: 100,
name: tmpList[elem].join(", ")});
That object literal passed to .push() will create a new, distinct object each time that code runs.

javascript - create new (global) objects with names from array

i am trying to create new Objects with names out of an array.
Without an array i would do:
var object_bruno = new Object();
var object_carlos = new Object();
var object_luci = new Object();
so i will end up with 3 new Objects. But why wont we do that with an loop, which makes it more easy to adde some more Objects later. So i ttried:
// an array full of object names
var obj_arr = [ "object_bruno", "object_carlos", "object_luci"];
// Method one:
for (x in obj_arr) {
alert(obj_arr[x]); // right names shown
var obj_arr[x] = new Object(); //syntax error, dosent work??
};
// Method two:
obj_arr.forEach(function(func_name) {
alert(func_name); // right names
var func_name = new Object(); // no objects are created ???
});
basicly i would prefer to use Method two. i like it because i can fill them late the same way? hopefuly? Any ideas what wents wrong?
You can just loop over the array and assign a new Object to each of the items , like this:
for (var i = 0, l = obj_arr.length; i < l; i++) {
obj_arr[i] = {};
}
UPDATE
You can also do it in this way by applying properties to the global object, for example window:
var people = [ "object_bruno", "object_carlos", "object_luci"];
for (var i = 0, l = people.length; i < l; i++) {
global[people[i]] = {};
}
Using this solution makes the objects global, so you can use them like object_bruno.
Another improvement can be the usage of computed propertiey names of ECMAScript 2015:
var people = [ "bruno", "carlos", "luci"], prefix = 'object_';
for (var i = 0, l = people.length; i < l; i++) {
global[prefix + people[i]] = {};
}
This allows to have more meaningful array.
Note, the global can be the window object in browsers or global object in NodeJS, or perhaps something else in other environments.
Because you are creating a new variable by declaring
obj_arr.forEach(function(func_name) {
alert(func_name); // right names
var func_name = new Object(); // no objects are created ???
});
try this
obj_arr.forEach(function(func_name) {
alert(func_name); // right names
func_name = new Object(); // no objects are created ???
});
var obj_arr = [ "object_bruno", "object_carlos", "object_luci"];
obj_arr.forEach(function(func_name, index, arr) {
arr[index] = {};
});

Create objects with names from an elements id attribute

I'm trying to create a few objects whose names are the id attributes of the divs with class="characteristic". How do i get the id for the name?
window.onload = function() {
var characteristicElements = document.getElementsByClassName("characteristic");
for ( var i = 0 ; i < characteristicElements.length ; i++ ) {
var characteristicElements[i].getAttribute("id") = { set: false, val: 0, unn: 0 };
}
};
You should create a map then, using an object, and use the ID as property name:
var objects = {};
var characteristicElements = document.getElementsByClassName("characteristic");
for ( var i = 0 ; i < characteristicElements.length ; i++ ) {
objects[characteristicElements[i].id] = {'set': false, val: 0, unn: 0 };
}
Afaik you have to put set in quotes because it is a keyword in object literals. I could be wrong though. Also note that getElementsByClassName is not available in IE8 and before.
I recommend reading the MDN JavaScript Guide - Working with Objects.
characteristicElements[i].getAttribute("id") is a string. What you're doing is like var "foo" = "bar";, doesn't make sense. What you want to do is doable but only with eval, and eval is evil. If you put the objects within another object it gets much easier:
window.onload = function() {
var characteristicElements = document.getElementsByClassName("characteristic");
var objects = {}; // New empty object
for ( var i = 0 ; i < characteristicElements.length ; i++ ) {
objects[characteristicElements[i].getAttribute("id")] = { set: false, val: 0, unn: 0 };
}
};
objects["foo"] is the same as objects.foo, just another notation.

Javascript: sort objects

function Player() {
var score;
this.getScore = function() { return score; }
this.setScore = function(sc) { score = sc; }
}
function compare(playerA, playerB) {
return playerA.getScore() - playerB.getScore();
}
var players = [];
players['player1'] = new Player();
players['player2'] = new Player();
Array(players).sort(compare);
I have code that is similar to the above. When I step through the code with a debugger, the compare function never gets called and the array isn't sorted. I'm not sure what's wrong with my code?
It's not sorting because you have specified the keys that the variables within the array belong on. Sorting will only move the objects on integer-valued keys. You should see your sorting work if you create your array as follow:
var players = [new Player(), new Player()];
though, of course, it won't be very effective since you have neither a score on which to sort or a method of identifying them. This'll do it:
function Player(name, score) {
this.getName = function() { return name; }
this.getScore = function() { return score; }
this.setScore = function(sc) { score = sc; }
}
function comparePlayers(playerA, playerB) {
return playerA.getScore() - playerB.getScore();
}
var playerA = new Player('Paul', 10);
var playerB = new Player('Lucas', 5);
var playerC = new Player('William', 7);
var players = [playerA, playerB, playerC];
for (var i = 0; i < players.length; i++)
alert(players[i].getName() + ' - ' + players[i].getScore());
players.sort(comparePlayers);
for (var i = 0; i < players.length; i++)
alert(players[i].getName() + ' - ' + players[i].getScore());
Hope that helps.
The main problem lies in this line:
Array(players).sort(compare);
Array(something) makes an array with something as its element.
console.log(Array(players)); //[[player1, player2]]
Use numeric indexed array instead of using object like array as in players['player1']
Run the following code (replace console.log with alert if you don't have Firebug).
function Player() {
var score;
//return this.score - else it returns undefined
this.getScore = function() { return this.score; }
this.setScore = function(sc) { this.score = sc; }
}
function compare(playerA, playerB) {
console.log("called " + playerA.getScore() + " " + playerB.score);
//compare method should return 0 if equal, 1 if a > b and -1 if a < b
return (playerA.getScore() == playerB.getScore()) ? 0
: ((playerA.getScore() > playerB.getScore()) ? 1 : -1);
}
var players = [];
players[0] = new Player();
players[1] = new Player();
players[2] = new Player();
players[3] = new Player();
players[0].setScore(9);
players[1].score = 14;
players[2].score = 11;
players[3].score = 10;
players.sort(compare);
console.log(players);//prints sorted array
It's probably because you don't have any "array values" inside your array - textual indexes are not regarded as array values but as object propertiest (arrays are "objects in disguise" in javascript). You can add as many properties to any object but array specific methods like sort take only "real" array members as their parameteres (i.e. only with numerical indexes)
var arr = new Array()
arr[0] = 1
arr[1] = 2
arr["textual_index"] = 3
alert(arr.length);
The last line alerts "2" not "3" since there are only two values with numeric indexes.
you can also use like below:
var a = [];
a.push(obj1);
a.push(obj2);
a.sort(compare);
so you can use push method rather than an integer index

Categories

Resources