Reputation: 103
I am having some trouble understanding function scope in JavaScript:
function Person() {
var _firstName;
var _lastName;
}
personOne = new Person();
personOne._firstName = "Fred";
alert(personOne._firstName);
This outputs "Fred", but I thought the variables of the Person function would only be accessible inside the function. Why does it work?
Upvotes: 1
Views: 145
Reputation:
JS objects objects are "expandable", you can add properties 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}
You don't actually have access to the _firstName
created inside the function scope, but rather you create a property with that name on your newly created object.
In order to expose a property, you attach it using this
keyword (which is a reference to the newly created object).
function Person() {
console.log(this); // Person {}
this._firstName = "Sam";
console.log(this); // Person {_firstName: "Sam"}
}
Upvotes: 0
Reputation: 10219
It works because you create the property _firstName
for the object Person
.
personOne._firstName = "Fred"; // here you create the property
In the example below I highlighted the fact that _firstName
is innacesible.
function Person() {
var _firstName= "Fred";;
var _lastName;
}
personOne = new Person();
alert(personOne._firstName); // output: "undefined"
If you want to make them accesible you can make use of this
to add a new property to the object.
function Person() {
var self = this;
self._firstName= "Fred";
var _lastName;
return self;
}
var personOne = new Person();
alert(personOne._firstName); // output: "Fred"
Upvotes: 1
Reputation: 11541
You cannot reference _firstName
inside the object declaration. If you want to access the object property you need to declare with this
, otherwise the _firstName
or _lastName
are considered local variables.
So to access the _firstName
or _lastName
as object properties, you have to declare as in the following way:
function Person() {
this._firstName = "John";
this._lastName = "Doe";
}
You may access _firstName
and _lastName
after you instantiate the Person
.
personOne = new Person();
personOne._firstName = "Fred";
This way you will override the properties already defined in the object constructor. In your case because _firstName
is declared inside the Object definition the scope of that variable is bind locally to that object. But when you instantiate the object you assign a new property which extends the originally declared object.
The most widely accepted pattern is to bind the object properties on the object declaration, but declare the object methods on their prototype level.
Like so:
function Person() {
this._firstName;
//...
}
Person.prototype = function() {
getName : function() {
//...
},
setName : function(name) {
this._firstName = name;
}
}
Upvotes: 0
Reputation: 555
In this line:
personOne._firstName = "Fred";
you are actually creating the property _firstName of the object. it is not the same as the var you created in the constructor function. You can always add new properties to a JavaScript object. Each property of an object is accessible. There is no such thing as a private property.
Due to function scope you will not be able to change the variables inside Person() from outside if you do not make methods available in Person to set the values of those variables.
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"
Upvotes: 0
Reputation: 49133
Because in the line:
personOne._firstName = "Fred";
You assigned a new property to the object with a value of "Fred". It has nothing to do with the (internally-scoped) variable you declared inside the function.
And in the following line, you're actually alert
ing the value of the newly-created property and not the variable.
See MDN
Upvotes: 2
Reputation: 64943
In JavaScript, objects are dynamically-expandable.
For example:
var obj = {};
obj.firstName = "Matías"; // <-- This adds the property even if it doesn't exist
In the other hand, if you want to declare properties that should be part of the object in the constructor function you need to qualify them with this
:
function Person() {
this._firstName = null;
this._lastName = null;
}
If you want to avoid objects from being dynamically-expandable, you can use the ECMA-Script 5 Object.preventExtensions
function:
var obj = {};
Object.preventExtensions(obj);
// This property won't be added!
obj.text = "hello world";
Upvotes: 5