0

I was looking for a way to self-reference an object to access it's property when I discover the ES5 getter feature (see. MDN).

I'm working with NPM module and can't access the canvas property.

config.js

import path from "path";
import layout from "./layouts";

const config = {
  canvas: { width: 80, height: 80 },
  layout: {
    get base() {
      console.log(this);
      console.log(this.canvas);
      return layout.base.bottom(this.canvas);
    },
    get annotation() {
      return layout.annotation.top(this.canvas);
    }
  }
};
export default config;

layouts.js

export default {
  annotation: {
    top: options => ({
      x: options.width / 2,
    })
  },
  base: {
    bottom: options => ({
      x: options.width / 2,
    })
  }
};

Error

{ base: [Getter], annotation: [Getter] }
undefined 
TypeError: Cannot read property 'width' of undefined                                                                                                                                          
    at Object.bottom (/data/projects/hanzi-pinyin-font/src/layouts.js:13:10)                                                                                                                  
    at Object.get base [as base] (/data/projects/hanzi-pinyin-font/src/config.js:17:26)                                                                                                       
    at generateSvg (/data/projects/hanzi-pinyin-font/index.js:15:40)                                                                                                                          
    at /data/projects/hanzi-pinyin-font/index.js:39:5                                                                                                                                         
    at /data/projects/hanzi-pinyin-font/node_modules/jsonfile/index.js:46:5                                                                                                                   

Question

Why isn't this working?

Community
  • 1
  • 1
Édouard Lopez
  • 40,270
  • 28
  • 126
  • 178

3 Answers3

2

You have nested object literals. The inner layout object literal does not know it has a parent so this in your getters for layout refers to config.layout.

You could use object shorthand syntax to make this better.

import path from "path";
import layouts from "./layouts";

const canvas = {
  canvas: { width: 80, height: 80 }
}

const layout = {
  get base() {
    return layouts.base.bottom(canvas);
  },
  get annotation() {
    return layouts.annotation.top(canvas);
  }
}

export default {
  canvas, layout
};
chris
  • 6,653
  • 6
  • 41
  • 54
1

.canvas is not a property of the layout object but of the config one, so you cannot access it using this (which refers to layout, as your log shows). Instead, use

import path from "path";
import layout from "./layouts";

export default const config = {
  canvas: { width: 80, height: 80 },
  layout: {
    get base() {
      return layout.base.bottom(config.canvas);
    },
    get annotation() {
      return layout.annotation.top(config.canvas);
    }
  }
};
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

As explained by @Chris, the this wasn't referencing my top object config, but the parent object layout.

Moving up the getter solve this.

const config = {
  get layout() {
    return {
      base: layout.base.bottom(this.canvas),
      annotation: layout.annotation.top(this.canvas)
    };
  }
}
Édouard Lopez
  • 40,270
  • 28
  • 126
  • 178