Initialize array in javascript constructor - javascript

I have a constructor and i want to initialize an array inside the object to be created. This array is supposed to contain a couple of objects.
function Cluster3DObject(name){
this.name = name;
this.array = [];
}
Cluster3DObject.prototype.add = function(obj) {
this.array.push(this.obj);
};
Here i define the "class" and i have added one method "add" and it is supposed to push an object into this.array..
var cluster = new Cluster3DObject("clster");
var testObj = new THREE.CSS3DObject(testDiv);
var testVector = new THREE.Vector3();
cluster.add(testObj);
When i call the cluster.add method i get the "undefined is not a function error" but i can't seem to find out what i'm doing wrong?
i am new to using constructors..

It's not this.obj, just obj
Cluster3DObject.prototype.add = function(obj) {
this.array.push(obj);
};
otherwise it seems fine, but that wouldn't really produce a "undefined is not a function error", it would just push undefined, so the error probably comes from trying to use the array filled with undefined values ?
FIDDLE

Related

Object's method getting called on object, when is store in a variable but not when the objects are stored in an array

I have defined a class Timeline in Javascript using the constructor method,
function Timeline(formal parameters)
{
//property definitions
}
The methods are defined on the prototype object,
Timeline.prototype.zoomMax = function(){ // Method Definition };
I am using array to store the objects of Timeline,
var timeline = [];
timeline[0] = new Timeline(parameter's values);
timeline[1] = new Timeline(parameter's values);
But when I am calling the method of Timeline as,
timeline[0].zoomMax();
I am getting the error,
Uncaught TypeError: Cannot read property 'zoomMax' of undefined
Note: I have checked printing timeline[0], object is getting stored in it.
When I am storing the object in a simple variable instead of an array, it works fine,
var timeline = new Timeline(parameter's values);
timeline.zoomMax(); //Gives me the output
I am not getting, how do I call the method zoomMax() on the objects stored in array.
Please guide.
My Timeline Code,
function Timeline(video_duration_in_sec,frames_per_sec = 25,zoom_value=1){
ComponentContainer.call(this,'time-cover');
this.video_duration_in_sec = video_duration_in_sec;
this.frame_count = video_duration_in_sec * frames_per_sec;
this.zoom_value = zoom_value;
this.ruler_width = this.video_duration_in_sec * (100/this.zoom_value);
this.min = 1;
this.max = 25;
}
Use class keyword to define object class
class Timeline
{
constructor(parameters) {
//property definitions, initialization...
}
zoomMax() {
console.log('zoom');
}
}
var timeline = [];
timeline[0] = new Timeline('parameters values');
timeline[1] = new Timeline('parameters values');
timeline[0].zoomMax();
This is working fine for me
function Timeline(params){ ... }
Timeline.prototype.zoomMax = function() { ... }
var timeline = []
timeline[0] = new Timeline(param1);
timeline[1] = new Timeline(param2);
timeline[0].zoomMax(); // Executes zoomMax function
Your initial error could have been due to wrong declaration of zoomMax method. More info about this is here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_a_function

Using HTML5 Audio in Javascript Objects

When I run the following...
var obj = {
array: ['1.mp3', '2.mp3', '3.mp3'],
audio: new Audio(this.array[0])
};
...I get an error saying that it cannot read property '0' of undefined. However, when I run the following...
var obj = {
array: ['1.mp3', '2.mp3', '3.mp3'],
};
var audio = new Audio(this.obj.array[0]);
...everything runs smoothly. How would I fix the first example? Am I doing something wrong with this?
How would I fix the first example? Am I doing something wrong with this?
You can't. The object is not yet created, so you can't refer to the property, using this
You can however do this
var obj = {
array: ['1.mp3', '2.mp3', '3.mp3'],
}; // object now created
obj.audio = new Audio(this.obj.array[0]); // set the property.
Note that you can refer to this to refer to the obj inside functions, but not outside them.
var obj = {
prop: (console.log(this), "Some value") // most probably Window but never obj
func: function(){
console.log(this); // obj
}
}
The problem is using this inside of a constructor: it's not referring to obj, it's referring to the new Audio object. You won't be able to reference it using this from inside the object like that.
Another way to do the same thing would be as follows:
var refArray = ['1.mp3', '2.mp3', '3.mp3'];
var myObj = {
array: ['1.mp3', '2.mp3', '3.mp3'],
audio: new Audio(this.obj.array[0]);
};
This does the same thing as stated in other answers, but allows you to add the audio object (as a property to the myObj) while you are defining the myObj variable.

Javascript Array defined in constructor is undefined in prototype

I'm pretty new to writing OO JS, but this has stumped me. So I setup me new Call object, then define what I assume to be empty arrays. When I call AddFieldQueryToArray() I get
Uncaught TypeError: Cannot call method 'push' of undefined
On this.fieldArray.push(field)
I don't really know why. I've tried this.fieldArray = fieldArray; in the constructor too.
function Call()
{
var fieldArray = new Array();
var queryArray = new Array();
}
Call.prototype.AddFieldQuerysToArray = function(field,query)
{
if(field !== 'undefined')
{
this.fieldArray.push(field);
}
this.queryArray.push(query);
}
You should reference instance properties with this. inside the constructor:
function Call()
{
this.fieldArray = [];
this.queryArray = [];
}
new Array() has a shortcut [] which I have used above.
If you use var fieldArray = []; you would create a local variable which is destroyed once your instance has been created unless you use this kind of construct:
function Call()
{
var fieldArray = [];
this.AddFieldQuerysToArray = function(field, query) {
// ...
fieldArray.push(field);
}
}
This creates a closure for each instance in which fieldArray is "kept alive" throughout the instance's lifetime.
function Call()
{
this.fieldArray = [];
this.queryArray = [];
}
Call.prototype.AddFieldQuerysToArray = function(field,query)
{
if(field !== 'undefined')
{
alert('field==='+this.fieldArray);
this.fieldArray.push(field);
}
alert('field==='+this.fieldArray);
this.queryArray.push(query);
alert(this.queryArray);// to check
alert(this.fieldArray);// to check
};
field = 'exampleField';
query = 'exampleField';
var cally = new Call();
cally.AddFieldQuerysToArray(field,query); //change
The only problem is that you were calling Call.prototype.AddFieldQuerysToArray() method and here this value actually
referred to execution context of Call.prototype object which didn't have the arrays fieldArray and queryArray.
Calling the prototype method AddFieldQuerysToArray() by coding cally.AddFieldQuerysToArray(field,query); refers to the execution context
of the cally instance which has got both the arrays declared in it through its constructor.
It's a very older post & the answer was given by Jack. this has to be used to avoid the Error.
But there's an anti-pattern used in the code block. new Array() should be avoided. Better approach is to use Array Literal Notation. Follow this StackOverflow answer What’s the difference between "Array()" and "[]" while declaring a JavaScript array? for details.
But the gist is that if only one parameter is given to the Array constructor then that will interpreted as length of the Array but that will NOT BE THE FIRST element in the array.
console.log(new Array(10).length);//10
console.log(new Array(10)[0] === undefined);//true

Javascript apply methods from one object to another

I have been at this for hours and just can't get it quite right. I have an object with methods that works fine. I need to save it as a string using JSON.stringify and then bring it back as an object and still use the same methods.
function Workflow(){
this.setTitle = function(newtitle){this.title = newtitle; return this;};
this.getTitle = function(){return this.title;};
}
function testIn(){
var workflow = new Workflow().setTitle('Workflow Test');
Logger.log(workflow);//{title=Workflow Test}
Logger.log(workflow.getTitle()); //Workflow Test
var stringy = JSON.stringify(workflow);
var newWorkflow = Utilities.jsonParse(stringy);
Logger.log(newWorkflow); //{title=Workflow Test}
//Looks like the same properties as above
Logger.log(newWorkflow.getTitle());//Error can't find getTitle
}
I think I should prototype the new object but nothing seems to work.
Please help I have very little hair left.
You need to copy the method to the new object:
newWorkflow.getTitle = workflow.getTitle;
you are losing your functions when you stringify and parse.
if you have access to jquery, the $.extend is handy (if not, just copy&paste form jquery source)
here's a demo:
http://jsfiddle.net/VPfLc/
Serializing to JSON won't store executable code. It's being removed from your object when calling JSON.stringify. Your best bet is to make the object so it can be initialized when created.
function Workflow(){
this.initialize = function(properties) { this.title = properties.title; }
this.setTitle = function(newtitle){this.title = newtitle; return this;};
this.getTitle = function(){return this.title;};
}
function testIn(){
var workflow = new Workflow().setTitle('Workflow Test');
Logger.log(workflow);//{title=Workflow Test}
Logger.log(workflow.getTitle()); //Workflow Test
var stringy = JSON.stringify(workflow);
var newWorkflow = new Workflow().initialize(Utilities.jsonParse(stringy));
Logger.log(newWorkflow); //{title=Workflow Test}
//Looks like the same properties as above
Logger.log(newWorkflow.getTitle());//Error can't find getTitle
}
All you have to do is use call.
Workflow.call(newWorkflow);
EDIT:
If your actual Workflow() implementation sets any attributes to default values during its initilization then calling on your new json object will also reset those. Which is what I'm assuming is going on, without being able to look at your actual implementation code.
If that is the case, then you have two options.
1) Rather than blindly initilize your object (and assuming its empty), conditionally initilize your variables.
function Workflow(){
this.setTitle = function(newtitle){this.title = newtitle; return this;};
this.getTitle = function(){return this.title;};
this.array = this.array || [];
}
for new empty objects. this.array will be null, and it'll be set to a new array. calling Workflow on a existing object that already has that property, it'll leave it alone.
2) Extract your methods into an Extension Module
function Workflow(){
this.array = this.array || [];
// Other work
// Lastly include my method extensions.
WorkflowMethodExtensions.call(this);
}
function WorkflowMethodExtensions(){
this.setTitle = function(newtitle){this.title = newtitle; return this;};
this.getTitle = function(){return this.title;};
}
Then use:
WorkflowMethodExtensions.call(newWorkflow);
to extend an existing object with those methods defined in the existion

Correct way to reset or clear a Javascript object?

I have a Javascript class that contains a few functions and member objects:
function MyUtils()
{
// Member Variables (Constructor)
var x = getComplexData();
var y = doSomeInitialization();
// Objects
this.ParamHash = function()
{
// Member variables
this.length = 0;
this.items = new Array();
// Constructor
for (var i = 0; i < arguments.length; i += 2)
{
// Fill the items array.
this.items[arguments[i]] = arguments[i+1];
this.length++;
}
}
// Functions
this.doSomething = function()
{
// Do something.
// Uses the items in the ParamHash object.
for (var i in this.ParamHash.items)
{
// Really do something!
}
// Clear the ParamHash object -- How??
}
}
This is invoked in the following manner:
// First call - works fine.
var utils = new MyUtils();
utils.paramHash = new utils.ParamHash("a", 1, "b", 2);
utils.doSomething();
// Don't want to re-initialize.
// utils = new MyUtils();
// Consequent call - crashes ["Object doesn't support this action."].
utils.paramHash = new utils.ParamHash("c", 3);
utils.doSomething();
The problem arises from the restriction that I want to reuse the same utils object throughout the code without having to re-initialize it. Also, I want the ParamHash object to be recreated from scratch everytime I call it. However, consequent calls to the ParamHash constructor throw an error "Object doesn't support this action." At this stage, I can see that the utils.paramHash object still contains the old values ("a", "b").
I have tried various ways to clear the ParamHash object such as setting it's items and length to null, popping items from the array. Nothing seemed to work until I used the following way (in the doSomething() function):
this.paramHash.items = new Array();
this.paramHash.length = 0;
This seems wrong because what if I had a lot of member variables... would I have to reset each of them individually?
So, the question is: What is the best way to reset the ParamHash object to the initial state? I'm sure hoping that there is a cleaner/more direct way. Something like :
// Doesn't work! :-(
this.paramHash = new function() {};
EDIT: I'm looking for a cross-browser solution - One that works atleast in IE6+ and FF 2+.
Solution: Thanks to Cristoph, I was able to do it by creating a separate variable/property within MyUtils which only holds the instance of the ParamHash function.
function MyUtils()
{
// Same ol' stuff.
var myParamHash;
}
// First call - works fine.
var utils = new MyUtils();
utils.myParamHash = new utils.ParamHash("a", 1, "b", 2);
utils.doSomething();
// Consequent call - works fine now.
utils.myParamHash = new utils.ParamHash("c", 3);
utils.doSomething();
This
utils.ParamHash = new utils.ParamHash("a", 1, "b", 2);
overwrites the the property which holds the ParamHash() constructor function with an instance object. You could get the constructor back via
utils.ParamHash.constructor
but the cleaner way would be to not overwrite it in the first place and use a seperate property to hold the instance.
I don't know the exact problem Cerebrus is trying to solve, so there might be valid reasons for what he's doing. But in my opinion, his solution is overly complicated. I'd do something like this:
function MyUtils() {
this.x = getComplexData();
this.y = doSomeInitialization();
this.params = {};
}
MyUtils.prototype.doSomething = function() {
for(var prop in this.params) {
if(this.params.hasOwnProperty(prop)) {
// do stuff
}
}
};
var utils = new MyUtils;
utils.params = { a : 1, b : 2 };
utils.doSomething();
The check for hasOwnProperty() is unnecessary if you can be sure that no one messed with Object.prototype.
Some additional comments:
in JavaScript, normally only the names of constructor functions are capitalized
items shouldn't be an array, but a plain object, ie this.items = {};
when you did this
utils.ParamHash = new utils.ParamHash("a", 1, "b", 2);
you replaced the ParamHash constructor function with an object instance. Subsequent new ParamHash() fails because utils.ParamHash is no longer a constructor function.
Try this:
var utils = new MyUtils();
utils.paramHashInstance = new utils.ParamHash("a", 1, "b", 2);
utils.DoSomething();
Have you tried omitting the new keyword?
utils.ParamHash = utils.ParamHash("c", 3);

Categories