【问题标题】:Javascript OOP - Why do these two almost exact same statements give different outputs?Javascript OOP - 为什么这两个几乎完全相同的语句给出不同的输出?
【发布时间】:2013-12-12 08:49:28
【问题描述】:

所以我对“正确的”Javascript 编程作为一个整体是新手。我只真正将它用于简单的 DOM 操作,并稍微涉足 jQuery。现在我正在尝试学习 Javascript 编程的完整概念,包括 OOP 等。我喜欢认为我对 JS 中的范围有所了解,但我无法理解:

function Person(name, age){
    this.name = name;
    this.age = age;

    this.getName = function(){
        return name;
    }

    this.setName = function(name){
        this.name = name;
    }

    this.getAge = function(){
        return age;
    }

    this.setAge = function(age){
        this.age = age;
    }
}

p = new Person("Bob", 12);
console.log(p.getName());
console.log(p.getAge());

console.log(name);  //logs "an empty string" - What?
console.log(age);   //logs "ReferenceError: age is not defined" - Expected

在前两个console.logs 正常运行后,我想检查Person 函数中的属性值,以确保没有任何内容超出范围。 name 在某种程度上有(只给出了一个空值 - 但仍然存在),但年龄没有。

我看不到任何拼写错误,这是我唯一能理解的导致此问题的原因。那么为什么console.log(name); 不给ReferenceError

尽管我很想知道答案,但我非常感谢对根本问题的完整解释,包括任何关键术语,例如原型、词法范围、提升等。

【问题讨论】:

  • name 是全局的,是window 的属性。
  • 哈!我想它可能是这样的,但我不知道。谢谢!

标签: javascript oop scope referenceerror


【解决方案1】:

name 标识符存在于浏览器的全局范围内,它是window 的一个属性。

window.name

【讨论】:

  • 也谢谢你!这让我很好奇为什么window 变量是完全全局的,而不是只能通过window.name 访问它。我会理解顶部是否有类似 import window 的内容,但如果知道我可能会在任何时候不小心使用其中一个变量,我会感到不舒服。
  • @Jazcash "window" 实际上是指向自身的全局对象的属性(参见window.window),全局对象的所有属性都是全局范围的一部分。 JavaScript 具有词法作用域,因此内部作用域可以从外部作用域引用标识符(因此 window 标识符如何解析为全局对象)。您可以将代码放在IIFE 中,所有变量/函数定义都不会与全局变量/函数定义冲突。 =]
  • 我的个人设置是 (function(){ 'use strict;' /*code here*/ }());,这样 var/function 声明不会与全局作用域冲突,未声明的变量不会泄漏到全局作用域(改为抛出 ReferenceError,请参阅 Strict mode) .希望 ES6 模块能够尽快标准化,让我们摆脱这个样板。
【解决方案2】:

您根本没有使用原型,最好将函数放在构造函数原型上。有关构造函数和原型的更多信息,您可以查看this answer

至于为什么不记录年龄;这是因为您尝试记录 window.age 而不是 p.age

p = new Person("Bob", 12);
console.log(p.name);
console.log(p.age);
console.log("this is:",this);
console.log("does window have a name property?",typeof this.name);
console.log("does window have an age property?",typeof this.age);

【讨论】:

  • 你说得对,我现在才刚学这些东西。问题中的代码只是我的测试示例之一。不过谢谢。