JavaScript class to populate object - javascript

I am trying to populate an object by using a JavaScript class. I am not even sure if I am doing it correctly, I am very new to JavaScript OOP.
var ImagesViewModel = {}; // Global object
function ImagesClass() {
this.addImage = function (iUrl) {
ImagesViewModel.push({ "ImageUrl": iUrl }) //< Error is here
}
}
var k = new ImagesClass()
k.addImage("http://www.yahoo.com")
k.addImage("http://www.xbox.com")
Basically I need an easy way to populate ImagesViewModel with multiple properties. Do I need to specify properties within ImagesViewModel? Maybe I can do all of this without having to specify a global variable?
I am getting the error
Object has no method PUSH

What you want is an array and not an object, push is a method on Array prototype and you are trying to use it on object.
Change:
var ImagesViewModel = {};
To:
var ImagesViewModel = [];
You can do it this way as well so that each instance of ImagesClass has its own set of images.
function ImagesClass() {
var _images = [];
this.addImage = function (iUrl) {
_images.push({ "ImageUrl": iUrl }) //< Error is here
}
this.getImages = function(){
return _images;
}
}
and use it as:
var k = new ImagesClass();
k.addImage("http://www.yahoo.com");
k.addImage("http://www.xbox.com");
var ImagesViewModel = k.getImages(); //You can either set it directly or as a property of object
console.log(ImagesViewModel);
Demo

the push method is only for Arrays, here you are trying to push() to an object, which is why it isn't working.
You will need to change var ImagesViewModel = {}; to var ImagesViewModel = [];

From a design perspective, you probably don't want your viewmodel to just be a flat array (even though you declared it as an object, as other posters pointed out).
I'd suggest declaring an array declaration to hold the images inside of your ImagesViewModel object.
var ImagesViewModel = { // ViewModel generic OBJECT
this.Images = new Array(); // prototype ARRAY object
};
function ImagesClass() {
this.addImage = function (iUrl) {
ImagesViewModel.Images.push({ "ImageUrl": iUrl })
}
}

Related

Javascript Arrays as an object field

