Javascript 导出全局匿名对象不会';当我试图要求一个特定的功能时,它不起作用

Javascript 导出全局匿名对象不会';当我试图要求一个特定的功能时,它不起作用,javascript,node.js,Javascript,Node.js,假设我有一个具有这种结构的项目: lib/ api.js thing.js index.js 每个模块的代码如下(在不失去意义的情况下简化) 使用new关键字导出的目的是确保始终返回相同的对象,因为我希望验证一次并保留已验证的api对象 下一个模块调用API发出请求。请注意,我需要api,然后对其调用函数request /* lib/thing.js */ "use strict"; var api = require('./api.js'); var thing = { s

假设我有一个具有这种结构的项目:

lib/
  api.js
  thing.js
index.js
每个模块的代码如下(在不失去意义的情况下简化)

使用
new
关键字导出的目的是确保始终返回相同的对象,因为我希望验证一次并保留已验证的api对象

下一个模块调用API发出请求。请注意,我需要api,然后对其调用函数
request

/* lib/thing.js */
"use strict";

var api = require('./api.js');

var thing = {

  storeThing: function(thingData) {
    return new Promise((resolve, reject) => {
      api.request(thingData).then(result => {
        resolve(result);
      }).catch(error => {
        console.log(error);
      });
    });
  }

};

module.exports = thing;
最后,我有一个入口点,该入口点使用API进行身份验证,然后调用
thing

/* index.js */
"use strict";

var api = require('./lib/api.js');
var libThing = require('./lib/thing.js');
var credentials = {
  username: "test@test.com",
  password: "password"
};

api.authenticate(credentials).then(result => {
  return libThing.storeThing({ id: 1 });
}).then(result => {
  console.log(result);
}).catch(error => {
  console.log(error);
});
这很有效。我可以从项目中的任何地方要求
api.js
,它将按预期工作。但是,如果我尝试在
lib/thing.js
中进行以下更改,则会失败:

 /* lib/thing.js */
"use strict";

var request = require('./api.js').request;

var thing = {

  storeThing: function(thingData) {
    return new Promise((resolve, reject) => {
      request(thingData).then(result => {
        resolve(result);
      }).catch(error => {
        console.log(error);
      });
    });
  }

};

module.exports = thing;
根据我的诊断,返回的
请求
函数有一个
未定义的
,因此显然无法访问任何属性


我觉得这是我应该理解的,但实际上我不明白为什么会这样。如果
require('./api.js')
返回同一个全局对象,那么为什么
require('./api.js')。request
不会返回从该对象派生的函数,我无法理解。这与何时对其求值有关还是与更明显的情况有关?

这是因为您在引用对象属性函数时更改了
上下文


在这种情况下,
这个
绑定到全局对象。

我很想了解这个的细节。在原始代码中调用
api.request
时,此
的上下文由调用该方法的对象确定。为什么在导出对象之外的代码中(即在模块的主要部分中)该上下文会发生更改?因为引擎就是这样处理的。这是一篇很好的文章,很好地解释了这个上下文绑定:非常有趣,谢谢。我还看到,事实上,在严格模式(我正在使用)中,上下文实际上是未定义的。给我一点时间来消化这整篇文章:)我会回来的。我知道这是答案(我已经投票了),但我仍然很难理解为什么在节点模块的上下文中,在对象上调用的函数的上下文不应该是对象本身的上下文。我还没有真正“明白”。但很明显你是对的。@DanielC问题是我还没有很好地理解它,但我理解的是,对象属性只是某个东西的标识符,它们从来没有实际值。现在,由于您完全脱离了它的父对象,scope将永远无法找到在这个对象上绑定什么。我极力推荐这本书
 /* lib/thing.js */
"use strict";

var request = require('./api.js').request;

var thing = {

  storeThing: function(thingData) {
    return new Promise((resolve, reject) => {
      request(thingData).then(result => {
        resolve(result);
      }).catch(error => {
        console.log(error);
      });
    });
  }

};

module.exports = thing;