为什么JavaScript中的子对象会失去全局范围?
我努力遵循Douglas Crockford的“JavaScript:The Good Parts”的建议和他的网站:
应尽量减少全局变量的使用。 隐含的全局变量决不应该被使用。
为此,我定义了一个“根”对象,它充当所有其他对象的容器,现在所有东西都被安排到共享功能的逻辑层次结构中。
我陷入困境的地方是儿童对象似乎失去了全球对象的范围。 我能想到的最好的例子就是我的记录器,我想将其全局定义为root.log ,并在其他地方重复使用它。
但是,当我尝试访问子对象内的root.log时,我的代码失败了,因为它无法再看到对根对象的任何引用。 我将子对象移出到全局范围,它再次看到一切正常。
我已经看到Stack Overflow上的其他帖子提供了父/子对象通信的解决方案,通过显式地将父引用向前传递给子进程,但这并不是我在这里之后所实现的。 我希望能够从任何角度访问根目录,如果我有三四个级别,我不想处理跟踪链。
一个明确的例子可能是,如果我深入了解我的实用程序层次结构并想记录消息。 假设我在root.util.array.getPositionInArray(),并且已经将父值传递给每个子对象。 我不想调用parent.parent.parent.log.write ,我只想对root.log.write进行一次简单的调用。
我可以在创建时将根对象和父对象引用传递给每个子对象,也可以尝试一些继承原则,看看我能否以这种方式实现它。
我的问题如下:
为什么当我在另一个对象中定义的对象时,全局范围“消失”了?
有没有一种简单的方法可以从子对象中访问该全局变量?
(也许是2的副本)建议如何处理这个问题?
我的示例代码如下(在这里它被加载到jsfiddle中)
// declare root object as global variable
var root = null;
$(document).ready(function() {
// instantiate root
root = new Foo();
// uncomment to instantiate child separately
// child = new ChildFoo();
// write to log from outside parent (shows scope is global)
root.log.write(root.x)
root.log.write(root.child.x);
});
function Foo() {
// instantiate logger as child of parent
this.log = new Logger("output");
// write a quick message
this.log.write("Foo constructor");
// set value of x
this.x = 1;
// instantiate child object
this.child = new ChildFoo;
}
// child object definition
function ChildFoo() {
// why is root.log == null here?
root.log.write("Child constructor");
// this reference to parent also fails
// this.x = 10 * root.x;
this.x = 10;
}
// log object definition
function Logger(container) {
// store reference to dom container
this.container = container;
}
// method to write message to dom
Logger.prototype.write = function(message) {
$("#" + this.container).append("[" + new Date() + "] " + message + "<br>");
}
我已经能够通过将以下部分添加到Foo对象定义的顶部来实现它。 这立即提供对根对象的全局对象引用,并且还实现了Singleton模式以确保只有一个根对象。 这个jsfiddle已经完全更新了。
if(root != null){
root.log.write("Root object already instantiated");
return root;
} else {
root = this;
}
问题是你在打电话...
var parent = null;
$(document).ready(function() {
parent = new Foo();
// ...
});
...... Foo
......
this.log = new Logger("output");
this.log.write("Foo constructor");
this.x = 1;
this.child = new ChildFoo;
...它调用尝试访问parent
ChildFoo
...
parent.log.write("Child constructor");
这一切都在一次调用中,因此原始new Foo
在您尝试访问parent
之前尚未完成,所以parent
仍然为null
。
上一篇: Why does a child object in JavaScript lose the global scope?