How can I refer to a key during object creation in Javascript? - javascript

I am trying to create an object with selectors inside. The first one is the context selector which I want to use within the object itself. How can I reference this key within the object?
var options = {
elements: {
"context": $('form#someForm'),
"someDropdown" : $("#someDropDown", this.context),
"someContainer" : $('div#someContainer', this.context),
},
constants: {
buttonImageLocation : 'image.jpg'
}
};
Thanks

JavaScript creates for every function a new scope, not for every block. So in your case this refers to the window and since the window has no context, it is undefined. You could do something like:
var options = {
element: new (function() {
this.context = $('form#someForm');
this.someDropdown = $("#someDropDown", this.context);
...
return this;
})()
}

Related

jQuery: use dynamic object based on variable value

I have several objects and all of them have some methods that are called the same but do different things.
When I click a button, I want to call the init() method, but the
object is different based on what button I clicked.
Here is a snippet
$btn.on('click', function(e){
e.preventDefault();
var $trigger = $(this);
var objectName = $trigger.data('object');
/*
if objectName is 'user', I want to call user.init(),
if it's 'product' I want to call product.init() and so on...
right now i get an error if I call like his
*/
objectName.init($trigger);
});
Is it possible to dynamically call an object like this ? I know it is for its properties and methods, but I din't find anything about this issue.
Thank you.
It's better to do mapping
var entities = {
user: user,
entity: entity
}
var objectName = $trigger.data('object');
entities[objectName].init($trigger);
In case your objects (or functions) defined in the global scope, you can access them using the window object:
var funcT = function() {
console.log('funcT was called');
}
var objT = {
'a': 1,
'b': 2
}
function a() {
var funcName = 'funcT'
window[funcName]();
var objName = 'objT'
console.log(window[objName]);
}
a()
With window[variable] you can access variables based on another variable.
So all that you need to do is to replace objectName.init($tr‌​igger); with: window[objectName].‌​init();

Javascript: get parent object key name from within child [duplicate]

