为什么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

    链接地址: http://www.djcxy.com/p/95307.html

    上一篇: Why does a child object in JavaScript lose the global scope?

    下一篇: How to get javascript object method name?