I am running into a problem with using an array as a Javascript field.
var Object = function () {
var admins = [];
this.addAdmin = function(admin){
this.admins.push(admin)
}
}
Normally I would expect admin to be pushed into the array admins but instead I get a 'cannot read property 'push' of undefined'.
If I'm not mistaken when I initialized the Object with new Object(), admins = []; should initialize the array. Is this a limitation of Javascript?
Thank you in advance.
var array creates a local variable. It does not create a property on the object.
You need:
this.admins = [];
or
admins.push(admin) /* without this */
In your function admins is a local variable to the function. You need to declare admins as a property on the instance.
function Obj(){
this.admins = [];
}
Obj.prototype.addAdmin = function(admin){
this.admins.push(admin);
}
obj = new Obj();
obj.addAdmin('tester');
Also, because Object is the global base object, don't create functions or objects named Object.
I suspect you've gotten confused (which is easy :-) ) because you've seen code like this:
class Obj {
admins = [];
addAdmin(admin) {
this.admins.push(admin);
}
}
That uses the modern class and class fields syntax to puts an admins property on the object constructed via new Obj. (Note there's no var before admins = [];.) But in your code, you've used the older function-based syntax. Within your function, var admins = []; just creates a local variable, not a property.
I'd suggest that if you want to create constructor functions, using the new class syntax above is the simpler, more powerful way to do that. If you want to use the older syntax, though, other answers have shown how, but for completeness either make admins a property of the object:
let Obj = function() {
this.admins = []; // ***
this.addAdmin = function(admin){
this.admins.push(admin)
};
};
or perhaps with addAdmin on the prototype:
let Obj = function() {
this.admins = []; // ***
};
Obj.prototype.addAdmin = function(admin){
this.admins.push(admin)
};
or use the fact addAdmins closes over the call to Obj, and thus the local admins:
let Obj = function() {
const admins = [];
this.addAdmin = function(admin){
admins.push(admin) // <=== No `this.` here, you want to close over the
// `admins` local
};
};
I am assumming Object is a placeholder, because it is a reserved keyword.
What is happening is, your variable var admins = []; is created locally and can noot be accesed with the this. as a result when you set the value in this.admins.push(admin) the admins there is undefined. you should modify your function to read this way
var Obj = function () {
this.admins = [];
this.addAdmin = function (admin) {
this.admins.push(admin);
};
};
const object = new Obj();
object.addAdmin(1);
you should not omit the this keyword like this(no pun intended) if you plan to new the function. Stick to the code above.
var Obj = function () {
var admins = [];
this.addAdmin = function (admin) {
admins.push(admin);
};
};
const object = new Obj();
console.log(object)

How to make the variable available in the methods of the class?

I apologize for this question, just starting to learn Javascript.
I have 2 methods:
Manager.prototype.filters = function () {
var user = [];
...
Manager.prototype.filters_main = function () {
var user = [];
...
I need to make the property 'user' available to the 2 methods (filters, filters_main). So that they can use the shared variable (user).
How it is possible to write?
You have to understand the prototype-based inheritance here.
var Manager = function() {
this.user = [];
}
var manager = new Manager();
These lines will define a Manager constructor function and create a new object. When you call the new Manager(), what happens is:
a new, empty, object is created: {}.
the code inside the constructor will run with this new, empty, object being the value of this. So, it will set the user property of the new object ({}) to be an empty array.
the __proto__ property of the new object will be set to the value of Manager.prototype. So, this happens without you seeing: manager.__proto__ = Manager.prototype.
Then, you want to define new methods on your prototype objects, using the inheritance. Keep in mind that the prototype is a plain JS object. Not a constructor, but an object. So every object created from the Manager function will have its __proto__ property set to the same object.
Then, you start defining new methods on the prototype object, like the filters function. When you, later, call manager.filters(), it will first look up its own properties for the filters function and won't find it. So, then, it will go for its prototype properties, and there if will find it. manager will then run the filters function that was defined on the prototype, but using itself (manager) as the context, as the this inside the function.
So, to use your user property inside the filters function, all you have to do is:
Manager.prototype.filters = function () {
this.user = ...;
}
Manager.prototype.filters_main = function () {
this.user = ...;
}
and you'll be manipulating the same user property defined when the object was constructed.
Define the variable in your Manager definition:
function Manager() {
this.user = [];
}
And now you should be able to use it in your filter functions:
Manager.prototype.filters = function() {
// Use it:
if (this.user.indexOf(...) != -1) {
...
}
};
Then you can continue as normal:
var manager = new Manager();
manager.user = ["user1", "user2"];
var filters = manager.filters();
Add it to the body:
function Manager() {
this.user = [];
}
Manager.prototype.filters = function () {
alert(this.user)
}
var m = new Manager();
m.user = [11,22,33]
m.filters();

Can you use custom objects as properties of an object in javascript?

Suppose I create a custom object/javascript "class" (airquotes) as follows:
// Constructor
function CustomObject(stringParam) {
var privateProperty = stringParam;
// Accessor
this.privilegedGetMethod = function() {
return privateProperty;
}
// Mutator
this.privilegedSetMethod = function(newStringParam) {
privateProperty = newStringParam;
}
}
Then I want to make a list of those custom objects where I can easily add or remove things from that list. I decide to use objects as a way to store the list of custom objects, so I can add custom objects to the list with
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = true;
myListOfCustomObjects[customObjectInstance2] = true;
myListOfCustomObjects[customObjectInstance3] = true;
and remove custom objects from the list with
delete myListOfCustomObjects[customObjectInstance1];
but if i try to iterate through the list with
for (i in myListOfCustomObjects) {
alert(i.privilegedGetMethod());
}
I would get an error in the FireBug console that says "i.privilegedGetMethod() is not a function". Is there a way to fix this problem or an idiom in javascript to do what I want? Sorry if this is a dumb question, but I'm new to javascript and have scoured the internet for solutions to my problem with no avail. Any help would be appreciated!
P.S. I realize that my example is super simplified, and I can just make the privateProperty public using this.property or something, but then i would still get undefined in the alert, and I would like to keep it encapsulated.
i won't be the original object as you were expecting:
for (i in myListOfCustomObjects) {
alert(typeof i); // "string"
}
This is because all keys in JavaScript are Strings. Any attempt to use another type as a key will first be serialized by toString().
If the result of toString() isn't somehow unique for each instance, they will all be the same key:
function MyClass() { }
var obj = {};
var k1 = new MyClass();
var k2 = new MyClass();
obj[k1] = {};
obj[k2] = {};
// only 1 "[object Object]" key was created, not 2 object keys
for (var key in obj) {
alert(key);
}
To make them unique, define a custom toString:
function CustomObject(stringParam) {
/* snip */
this.toString = function () {
return 'CustomObject ' + stringParam;
};
}
var obj = {};
var k1 = new CustomObject('key1');
var k2 = new CustomObject('key2');
obj[k1] = {};
obj[k2] = {};
// "CustomObject key1" then "CustomObject key2"
for (var key in obj) {
alert(key);
}
[Edit]
With a custom toString, you can set the object as the serialized key and the value to keep them organized and still continue to access them:
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = customObjectInstance1;
myListOfCustomObjects[customObjectInstance2] = customObjectInstance2;
myListOfCustomObjects[customObjectInstance3] = customObjectInstance3;
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
The for iteration variable is just the index, not the object itself. So use:
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
and, in my opinion, if you use an Object as an array index / hash, it just would be converted to the string "Object", which ends up in a list with a single entry, because all the keys are the same ("Object").
myListOfCustomObjects =[
new CustomObject('someString'),
new CustomObject('someOtherString'),
new CustomObject('yetAnotherString')
]
you will get access to any element by index of array.

javascript / jquery - adding properties to an instantiated object

I am instantiating an object which builds an associative array. After it is instantiated, I want to add properties the object's members, but I'm getting an error when I attempt to do so.
So this is the object, which parses a bunch of xml and builds out the scenes and vehicles arrays:
var supertree = {
scenes: {},
vehicles: {},
init: function() {
this.parseScenes();
this.parseVehicles();
},
...
And when I instantiate the object:
supertree.init();
supertree.ready = function() {
assignSpritePos();
}
I can't add properties to it. This is what I'm trying to do:
function assignSpritePos(){
var sceneCount = 0;
var sceneLength = Object.keys(supertree.scenes).length;
for (i=0; i< sceneLength; i++){
//console.log(i);
supertree.scenes[i].index = i;
sceneCount++;
}
}
As you can see, all I'm really trying to do is store some permanent reference to its index in the overall object. How do I do this? The error I get is:
TypeError: 'undefined' is not an object (evaluating 'supertree.scenes[i].index = i')
Assigning properties to objects isn't recursive, i.e. it doesn't create objects automagically for you so you must assign each property individually.
Try this...
supertree.scenes[i] = { 'index': i };
You can't assign a property to an object that doesn't exist yet. Use this:
supertree.scenes[i] = {};
supertree.scenes[i].index = i;

Loop through All Objects of a Class

Let's say I have some class called loopObject and I initialize every object through something like var apple = new loopObject(); Is there anyway to loop through all objects of a class so that some function can be performed with each object as a parameter? If there isn't a direct method, is there a way to place each new object into an array upon initialization?
You can make an array that contains every instance, like this:
function LoopObject() {
LoopObject.all.push(this);
}
LoopObject.all = [];
However, it will leak memory - your instances will never go out of scope.
function loopObject(){
this.name = 'test'
};
var list = [], x = new loopObject, y = new loopObject;
list.push(x)
list.push(y)
for ( var i = list.length; i--; ) {
alert( list[i].name )
}
var allObjects [] = new Array();
function loopObject() {
...
allObjects.push(this);
}
Then one can loop through all elements of allObjects as necessary using allObjects.length.

Categories

Resources