Home > Enterprise >  access object from object nested function with this keyword
access object from object nested function with this keyword

Time:04-05

I have this object:

popup_data = {
    club: {
        type: 'club',
        type_img: {
            header: 'CLUB HEADER',
            img: 'https://source.unsplash.com/random/800x600',
            sub_header: 'CLUB SUB HEADER',
            content: 'TEXT',
            hotspot_position: [5, -1.5, 2.5]
        },
        hotspots_array: [
            {   id: () => this.club.type   '-'   'type_img',
                position: () => this.club.type_img.hotspot_position,
            },
        ]   
    },

How to get type and type_img.hotspot_position from these nested functions

CodePudding user response:

just use the var name, popup_data

popup_data = {
    club: {
        type: 'club',
        type_img: {
            header: 'CLUB HEADER',
            img: 'https://source.unsplash.com/random/800x600',
            sub_header: 'CLUB SUB HEADER',
            content: 'TEXT',
            hotspot_position: [5, -1.5, 2.5]
        },
        hotspots_array: [
            {   id: () => popup_data.club.type   '-'   'type_img',
                position: () => popup_data.club.type_img.hotspot_position,
            },
        ]   
    },

Read This and This

What is this?
In JavaScript, the this keyword refers to an object.

Which object depends on how this is being invoked (used or called).

The this keyword refers to different objects depending on how it is used:

In an object method, this refers to the object.
Alone, this refers to the global object.
In a function, this refers to the global object.
In a function, in strict mode, this is undefined.
In an event, this refers to the element that received the event.
Methods like call(), apply(), and bind() can refer this to any object.

CodePudding user response:

You can access it by the variable name that you assign the entire object into.

popup_data = {
    club: {
        type: 'club',
        type_img: {
            header: 'CLUB HEADER',
            img: 'https://source.unsplash.com/random/800x600',
            sub_header: 'CLUB SUB HEADER',
            content: 'TEXT',
            hotspot_position: [5, -1.5, 2.5]
        },
        hotspots_array: [
            {   id: () => popup_data.club.type   '-'   'type_img',
                position: () => popup_data.club.type_img.hotspot_position,
            },
        ]   
    },

Since you are using ES6 arrow function, this will not work at all. And if you used normal function, this would be the object inside hotspots_array, not the entire object.

CodePudding user response:

If you have more than one item, and want all those items to have access to the root, you can bind the function. You will need to use none arrow functions here, as they don't have a this..

You can even extract your id and position function out of the object too, so that your not creating multiple instances of the exact same function.

eg..

function id() {
  return this.club.type   '-'   'type_img';
}

function position() {
  return this.club.type_img.hotspot_position;
}


const popup_data = {
  club: {
    type: 'club',
    type_img: {
       header: 'CLUB HEADER',
       img: 'https://source.unsplash.com/random/800x600',
       sub_header: 'CLUB SUB HEADER',
       content: 'TEXT',
       hotspot_position: [5, -1.5, 2.5]
    },
    hotspots_array: [
       {   
         name: 'test',
         id, position
       }, {
         name: 'test2',
         id, position
       }
    ]   
   }  
};

const popup_data_2 = {
  club: {
    type: 'this is club 2',
    type_img: {
       hotspot_position: [5, -1.5, 2.5]
    },
    hotspots_array: [
       {   
         id, position
       }
    ]   
   }  
};
 
function bindFunctions(r, a) {
  Object.entries(a).map(([k, v]) => {
    const tp = typeof v;
    if (tp === 'function') {
       a[k] = v.bind(r);
    } else if (tp === 'object') {
       bindFunctions(r, v);
    }
  });
}
 
 bindFunctions(popup_data, popup_data);
 bindFunctions(popup_data_2, popup_data_2);
 
 console.log(popup_data.club.hotspots_array[0].id());
 console.log(popup_data.club.hotspots_array[0].position());
 console.log(popup_data_2.club.hotspots_array[0].id());

Another option, having a single root item can be restrictive. If you wanted something more fancy I would create your Object using a function and use the power of closures. The example below I've added another prop that then has access to it's array.

function makeObject(data) {
    const root = data;
    for (const h of data.club.hotspots_array) {
       //now lets add our functions
       h.id = () => root.club.type   '-'   'type_img';
       h.position = () => root.club.type_img.hotspot_position;
       h.array = data.club.hotspots_array;
    }
    return root;
 }
 
 const o1 = makeObject({
 club: {
    type: 'club',
    type_img: {
       header: 'CLUB HEADER',
       img: 'https://source.unsplash.com/random/800x600',
       sub_header: 'CLUB SUB HEADER',
       content: 'TEXT',
       hotspot_position: [5, -1.5, 2.5]
    },
    hotspots_array: [
       {   
         name: 'test',
       }, {
         name: 'test2',
       }
    ]   
   }
 });
 
 console.log(o1.club.hotspots_array[0].id());
 console.log(o1.club.hotspots_array[0].position());
 console.log('array:'   o1.club.hotspots_array[0].array.length);

  • Related