函数范围如何在JavaScript中运行?

时间:2015-06-01 10:04:10

标签: javascript scope

我在理解JavaScript中的函数范围时遇到了一些麻烦:

function Person() {
    var _firstName;
    var _lastName;
}
personOne = new Person();
personOne._firstName = "Fred";
alert(personOne._firstName);  

这输出" Fred",但我认为Person函数的变量只能在函数内部访问。它为什么有效?

6 个答案:

答案 0 :(得分:5)

在JavaScript中,对象是可动态扩展的。

例如:

var obj = {};
obj.firstName = "Matías"; // <-- This adds the property even if it doesn't exist

另一方面,如果要在构造函数中声明属于对象一部分的属性,则需要使用this限定它们:

function Person() {
    this._firstName = null;
    this._lastName = null;
}

额外信息

如果要避免对象可动态扩展,可以使用ECMA-Script 5 Object.preventExtensions函数:

var obj = {};
Object.preventExtensions(obj);

// This property won't be added!
obj.text = "hello world";

答案 1 :(得分:2)

因为在行中:

personOne._firstName = "Fred";

您为对象指定了一个新的属性,其值为“Fred”。它与您在函数内声明的(内部作用域)变量无关。

在下一行中,您实际上是alert新创建的属性的值,而不是变量。

请参阅MDN

答案 2 :(得分:1)

它的工作原理是因为您为对象_firstName创建了属性Person

personOne._firstName = "Fred"; // here you create the property

在下面的示例中,我强调了 _firstName无法使用的事实

&#13;
&#13;
function Person() {
    var _firstName= "Fred";;
    var _lastName;
}
personOne = new Person();
alert(personOne._firstName); // output: "undefined"
&#13;
&#13;
&#13;

如果您想让它们可访问,您可以使用this向对象添加新属性。

&#13;
&#13;
function Person() {
    var self = this;
    self._firstName= "Fred";
    var _lastName;
  
    return self;
}
var personOne = new Person();
alert(personOne._firstName); // output: "Fred"
&#13;
&#13;
&#13;

答案 3 :(得分:0)

您无法在对象声明中引用_firstName。如果要访问对象属性,则需要使用this声明,否则_firstName_lastName将被视为局部变量。

因此,要访问_firstName_lastName作为对象属性,您必须按以下方式声明:

function Person() {
    this._firstName = "John";
    this._lastName = "Doe";
}

实例化_firstName后,您可以访问_lastNamePerson

personOne = new Person();
personOne._firstName = "Fred";

这样您将覆盖已在对象构造函数中定义的属性。在您的情况下,因为_firstName在Object定义中声明,该变量的范围是本地绑定到该对象。但是,当您实例化对象时,您将分配一个扩展最初声明的对象的新属性。

最广泛接受的模式是绑定对象声明上的对象属性,但在其原型级别声明对象方法。

像这样:

function Person() {
   this._firstName;
   //...
}

Person.prototype = function() {
   getName : function() {
      //...
   },

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

答案 4 :(得分:0)

JS对象是&#34;可扩展&#34;,您可以通过dinamically添加属性。

function Person() {
    var _firstName;
    var _lastName;
}

var personOne = new Person();
console.log(personOne); // Person {}

personOne._firstName = "Fred";
personOne._age = 20;
console.log(personOne); // Person {_firstName: "Fred", _age: 20}

您实际上无法访问在函数范围内创建的_firstName,而是在新创建的对象上创建具有该名称的属性。

为了公开属性,您可以使用this关键字(它是对新创建的对象的引用)附加它。

 function Person() {
    console.log(this); // Person {}
    this._firstName = "Sam";
    console.log(this); // Person {_firstName: "Sam"}
 }

答案 5 :(得分:0)

在这一行:

personOne._firstName = "Fred";

您实际上是在创建对象的属性_firstName。它与您在构造函数中创建的var不同。您始终可以向JavaScript对象添加新属性。可以访问对象的每个属性。没有私有财产。

由于函数范围的原因,如果你没有在Person中设置方法来设置这些变量的值,你将无法从外部更改Person()内的变量。

function Person(firstName, lastName) {
    var _firstName = firstName, _lastName = lastname;
    this.getFullName = function () {
         return _firstName + " " + _lastName;
    };
} 

var someone = new Person("Some", "one");

someone._firstName = "something else"; // creates new property in the object someone

var fullName = someone.getFullName(); // still returns "some one"