[英]Node Function Scope
我最近跳入深渊,一直在慢慢学习游泳。 我正在使用CLI构建一个简单的文本游戏世界。 该代码变得一团糟,所以我尝试重新创建下面以更简单形式出现的错误。
尝试尝试,我似乎无法理解构造所有函数的最佳方法。 在我的项目中,我有一个解析器函数,该函数分解输入并搜索通过try / catch块调用的“动词”。 当一个动词(即“ look”)运行时,它访问我的数据库模块并基于几个参数发送查询以返回房间或事物的描述。 因为这都是异步的,所以实际上所有内容都包含在一个Promise中,但是我将其排除在本示例之外。 以下不是实际的项目,只是我设置对象的一种简单方式。
APP:
// ***********************
const player = require('./scope_test_player');
player.look();
player.water();
模块1:
// ***********************
const apple_tree = require('./scope_test_apple_tree');
module.exports = {
look: function(){
console.log(
'The apple tree is '+apple_tree.height+'ft tall and has '
+apple_tree.apples+' apples growing on it'
);
},
water: function() {
apple_tree.grow();
}
};
模块2:
// ***********************
const player = require('./scope_test_player');
module.exports = {
height: 10,
nutrition: 0.3,
apples: [],
fertilize: function(number) {
this.nutrition+=number;
},
grow: function() {
this.height+=this.nutrition;
}
};
在上面的代码中,我从水中得到“ TypeError:apple_tree.grow不是一个函数”,或者从外观中未得到定义。 这是我生存的祸根,在我的主要项目中,我似乎一直在随意获取它,这使我相信我不了解范围。 我知道我可以在函数中要求该模块,并且该模块可以工作,但这很丑陋,最后会增加数百行代码。 如何从其他对象中干净地访问对象的功能?
您的问题是项目中具有循环依赖性,并且您覆盖了模块的exports
属性。 因此,节点将缓存所需模块的方式,您将在scope_test_player
文件中获得原始module.exports
对象,而不是被覆盖的对象。 为了解决这个问题,您需要这样写:
// ***********************
const apple_tree = require('./scope_test_apple_tree');
module.exports.look = function() {
console.log(
'The apple tree is ' + apple_tree.height + 'ft tall and has ' + apple_tree.apples + ' apples growing on it'
);
};
module.exports.water = function() {
apple_tree.grow();
};
和
// ***********************
const player = require('./scope_test_player');
module.exports.height = 10;
module.exports.nutrition = 10;
module.exports.apples = [];
module.exports.fertilize = function(number) {
this.nutrition = +number;
};
module.exports.growth = function() {
this.height = +this.nutrition;
}
但这对于Gerenal来说确实是一个糟糕的设计,您应该找到另一种解决方法。 您应始终避免在依赖关系树中出现循环/圆。
UPDATE
在节点中,每个文件都以这种方式包装到装入函数中:
function moduleLoaderFunction( module, exports /* some other paramteres that are not relavant here*/)
{
// the original code of your file
}
node.js在内部需要执行以下操作:
var loadedModules = {}
function require(moduleOrFile) {
var resolvedPath = getResolvedPath(moduleOrFile)
if( !loadedModules[resolvedPath] ) {
// if the file was not loaded already create and antry in the loaded modules object
loadedModules[resolvedPath] = {
exports : {}
}
// call the laoded function with the initial values
moduleLoaderFunction(loadedModules[resolvedPath], loadedModules[resolvedPath].exports)
}
return loadedModules[resolvedPath].exports
}
由于周期性的需求, require
函数将返回原始的cache[resolvedPath].exports
,它是在将自己的对象赋给它之前最初设置的。
是Module1 = scope_test_player和Module2 = scope_test_apple_tree吗? 也许您在这里有循环参考?
APP需要scope_test_player
//循环
scope_test_player需要scope_test_apple_tree
scope_test_apple_tree需要scope_test_player
//循环
如我所见,scope_test_apple_tree不使用播放器。
您可以尝试删除:
const player = require('./scope_test_player');
来自Module2吗?
有几个问题要解决。
删除模块2( scope_test_apple_tree.js
)中的播放器要求:
const player = require('./scope_test_player')
将其保留在此处不会造成任何损害,但这只是不必要的。
另外,在我的fertilize
和grow
,用+=
代替=+
,这就是我认为的目标。
我能够使用这些修复程序自然地运行代码。
如果您想重构,我可能会整理需求文件,并在控制播放器动作的主文件中进行处理,并使用运行它所需的内容(在本例中为树)显式命名函数。
基本上保持您的编码约定,我的轻微重构看起来像:
const player = require('./scope_test_player');
const apple_tree = require('./scope_test_apple_tree');
player.lookAtTree(apple_tree);
player.waterTree(apple_tree);
module.exports = {
lookAtTree: function(tree){
console.log(
'The apple tree is '+tree.height+'ft tall and has '
+tree.apples.length+' apples growing on it'
);
},
waterTree: function(tree) {
tree.grow();
console.log('The apple tree grew to', tree.height, 'in height')
}
};
module.exports = {
height: 10,
nutrition: 0.3,
apples: [],
fertilize: function(number) {
this.nutrition += number;
},
grow: function() {
this.height += this.nutrition;
}
};
是的,我的代码中有循环依赖项,因为我没有意识到它们带来的危险。 当我从主项目中删除它们时,请确保它又可以开始工作了。 现在看来,我将不得不重新设计该项目,因为具有两个彼此随机引用的模块会引起更多问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.