Reputation: 89
I am still getting the hang of it, and its probally logic for a lot of you. But I've updated the post with how I got it working, might some one come here by search.
declare:
var test=Element({"id" : 1, "name" : "wrapper"}).
append(Element({"id" : 2, "name" : "elm A"}),
Element({"id" : 3, "name" : "elm b"})
);
alert(test.getInfo("name"));
alert(test.aArguments["children"][1].getInfo("name"));
'class':
var Element = function ($aPassArguments) {
aArguments: {
"id" : false,
"name" : false,
"type" : false,
"title" : false,
"style" : false,
"action" : [],
"parent" : false,
"children" : []
};
for (var prop in this.aArguments)
if (prop in $aPassArguments)
this.aArguments[prop] = $aPassArguments[prop];
return {
append: function () {
$argList = arguments;
for ($i = 0; $i < $argList.length; $i++)
if (typeof $argList[$i]=="string")
this.setChild(this.importDB($argList[$i],true));
else
this.setChild($argList[$i]);
},
setChild: function($oChild) {
this.aArguments["children"][this.aArguments["children"].length]=$oChild;
}
};
};
.............................................................
I wasnt aware a new object instance in javascript is a reference instead of a copy. Now I want to have a copy of my own object Element. Apperantly (thanks @blurd) I want it to be a factory hybrid: http://javascript.info/tutorial/factory-constructor-pattern
Thanks to the help of @blurd and me defining some problems, I came up with a sollution like the following:
In which I finaly got copies of my Element object instead of references. The good answers below didnt completly solve my problem. But this is due to my poor clarification and understanding of the problems
var Element = function (initialConfig) {
return {
aArguments: {
"id" : false,
"name" : false,
"type" : false,
"title" : false,
"style" : false,
"action" : [],
"parent" : false,
"children" : [],
},
create:function ($aPassArguments) {
for (var prop in this.aArguments)
if (prop in $aPassArguments)
this.aArguments[prop] = $aPassArguments[prop];
},
append: function () {
$argList = arguments;
for ($i = 0; $i < $argList.length; $i++)
if (typeof $argList[$i]=="string")
this.setChild(this.importDB($argList[$i],true));
else
this.setChild($argList[$i]);
},
setChild: function($oChild) {
this.aArguments["children"][this.aArguments["children"].length]=$oChild;
}
};
};
var test=Element();
test.create({"id" : 1, "name" : "wrapper"});
var test2=Element();
test2.create({"id" : 2, "name" : "elm A"});
test3.create({"id" : 3, "name" : "elm B"});
test.append(test2,test3);
alert(test.aArguments["name"]);
alert(test.aArguments["children"][0].aArguments["name"]);
Now I am very unhappy about the usage,I would like it be one line and use a constructor again. And this is probally possible, and... after some more selfschooling I will probally solve it. But for now I am done with it :P just updated my post with this. When I get to it again and have a beter declaration I will update it again. And perhaps someone might share a way (beter way) to do this. To eventually have something like this:
var test=new Element({"id" : 3, "name" : "wrapper"})
.append( new Element{"id" : 3, "name" : "elm A"}),
new Element({"id" : 3, "name" : "elm B"})
);
.............................................................................................
I am pulling my hair outs here, everything I search about javascript and objects tells me the same, which is not enough, because I cant figure out why the following code isnt working propaly:
For example I am making an object like this:
var Element = {
aArguments: { //set Default arguments
"id" : false,
"name" : false,
"type" : false,
"title" : false,
"style" : false,
"action" : [],
"parent" : false,
"children" : {},
},
create:function ($aPassArguments) {
for (var prop in this.aArguments)
if (prop in $aPassArguments)
this.aArguments[prop] = $aPassArguments[prop];
return this;
},
append: function () {
$argList = arguments;
for ($i = 0; $i < $argList.length-1; $i++)
if (typeof $argList[$i]=="string")
this.setChild(this.importDB($argList[$i],true));
else
this.setChild($argList[$i]);
return this;
},
setChild: function($oChild) {
this.aArguments["children"][this.aArguments["children"].length-1]=$oChild;
},
getInfo: function($sKey) {
return this.aArguments[$sKey];
}
};
Which merges $aPassArguments with this.Arguments on calling of .create() (I cant figureif its possible to use a '__constructor'). To replace given proparties in aArguments.
And add passed object(s) with .append to aArguments["childeren"].
But when I call the object like this:
$set=(Element.create({"id": 1, "name" : "wrapper"})).
append(Element.create({"id" : 3, "name" : "elm A"}));
alert($set.getInfo("name"));
It will alert me "Elm A" and not "wrapper".
I assume that this is because I am not creating a new object of Element, but are working on the same object. Now to me the logical solution and start would be to write:
$set=(new Element.create({"id": 1, "name" : "wrapper"})).
append(new Element.create({"id" : 3, "name" : "elm A"}));
alert($set.getInfo("name"));
but I get the error: TypeError: (intermediate value).append is not a function
Why isnt my code not working as supposed by me? And is it possible and if so how do I add a constructor to an object? So I could skip calling .create and use:
$set=new Element({"id": 1, "name" : "wrapper"}).
append(new Element({"id" : 3, "name" : "elm A"}));
Upvotes: 1
Views: 84
Reputation: 2417
You are right, you should be using the new
operator. Aside from that, it looks like you're trying to make this some type of factory hybrid. I suggest the following.
Include an optional configuration that you can use when creating the object.
var Element = function (initialConfig) {
if (initialConfig) {
this.create(initialConfig);
}
};
All your shared Element
members should be part of the prototype.
Element.prototype = {
aArguments: {
"id" : false,
"name" : false,
"type" : false,
"title" : false,
"style" : false,
"action" : [],
"parent" : false,
"children" : {},
},
create:function ($aPassArguments) {
for (var prop in this.aArguments)
if (prop in $aPassArguments)
this.aArguments[prop] = $aPassArguments[prop];
return this;
},
append: function () {
$argList = arguments;
for ($i = 0; $i < $argList.length-1; $i++)
if (typeof $argList[$i]=="string")
this.setChild(this.importDB($argList[$i],true));
else
this.setChild($argList[$i]);
return this;
},
setChild: function($oChild) {
this.aArguments["children"][this.aArguments["children"].length-1]=$oChild;
},
getInfo: function($sKey) {
return this.aArguments[$sKey];
}
};
Your examples should now work as you expected. Notice that you can't call new Element.create()
as that would treat Element.create
as a constructor. Instead, pass your initial values into the constructor.
$set = new Element({"id": 1, "name" : "wrapper"}).
append(new Element({"id" : 3, "name" : "elm A"}));
alert($set.getInfo("name"));
You're not checking for own properties in your loops, omitting {}
, and I spotted at least one implied global. JavaScript will bite you if you're not careful. Consider using JSLint or JSHint to help you spot these problems.
Upvotes: 1
Reputation: 19294
Your create function does not create any object, but rather changes on place the Element. aArguments
object. Any strange thing might follow.
Anyway, just go for a clean and simple prototypal inheritance scheme, do not use $, remember to always declare your vars, and keep things simple :
function Element(initialValues) {
this.id = this.prototype.id++;
this.name = null;
this.type = null;
this.title = null;
this.style = null;
this.action = [];
this.parent = null;
this.children = [];
for (var prop in initialValues)
if (this[prop] != undefined) this[prop] = initialValues[prop];
}
Element.prototype = {
append: function () {
for (var i = 0; i < arguments.length - 1; i++) {
var thisElement = arguments[i];
if (typeof thisElement == "string") this.setChild(this.importDB(thisElement, true));
else this.setChild(thisElement);
}
return this;
},
setChild: function (child) {
this.children.push(child);
return this;
},
getInfo: function (key) {
return this[Key];
},
id: 0
};
Upvotes: 1