You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建JavaScript environment对象时,如何访问同一对象内已定义属性?

解决JavaScript对象字面量中访问自身属性的问题

我想要创建如下的environment对象:

export const environment = {
  production: false,
  hmr : false,
  api: {
    auth: {
      protocol: 'http',
      host: 'localhost',
      port: '8083',
      api_path: 'api',
      version: {
        path: 'v',
        major: 1,
        minor: 0,
        patch: 0,
      },
      url: this.api.auth.protocol + '://' + this.api.auth.host + ':' + this.api.auth.port,
      controllers: {
        auth: {
          service_name: 'auth',
          base_url: this.api.auth.url + '/' + this.api.auth.controllers.auth.service_name + '/' + this.api.auth.api_path + '/' + this.api.auth.version.path + '/' + this.api.auth.version.major + '.' + this.api.auth.version.minor + '.' + this.api.auth.version.patch + '/',
          refresh_token_url: this.api.auth.controllers.auth.base_url + '/refresh_token',
          login_url: this.api.auth.controllers.auth.base_url + '/login',
          logout_url: this.api.auth.controllers.auth.base_url + '/logout'
        }
      }
    }
  }
};

我希望在同一对象中访问已赋值的属性,例如在api.auth.url中通过this.api.auth.protocol访问api.auth.protocol,拼接出http://localhost:8083这类URL。但当前写法无法访问,编译后报错:“Uncaught TypeError: Cannot read property 'api' of undefined”。我是开发新手,请问如何解决该问题?


为啥你的代码会报错?

在你写的这种对象字面量({ ... }结构)里,this并不会指向正在创建的environment对象哦!它的指向取决于当前代码的运行上下文(比如浏览器里默认是window,严格模式下是undefined),自然找不到this.api,所以才会报错。

几种适合新手的解决方法

方法1:先创建基础对象,再补全依赖属性

先把不需要依赖其他属性的部分写好,再逐步添加那些需要拼接的属性,这样就能直接访问已经存在的属性了:

export const environment = {
  production: false,
  hmr : false,
  api: {
    auth: {
      protocol: 'http',
      host: 'localhost',
      port: '8083',
      api_path: 'api',
      version: {
        path: 'v',
        major: 1,
        minor: 0,
        patch: 0,
      },
    }
  }
};

// 补全url属性,用模板字符串拼接更清爽
environment.api.auth.url = `${environment.api.auth.protocol}://${environment.api.auth.host}:${environment.api.auth.port}`;

// 补全控制器相关属性
environment.api.auth.controllers = {
  auth: {
    service_name: 'auth',
    base_url: `${environment.api.auth.url}/${environment.api.auth.controllers.auth.service_name}/${environment.api.auth.api_path}/${environment.api.auth.version.path}/${environment.api.auth.version.major}.${environment.api.auth.version.minor}.${environment.api.auth.version.patch}/`,
    refresh_token_url: `${environment.api.auth.controllers.auth.base_url}/refresh_token`,
    login_url: `${environment.api.auth.controllers.auth.base_url}/login`,
    logout_url: `${environment.api.auth.controllers.auth.base_url}/logout`
  }
};

方法2:提前定义变量,再构建对象

把需要复用的属性先提取成单独变量,最后再把这些变量组装成对象,这种方式逻辑最清晰,完全不用纠结this的指向问题,新手友好度拉满:

// 先把所有基础配置拆成变量
const protocol = 'http';
const host = 'localhost';
const port = '8083';
const apiPath = 'api';
const version = {
  path: 'v',
  major: 1,
  minor: 0,
  patch: 0,
};
const serviceName = 'auth';

// 提前计算好需要拼接的URL
const authBaseUrl = `${protocol}://${host}:${port}`;
const authControllerBaseUrl = `${authBaseUrl}/${serviceName}/${apiPath}/${version.path}/${version.major}.${version.minor}.${version.patch}/`;

// 最后组装成完整对象
export const environment = {
  production: false,
  hmr : false,
  api: {
    auth: {
      protocol,
      host,
      port,
      api_path: apiPath,
      version,
      url: authBaseUrl,
      controllers: {
        auth: {
          service_name: serviceName,
          base_url: authControllerBaseUrl,
          refresh_token_url: `${authControllerBaseUrl}/refresh_token`,
          login_url: `${authControllerBaseUrl}/login`,
          logout_url: `${authControllerBaseUrl}/logout`
        }
      }
    }
  }
};

我个人最推荐这种写法,后续修改配置或者排查问题都特别方便。

方法3:用getter函数动态计算属性

如果想把所有代码放在一个对象字面量里,可以用get关键字定义getter属性,每次访问这个属性时会自动计算结果:

export const environment = {
  production: false,
  hmr : false,
  api: {
    auth: {
      protocol: 'http',
      host: 'localhost',
      port: '8083',
      api_path: 'api',
      version: {
        path: 'v',
        major: 1,
        minor: 0,
        patch: 0,
      },
      // 用getter定义url,这里的this指向api.auth
      get url() {
        return `${this.protocol}://${this.host}:${this.port}`;
      },
      controllers: {
        auth: {
          service_name: 'auth',
          // 这里的this指向controllers.auth,需要手动关联上层对象
          get base_url() {
            const auth = environment.api.auth;
            return `${auth.url}/${this.service_name}/${auth.api_path}/${auth.version.path}/${auth.version.major}.${auth.version.minor}.${auth.version.patch}/`;
          },
          get refresh_token_url() {
            return `${this.base_url}/refresh_token`;
          },
          get login_url() {
            return `${this.base_url}/login`;
          },
          get logout_url() {
            return `${this.base_url}/logout`;
          }
        }
      }
    }
  }
};

这种方法的好处是,如果后续修改了protocol或host,url会自动更新,但要注意每次访问getter属性都会重新计算哦。

内容的提问来源于stack exchange,提问作者Asaduzzaman Noor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:32:04