为什么我收到此错误:未捕获的TypeError:无法读取undefined的属性'john'

时间:2013-09-13 12:11:29

标签: javascript object

我是JavaScript的新手,可能没有使用正确的术语,所以请耐心等待。

http://jsbin.com/IPaDAJO/1/

我希望页面上显示以下内容 您好,我的名字是约翰史密斯,我今年29岁。您好,我的名字是Suzie Alport,我今年24岁。

我想明白为什么Suzie不能参考John的问候方法?

<script>
        var employees = {
            john: {
                name: "John Smith",
                age: 29,
                job: "web developer",
                greet: function(){
                    document.write("Hello my name is " + this.name + " and I am " + this.age + " years old. ");
                }
            },
            suzie: {
                name: "Suzie Alport",
                age: 24,
                job: "nursery assistant",
                greet: employees.john.greet
            }
        };
        employees.john.greet();
        employees.suzie.greet();
</script>

由于

1 个答案:

答案 0 :(得分:2)

截至您创建要分配给suzie媒体资源的对象时,employeesundefined。在整个表达式完成之前评估属性初始值设定项。

以下是事情发生的顺序:

  1. 引擎创建一个名为employees的变量,其初始值为undefined
  2. 引擎创建一个空白对象(最终将分配给employees)。
  3. 引擎创建另一个空白对象(最终将成为john属性值)。
  4. 评估"John Smith"并在#3名为name的空白对象上创建一个属性,为其赋予该值。
  5. 重复agejobgreet的处理过程。
  6. 它将该对象分配给上面#2中对象的john属性。
  7. 它会创建另一个空白对象(成为suzie)。
  8. 它评估"Suzie Alport"并在#7名为name的对象上创建一个属性,为其赋予该值。
  9. 重复agejob
  10. 的流程
  11. 它尝试评估表达式employees.john.greet并失败,因为employeesundefined
  12. 如果你把它分成两部分,它可以工作(直到document.write炸毁):

    var employees = {
        john: {
            name: "John Smith",
            age: 29,
            job: "web developer",
            greet: function(){
                document.write("Hello my name is " + this.name + " and I am " + this.age + " years old. ");
            }
        }
    };
    employees.suzie = {
        name: "Suzie Alport",
        age: 24,
        job: "nursery assistant",
        greet: employees.john.greet
    };
    employees.john.greet();
    employees.suzie.greet();
    

    这是有效的,因为在我们尝试评估employees.john.greet之前,已经将对上面#2中创建的对象的引用分配给employees变量。


    旁注:

    避免在现代网页和应用程序中使用document.write。相反,请使用DOM methodsdocument.write仅在初始页面加载期间以您希望的方式运行;在初始页面加载后,它将完全擦除现有文档并开始在同一窗口中编写新文档。

    例如,您可以将段落附加到document.body,如下所示:

    function display(msg) {
      var p = document.createElement('p');
      p.innerHTML = String(msg);
      document.body.appendChild(p);
    }
    

    Live Example同时使用以上两者(source