我在理解JavaScript中的函数范围时遇到了一些麻烦:
function Person() {
var _firstName;
var _lastName;
}
personOne = new Person();
personOne._firstName = "Fred";
alert(personOne._firstName);
这输出" Fred",但我认为Person函数的变量只能在函数内部访问。它为什么有效?
答案 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
无法使用的事实。
function Person() {
var _firstName= "Fred";;
var _lastName;
}
personOne = new Person();
alert(personOne._firstName); // output: "undefined"
&#13;
如果您想让它们可访问,您可以使用this
向对象添加新属性。
function Person() {
var self = this;
self._firstName= "Fred";
var _lastName;
return self;
}
var personOne = new Person();
alert(personOne._firstName); // output: "Fred"
&#13;
答案 3 :(得分:0)
您无法在对象声明中引用_firstName
。如果要访问对象属性,则需要使用this
声明,否则_firstName
或_lastName
将被视为局部变量。
因此,要访问_firstName
或_lastName
作为对象属性,您必须按以下方式声明:
function Person() {
this._firstName = "John";
this._lastName = "Doe";
}
实例化_firstName
后,您可以访问_lastName
和Person
。
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"