This question already has answers here:
access parent object in javascript
(15 answers)
Closed 5 years ago.
I have the following (nested) object:
obj: { subObj: { foo: 'hello world' } };
Next thing I do is to reference the subobject like this:
var s = obj.subObj;
Now what I would like to do is to get a reference to the object obj out of the variable s.
Something like:
var o = s.parent;
Is this somehow possible?
A nested object (child) inside another object (parent) cannot get data directly from its parent.
Have a look on this:
var main = {
name : "main object",
child : {
name : "child object"
}
};
If you ask the main object what its child name is (main.child.name) you will get it.
Instead you cannot do it vice versa because the child doesn't know who its parent is.
(You can get main.name but you won't get main.child.parent.name).
By the way, a function could be useful to solve this clue.
Let's extend the code above:
var main = {
name : "main object",
child : {
name : "child object"
},
init : function() {
this.child.parent = this;
delete this.init;
return this;
}
}.init();
Inside the init function you can get the parent object simply calling this.
So we define the parent property directly inside the child object.
Then (optionally) we can remove the init method.
Finally we give the main object back as output from the init function.
If you try to get main.child.parent.name now you will get it right.
It is a little bit tricky but it works fine.
No. There is no way of knowing which object it came from.
s and obj.subObj both simply have references to the same object.
You could also do:
var obj = { subObj: {foo: 'hello world'} };
var obj2 = {};
obj2.subObj = obj.subObj;
var s = obj.subObj;
You now have three references, obj.subObj, obj2.subObj, and s, to the same object. None of them is special.
This is an old question but as I came across it looking for an answer I thought I will add my answer to this to help others as soon as they got the same problem.
I have a structure like this:
var structure = {
"root":{
"name":"Main Level",
nodes:{
"node1":{
"name":"Node 1"
},
"node2":{
"name":"Node 2"
},
"node3":{
"name":"Node 3"
}
}
}
}
Currently, by referencing one of the sub nodes I don't know how to get the parent node with it's name value "Main Level".
Now I introduce a recursive function that travels the structure and adds a parent attribute to each node object and fills it with its parent like so.
var setParent = function(o){
if(o.nodes != undefined){
for(n in o.nodes){
o.nodes[n].parent = o;
setParent(o.nodes[n]);
}
}
}
Then I just call that function and can now get the parent of the current node in this object tree.
setParent(structure.root);
If I now have a reference to the seconds sub node of root, I can just call.
var node2 = structure.root.nodes["node2"];
console.log(node2.parent.name);
and it will output "Main Level".
Hope this helps..
Many of the answers here involve looping through an object and "manually" (albeit programmatically) creating a parent property that stores the reference to the parent. The two ways of implementing this seem to be...
Use an init function to loop through at the time the nested object is created, or...
Supply the nested object to a function that fills out the parent property
Both approaches have the same issue...
How do you maintain parents as the nested object grows/changes??
If I add a new sub-sub-object, how does it get its parent property filled? If you're (1) using an init function, the initialization is already done and over, so you'd have to (2) pass the object through a function to search for new children and add the appropriate parent property.
Using ES6 Proxy to add parent whenever an object/sub-object is set
The approach below is to create a handler for a proxy always adds a parent property each time an object is set. I've called this handler the parenter handler. The parenter responsibilities are to recognize when an object is being set and then to...
Create a dummy proxy with the appropriate parent and the parenter handler
var p = new Proxy({parent: target}, parenter);
Copy in the supplied objects properties-- Because you're setting the proxy properties in this loop the parenter handler is working recursively; nested objects are given parents at each level
for(key in value){
p[key] = value[key];
}
Set the proxy not the supplied object
return target[prop] = p;
Full code
var parenter = {
set: function(target, prop, value){
if(typeof value === "object"){
var p = new Proxy({parent: target}, parenter);
for(key in value){
p[key] = value[key];
}
return target[prop] = p;
}else{
target[prop] = value;
}
}
}
var root = new Proxy({}, parenter);
// some examples
root.child1 = {
color: "red",
value: 10,
otherObj: {
otherColor: "blue",
otherValue: 20
}
}
// parents exist/behave as expected
console.log(root.child1.color) // "red"
console.log(root.child1.otherObj.parent.color) // "red"
// new children automatically have correct parent
root.child2 = {color: "green", value3: 50};
console.log(root.child2.parent.child1.color) // "red"
// changes are detected throughout
root.child1.color = "yellow"
console.log(root.child2.parent.child1.color) // "yellow"
Notice that all root children always have parent properties, even children that are added later.
There is a more 'smooth' solution for this :)
var Foo = function(){
this.par = 3;
this.sub = new(function(t){ //using virtual function to create sub object and pass parent object via 't'
this.p = t;
this.subFunction = function(){
alert(this.p.par);
}
})(this);
}
var myObj = new Foo();
myObj.sub.subFunction() // will popup 3;
myObj.par = 5;
myObj.sub.subFunction() // will popup 5;
To further iterate on Mik's answer, you could also recursivey attach a parent to all nested objects.
var myApp = {
init: function() {
for (var i in this) {
if (typeof this[i] == 'object') {
this[i].init = this.init;
this[i].init();
this[i].parent = this;
}
}
return this;
},
obj1: {
obj2: {
notify: function() {
console.log(this.parent.parent.obj3.msg);
}
}
},
obj3: {
msg: 'Hello'
}
}.init();
myApp.obj1.obj2.notify();
http://jsbin.com/zupepelaciya/1/watch?js,console
You could try this(this uses a constructor, but I'm sure you can change it around a bit):
function Obj() {
this.subObj = {
// code
}
this.subObj.parent = this;
}
I have been working on a solution to finding the parent object of the current object for my own pet project. Adding a reference to the parent object within the current object creates a cyclic relationship between the two objects.
Consider -
var obj = {
innerObj: {},
setParent: function(){
this.innerObj.parent = this;
}
};
obj.setParent();
The variable obj will now look like this -
obj.innerObj.parent.innerObj.parent.innerObj...
This is not good. The only solution that I have found so far is to create a function which iterates over all the properties of the outermost Object until a match is found for the current Object and then that Object is returned.
Example -
var obj = {
innerObj: {
innerInnerObj: {}
}
};
var o = obj.innerObj.innerInnerObj,
found = false;
var getParent = function (currObj, parObj) {
for(var x in parObj){
if(parObj.hasOwnProperty(x)){
if(parObj[x] === currObj){
found = parObj;
}else if(typeof parObj[x] === 'object'){
getParent(currObj, parObj[x]);
}
}
}
return found;
};
var res = getParent(o, obj); // res = obj.innerObj
Of course, without knowing or having a reference to the outermost object, there is no way to do this. This is not a practical nor is it an efficient solution. I am going to continue to work on this and hopefully find a good answer for this problem.
Try this until a non-no answer appears:
function parent() {
this.child;
interestingProperty = "5";
...
}
function child() {
this.parent;
...
}
a = new parent();
a.child = new child();
a.child.parent = a; // this gives the child a reference to its parent
alert(a.interestingProperty+" === "+a.child.parent.interestingProperty);
You will need the child to store the parents this variable. As the Parent is the only object that has access to it's this variable it will also need a function that places the this variable into the child's that variable, something like this.
var Parent = {
Child : {
that : {},
},
init : function(){
this.Child.that = this;
}
}
To test this out try to run this in Firefox's Scratchpad, it worked for me.
var Parent = {
data : "Parent Data",
Child : {
that : {},
data : "Child Data",
display : function(){
console.log(this.data);
console.log(this.that.data);
}
},
init : function(){
this.Child.that = this;
}
}
Parent.init();
Parent.Child.display();
Just in keeping the parent value in child attribute
var Foo = function(){
this.val= 4;
this.test={};
this.test.val=6;
this.test.par=this;
}
var myObj = new Foo();
alert(myObj.val);
alert(myObj.test.val);
alert(myObj.test.par.val);
when I load in a json object I usually setup the relationships by iterating through the object arrays like this:
for (var i = 0; i < some.json.objectarray.length; i++) {
var p = some.json.objectarray[i];
for (var j = 0; j < p.somechildarray.length; j++) {
p.somechildarray[j].parent = p;
}
}
then you can access the parent object of some object in the somechildarray by using .parent

Working with JavaScript prototypes and accessing base class fields.

I am new to pseudo classes and prototypes in JavaScript and I am having a bit of difficulty implementing it properly. What I am trying to do is have a base 'class' with some fields then create a prototype of that base class with my methods defined as object literals. I am torn between doing it this way and just using singletons inside my base class for my methods. I think though that doing it this way is a little more elegant and I think I am actually not creating every method every time I create a new object.
Anyways, the small issue I am having is referencing the fields of my base class in my methods. Because when I try to reference them as this.field this is referring to the current function/ scope but I want it to reference the newly create object. Is there a work around for this or should I change the way I am creating my methods.
Below is some code that I think will make it more clear what I am doing and the problem I am having.
function BaseClass() {
this.items[];
this.fieldOne = "asdasd";
}
BaseClass.prototype = {
methodOne: function (input) {
function addElement(a. b) {
var element = {};
element.prop1 = a;
element.prop2 = b;
//The issue I am having is that items is undefined, how can I refernce the parent class object.
this.items.push(element);
}
function traverse() {
//go through a list and add a bunch of elements
addElement("ASdasd", 324);
}
},
methodTwo: function () {
//see now fieldOne is asdasd
console.log("fieldOne" + fieldOne);
}
}
var forTest = new BaseClass();
forTest.methodTwo();
So yeah I want to have some fields in the parent class that I can access from any method, but I would rather not just put the functions in my base class so that I do not create every method everytime I create a new object from BaseClass. Is there a work around or a better way to implement this?
Thanks in advance for the help.
You're losing the reference to this inside your nested functions. You can solve that with:
methodOne: function (input) {
var self = this;
function addElement(a. b) {
var element = {};
element.prop1 = a;
element.prop2 = b;
//The issue I am having is that items is undefined, how can I refernce the parent class object.
self.items.push(element);
}
function traverse() {
//go through a list and add a bunch of elements
addElement("ASdasd", 324);
}
// You never called anything?
// is traverse() what you wanted?
traverse();
},
methodOne: function (input) {
function addElement(a. b) {
var element = {};
element.prop1 = a;
element.prop2 = b;
//The issue I am having is that items is undefined, how can I refernce the parent class object.
this.items.push(element);
}
The issue here is that you've encountered javascript design error which is that this in subfunction is bound to wrong object. The ususal workaround for this looks like:
methodOne: function (input) {
var that = this;
function addElement(a, b) {
...
that.items.push(element);
}
}
In fact it's bound to the global object:
var o = {
f : function(){
var g = function(){
this.name = "test";
};
g();
}
};
o.f();
console.log(name); // "test"

Prototype chain - setting key on one object affects a sibling object?

I am working on my first JS project that involves inheritance and the prototype chain, and I am confused about why the creation of one object with specific data is affecting the data already in place on my second object.
The goal is to have a set of basic defaults in the full_params object literal in the "parent" object, and have some more specific defaults in the default_params object literal in the "child" object.
The child object specificRequest takes an array argument for its constructor function, adds those to its default_params, and then call the setOptions function of its prototype to add those to the full_params.
The problem is that when I create one specificRequest object and initialize it, it works fine, but then when I create a second specificRequest object, the full_params is already the same as
that of the first.
This is probably something very simple from a misunderstanding of how prototype works...
/////// PARENT OBJECT
function baseRequest(custom_params) {
var key;
this.full_params = {
"SignatureVersion": "2",
"Timestamp": Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd'T'HH:mm:ss'Z'")
};
this.custom_params = custom_params;
}
baseRequest.prototype.setOptions = function(arg_options) {
var key;
if (typeof arg_options === "object") this.custom_params = arg_options;
// If an object of request options is passed, use that. Otherwise use whatever is already in the custom_params object.
for (key in this.custom_params) {
this.full_params[key] = this.custom_params[key];
}
}
///////// CHILD OBJECT
function specificRequest(mySKUList) {
var i;
this.mySKUList = mySKUList;
this.default_params = {
"Action": "myAction",
"Version": "2011-10-01"
};
for (i = 0; i < this.mySKUList.length; i++) {
var temp_sku = this.mySKUList[i];
var temp_sku_name = "SellerSKUList.SellerSKU." + (i + 1);
this.default_params[temp_sku_name] = temp_sku;
}
this.setOptions(this.default_params);
}
specificRequest.prototype = new baseRequest
///// Function to run
function testfoo() {
var skulist1 = ["AR6100", "AR6102", "WB1234"]
var skulist2 = ["XY9999"]
var req1 = new specificRequest(skulist1);
var req2 = new specificRequest(skulist2);
// Req1 has AR6100, AR6102, and WB1234 as parameters, as expected
// Req2 should only have XY9999, but instead has XY9999, AR6102, and WB1234
}
Well you have tied a concrete instance of the parent class to be the prototype of the child class with this line:
specificRequest.prototype = new baseRequest
Instead, don't instantiate the parent class at all:
specificRequest.prototype = Object.create( baseRequest.prototype );
Also, call super() equivalent when constructing a child instance:
function specificRequest(mySKUList) {
baseRequest.call( this );
...
}
And please start constructor names with UpperCase.

Javascript objects: get parent [duplicate]

This question already has answers here:
access parent object in javascript
(15 answers)
Closed 5 years ago.
I have the following (nested) object:
obj: { subObj: { foo: 'hello world' } };
Next thing I do is to reference the subobject like this:
var s = obj.subObj;
Now what I would like to do is to get a reference to the object obj out of the variable s.
Something like:
var o = s.parent;
Is this somehow possible?
A nested object (child) inside another object (parent) cannot get data directly from its parent.
Have a look on this:
var main = {
name : "main object",
child : {
name : "child object"
}
};
If you ask the main object what its child name is (main.child.name) you will get it.
Instead you cannot do it vice versa because the child doesn't know who its parent is.
(You can get main.name but you won't get main.child.parent.name).
By the way, a function could be useful to solve this clue.
Let's extend the code above:
var main = {
name : "main object",
child : {
name : "child object"
},
init : function() {
this.child.parent = this;
delete this.init;
return this;
}
}.init();
Inside the init function you can get the parent object simply calling this.
So we define the parent property directly inside the child object.
Then (optionally) we can remove the init method.
Finally we give the main object back as output from the init function.
If you try to get main.child.parent.name now you will get it right.
It is a little bit tricky but it works fine.
No. There is no way of knowing which object it came from.
s and obj.subObj both simply have references to the same object.
You could also do:
var obj = { subObj: {foo: 'hello world'} };
var obj2 = {};
obj2.subObj = obj.subObj;
var s = obj.subObj;
You now have three references, obj.subObj, obj2.subObj, and s, to the same object. None of them is special.
This is an old question but as I came across it looking for an answer I thought I will add my answer to this to help others as soon as they got the same problem.
I have a structure like this:
var structure = {
"root":{
"name":"Main Level",
nodes:{
"node1":{
"name":"Node 1"
},
"node2":{
"name":"Node 2"
},
"node3":{
"name":"Node 3"
}
}
}
}
Currently, by referencing one of the sub nodes I don't know how to get the parent node with it's name value "Main Level".
Now I introduce a recursive function that travels the structure and adds a parent attribute to each node object and fills it with its parent like so.
var setParent = function(o){
if(o.nodes != undefined){
for(n in o.nodes){
o.nodes[n].parent = o;
setParent(o.nodes[n]);
}
}
}
Then I just call that function and can now get the parent of the current node in this object tree.
setParent(structure.root);
If I now have a reference to the seconds sub node of root, I can just call.
var node2 = structure.root.nodes["node2"];
console.log(node2.parent.name);
and it will output "Main Level".
Hope this helps..
Many of the answers here involve looping through an object and "manually" (albeit programmatically) creating a parent property that stores the reference to the parent. The two ways of implementing this seem to be...
Use an init function to loop through at the time the nested object is created, or...
Supply the nested object to a function that fills out the parent property
Both approaches have the same issue...
How do you maintain parents as the nested object grows/changes??
If I add a new sub-sub-object, how does it get its parent property filled? If you're (1) using an init function, the initialization is already done and over, so you'd have to (2) pass the object through a function to search for new children and add the appropriate parent property.
Using ES6 Proxy to add parent whenever an object/sub-object is set
The approach below is to create a handler for a proxy always adds a parent property each time an object is set. I've called this handler the parenter handler. The parenter responsibilities are to recognize when an object is being set and then to...
Create a dummy proxy with the appropriate parent and the parenter handler
var p = new Proxy({parent: target}, parenter);
Copy in the supplied objects properties-- Because you're setting the proxy properties in this loop the parenter handler is working recursively; nested objects are given parents at each level
for(key in value){
p[key] = value[key];
}
Set the proxy not the supplied object
return target[prop] = p;
Full code
var parenter = {
set: function(target, prop, value){
if(typeof value === "object"){
var p = new Proxy({parent: target}, parenter);
for(key in value){
p[key] = value[key];
}
return target[prop] = p;
}else{
target[prop] = value;
}
}
}
var root = new Proxy({}, parenter);
// some examples
root.child1 = {
color: "red",
value: 10,
otherObj: {
otherColor: "blue",
otherValue: 20
}
}
// parents exist/behave as expected
console.log(root.child1.color) // "red"
console.log(root.child1.otherObj.parent.color) // "red"
// new children automatically have correct parent
root.child2 = {color: "green", value3: 50};
console.log(root.child2.parent.child1.color) // "red"
// changes are detected throughout
root.child1.color = "yellow"
console.log(root.child2.parent.child1.color) // "yellow"
Notice that all root children always have parent properties, even children that are added later.
There is a more 'smooth' solution for this :)
var Foo = function(){
this.par = 3;
this.sub = new(function(t){ //using virtual function to create sub object and pass parent object via 't'
this.p = t;
this.subFunction = function(){
alert(this.p.par);
}
})(this);
}
var myObj = new Foo();
myObj.sub.subFunction() // will popup 3;
myObj.par = 5;
myObj.sub.subFunction() // will popup 5;
To further iterate on Mik's answer, you could also recursivey attach a parent to all nested objects.
var myApp = {
init: function() {
for (var i in this) {
if (typeof this[i] == 'object') {
this[i].init = this.init;
this[i].init();
this[i].parent = this;
}
}
return this;
},
obj1: {
obj2: {
notify: function() {
console.log(this.parent.parent.obj3.msg);
}
}
},
obj3: {
msg: 'Hello'
}
}.init();
myApp.obj1.obj2.notify();
http://jsbin.com/zupepelaciya/1/watch?js,console
You could try this(this uses a constructor, but I'm sure you can change it around a bit):
function Obj() {
this.subObj = {
// code
}
this.subObj.parent = this;
}
I have been working on a solution to finding the parent object of the current object for my own pet project. Adding a reference to the parent object within the current object creates a cyclic relationship between the two objects.
Consider -
var obj = {
innerObj: {},
setParent: function(){
this.innerObj.parent = this;
}
};
obj.setParent();
The variable obj will now look like this -
obj.innerObj.parent.innerObj.parent.innerObj...
This is not good. The only solution that I have found so far is to create a function which iterates over all the properties of the outermost Object until a match is found for the current Object and then that Object is returned.
Example -
var obj = {
innerObj: {
innerInnerObj: {}
}
};
var o = obj.innerObj.innerInnerObj,
found = false;
var getParent = function (currObj, parObj) {
for(var x in parObj){
if(parObj.hasOwnProperty(x)){
if(parObj[x] === currObj){
found = parObj;
}else if(typeof parObj[x] === 'object'){
getParent(currObj, parObj[x]);
}
}
}
return found;
};
var res = getParent(o, obj); // res = obj.innerObj
Of course, without knowing or having a reference to the outermost object, there is no way to do this. This is not a practical nor is it an efficient solution. I am going to continue to work on this and hopefully find a good answer for this problem.
Try this until a non-no answer appears:
function parent() {
this.child;
interestingProperty = "5";
...
}
function child() {
this.parent;
...
}
a = new parent();
a.child = new child();
a.child.parent = a; // this gives the child a reference to its parent
alert(a.interestingProperty+" === "+a.child.parent.interestingProperty);
You will need the child to store the parents this variable. As the Parent is the only object that has access to it's this variable it will also need a function that places the this variable into the child's that variable, something like this.
var Parent = {
Child : {
that : {},
},
init : function(){
this.Child.that = this;
}
}
To test this out try to run this in Firefox's Scratchpad, it worked for me.
var Parent = {
data : "Parent Data",
Child : {
that : {},
data : "Child Data",
display : function(){
console.log(this.data);
console.log(this.that.data);
}
},
init : function(){
this.Child.that = this;
}
}
Parent.init();
Parent.Child.display();
Just in keeping the parent value in child attribute
var Foo = function(){
this.val= 4;
this.test={};
this.test.val=6;
this.test.par=this;
}
var myObj = new Foo();
alert(myObj.val);
alert(myObj.test.val);
alert(myObj.test.par.val);
when I load in a json object I usually setup the relationships by iterating through the object arrays like this:
for (var i = 0; i < some.json.objectarray.length; i++) {
var p = some.json.objectarray[i];
for (var j = 0; j < p.somechildarray.length; j++) {
p.somechildarray[j].parent = p;
}
}
then you can access the parent object of some object in the somechildarray by using .parent

Categories