简体   繁体   中英

'this' inside nested objects (JavaScript)

I would like to have some object structure like this (which I know that's not possible)

const AUTH = {
    base: 'auth',
    login: {
        enter: `${AUTH.base}/login`,
        password: `${AUTH.base}/login/password`,
    },
}

EDIT: I also want to export the object as a module

So I did some experiences

Experience A

 const AUTH_BASE = 'auth' const AUTH_A = { login: { enter: `${AUTH_BASE}/login`, password: `${AUTH_BASE}/login/password`, } } console.log('enter ->', AUTH_A.login.enter) console.log('recover ->', AUTH_A.login.password)

Experience A output:

enter -> auth/login
recover -> auth/login/password

Experience B

 const AUTH_B = { base: 'auth', login() { return `${this.base}/login` }, password() { return `${this.base}/login/password` }, } console.log('enter ->', AUTH_B.login()) console.log('recover ->', AUTH_B.password())

Experience B output:

enter -> auth/login
recover -> auth/login/password

Experience C

 const AUTH_C = { base1: 'auth', login: { base2: 'auth????????????????', enter1: function() { return `${this.base1}/login` }, enter2: function() { return `${this.base2}/login` }, password: function() { return `${this.base}/login/password` }, } } console.log('enter 1 ->', AUTH_C.login.enter1()) console.log('enter 2 ->', AUTH_C.login.enter2()) console.log('recover ->', AUTH_C.login.password())

Experience C output:

enter 1 -> undefined/login
enter 2 -> auth????????????????/login
recover -> undefined/login/password

Experience D

 const AUTH_D = { base: 'auth', login: {}, } AUTH_D.login = { enter: `${AUTH_D.base}/login`, password: `${AUTH_D.base}/login/password`, } console.log('enter ->', AUTH_D.login.enter) console.log('recover ->', AUTH_D.login.password)

Experience D output:

enter -> auth/login
recover -> auth/login/password

My question is: there is any better way to achieve my desired syntax?

repl.it link: https://repl.it/@SandroMiguel/Endpoints-constants-experience

You could use a static class like this :

class Auth {
  static base = 'auth'
  static login = {
    enter: `${Auth.base}/login`
  }
}

Or use getters to self-references the object

const AUTH = {
  base: 'auth',
  get login() {
    return {
      enter: `${AUTH.base}/login`,
      password: `${AUTH.base}/login/password`
    }
  }
}

So you can access your properties like any others props :

console.log(AUTH.login.enter)
console.log(AUTH.login.password)

In comment i'm talking about this :

function authFactory(base){
    this.base = base;
    this.login = {
        enter: `${base}/login`,
        password: `${base}/login/password`
    }
}

const AUTH_E = new authFactory("auth");
console.log('enter E ->', AUTH_E.login.enter);
console.log('recover E ->', AUTH_E.login.password);

The best method to achieve what you want is this

 const AUTH_B = { base: 'auth', login() { return `${this.base}/login` }, password() { return `${this.base}/login/password` }, } Object.freeze(AUTH_B); AUTH_B.base = "something_else"; console.log(AUTH_B.login())

Because the object property is now frozen inside and cannot be edited from outside and will not affect others.
To export this as a module create a file named module.js and paste this inside

const AUTH_B = {
    base: 'auth',
    login() {
        return `${this.base}/login`
    },
    password() {
        return `${this.base}/login/password`
    },
}
Object.freeze(AUTH_B);
AUTH_B.base = "something_else";

exports.AUTH_B = AUTH_B; // export your object like this

Now open your index.js and do

var m = require('./module.js'); // access it like m.AUTH_B
console.log(m.AUTH_B.login()); // gives -> auth/login

Example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM