undefined output while printing object in console - javascript

Suppose i have a object with properties and method.
When i assign this object to another object, and i execute following code. Its giving me undefined undefined output while printing object obj1 in console, can anyone please help me on this, and explain me this behaviour.
thank you.
var emp = {
fname: "sachin",
lname: "pawar",
getname: function() {
return this.fname + " " + this.lname;
}
};
var obj = emp.getname;
var obj1 = obj();
var obj3 = emp.getname();
console.log(obj1);

The issue is that this in your getname method is undefined when called via the line:
var obj1 = obj();
In JavaScript this is dependent upon the context in which the function is called. So, when you call it as a 'dot method' against the emp object this refers to its containing object. Where you call it 'stand alone' it has no contect and this is undefined.
You can bind a standalone call to give it a context, as follows:
var obj=emp.getname.bind(emp);
var obj1=obj();
Then when it executes it will use emp to get its context for this.

When you do obj = emp.getname, its reference is copied and when you call it, there is a difference in obj.function() and function().
When you do obj.function, function's this is set as obj, but when you copy reference and call it, since no object is associated to this call, it takes global scope(window). Hence it returns undefined.
Sample
window.fname = "Foo";
window.lname = "Bar";
var emp = {
fname: "sachin",
lname: "pawar",
getname: function() {
return this.fname + " " + this.lname;
}
};
var obj = emp.getname;
var obj1 = obj();
var obj3 = emp.getname();
console.log(obj1);
console.log(obj3);
Alternate implementation
var emp = (function() {
// private properties
var fname = "sachin"
var lname = "pawar"
var getname = function() {
return fname + " " + lname;
}
// Selected properties exposed
return {
getname: getname
}
})()
var obj = emp.getname;
var obj1 = obj();
var obj3 = emp.getname();
console.log(obj1);
console.log(obj3);

Related

Object.create() cant access variable inside function

I'm using below code.
var emp = function employee(name, sal) {
this.empname = name;
this.sal = sal;
}
emp.prototype.getName = function() {
return this.empname
};
var man = new emp("manish", 100);
console.log(man.getName()); //prints manish
var man1 = Object.create(emp);
man1.empname = "manish1";
console.log(man1.prototype.getName()); //prints undefined.
can some help me to understand why object create is printing undefined instead manish1.
new X() creates a new object with constructor X and prototype X.prototype. Object.create(X) creates a new object with prototype X (and therefore constructor X.constructor).
So you need to call it with the prototype you want:
var man2 = Object.create(emp.prototype);
man2.empname = "manish2";
console.log (man2.getName()); // prints manish2

How does function scope work in JavaScript?

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?
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;
}
Extra info
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";
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 alerting the value of the newly-created property and not the variable.
See MDN
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"
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"
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;
}
}
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"}
}

Use an object as a blueprint for other objects

I have created a simple object that want to use as a blueprint for other objects. But something is not going well. Can anyone find out why? When I click one button it should change innerHTML of the div to display the properties of the new objects!
here is a fiddle
var objekt = {
name : "olsi",
surname : "Angjellari",
kot : function () {
return this.name + this.surname
},
print : function () {
id.innerHTML = this.kot()
}
};
http://jsfiddle.net/cTRuL/
There are a number of problems:
When you want to do:
var dana = new objekt();
Then, objekt must be a function, not just an object because an object is not a constructor, only a function can be a constructor. This is one way to do that:
function objekt() {
this.name = "olsi";
this.surname = "Angjellari";
};
objekt.prototype = {
kot : function () {
return this.name + this.surname
},
print : function () {
id.innerHTML = this.kot()
}
};
Second, in your jsFiddle if you're going to put function names in the HTML, then those functions have to be global. To make your code global in the jsFiddle, you have to set the upper left setting to "No wrap - in <body>" or "No wrap - in <head>". As you had your jsFiddle, your code was defined inside an onload handler and therefore NOT reachable by function calls from your HTML.
Third, once you make objekt into a function to fix the previous issue, then you can't call objekt.print() directly. You probably want to call .print on an actual object of type objekt like dana or boi.
You can see it all working here: http://jsfiddle.net/jfriend00/7TbEx/
you want to create a constructor so you can make instances using the new operator like you are trying
function objekt(name,surname){
this.name = name||"olsi";
this.surname = surname||"Angjellari";
this.kot = function () {
return this.name + this.surname
};
this.print = function () {
id.innerHTML = this.kot()
};
}
var obj = new objekt();
var obj2 = new objekt("First","Last");
obj.print();
obj2.print();
You could also make these through the prototype
function objekt(){}
objekt.prototype.name = "";
objekt.prototype.surname = "";
objekt.prototype.kot = function(){
return this.name + this.surname;
};
objekt.prototype.kot = function(){
id.innerHTML = this.kot();
};
var obj = new objekt();
obj.name = "First";
obj.surname = "Last";
var obj2 = new objekt();
obj2.name = "Last";
obj2.surname = "First";
obj.print();
obj2.print();

how to call a method in an object following the factory pattern

I would like to display name, age, job in an alert message box, how do I do that?
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function () {
alert(this.name);
};
return o;
}
var person1 = createPerson('Nicholas', 29, 'Software Engineer');
var person2 = createPerson('Greg', 27, 'Doctor');
jsFiddle Demo
"I would like to display name, age, job in an alert message box, how do I do that?"
Access the properties on the object using .name, .age, and .job like this:
alert(person1.name+" "+person1.age+" "+person1.job); from the outside. If you would like to have the object be able to use this alert then you can attach it like this:
o.alertInformation = function(){ alert(this.name+" "+this.age+" "+this.job); };
function createPerson(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
o.alertInformation = function(){ alert(this.name+" "+this.age+" "+this.job); };
return o;
}
var person1 = createPerson('Nicholas', 29, 'Software Engineer');
var person2 = createPerson('Greg', 27, 'Doctor');
//example of accessing the object properties with dot notation
//alternatively, you could use person1["name"] to access them
alert(person1.name+" "+person1.age+" "+person1.job);
//or if you want to use an internal method on person
person1.alertInformation();
jsFiddle Demo
Blurb on "factory" pattern:
Usually an approach is used where the new keyword is called on a function. When new is used on a function, it creates a scope in the function where this refers to the function object. Using this.name inside of a function called with new will attach name to the object. When you use new, it implicitly assigns the function object to the variable, in the below example, p is used.
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
}
Person.prototype.sayName = function(){
alert(this.name);
};
Person.prototype.alertInformation = function(){
alert(this.name+" "+this.age+" "+this.job);
};
var p = new Person('Nicholas', 29, 'Software Engineer');
p.sayName();
p.alertInformation();
jsFiddle Demo
For this to be an actual factory, remember that it has to be involved with the actual creation of the objects, not just implicitly returning them. To do this, we would need a PersonFactory (sounds strange :P).
function personFactory(){
var People = [];
var autoIncId = 0;
return {
Create: function(name,age,job){
var p = new Person(autoIncId++,name,age,job);
People.push(p);
return p;
},
GetPersonById: function(id){
return People[id];
}
};
}
which would then be used:
var pf = personFactory();
var p = pf.Create('Nicholas', 29, 'Software Engineer');
p.sayName();
p.alertInformation();
function createPerson(name, age, job){
this.name=name;
this.age=age;
this.job=job;
if(createPerson._intialized=="undefined"){
createPerson.prototype.sayPersonInfo=function(){
alert('i am '+this.name+' , '+this.age+'years old and my job is '+this.job);
}
createPerson._initialized=true;
}
var person1 = createPerson('Nicholas', 29, 'Software Engineer');
var person2 = createPerson('Greg', 27, 'Doctor');
person1.sayPersonInfo();
this method is called ' dynamic prototype ' and is the best way in know .
i hope this can help ...

how to access javascript object variables in prototype function

I have the following javascript
function person() {
//private Variable
var fName = null;
var lName = null;
// assign value to private variable
fName = "Dave";
lName = "Smith";
};
person.prototype.fullName = function () {
return this.fName + " " + this.lName;
};
var myPerson = new person();
alert(myPerson.fullName());
I am trying to get an understanding of object orientated techniques in javascript. I have a simple person object and added a function to its prototype.
I was expecting the alert to have "Dave Smith", however I got "underfined underfined". why is that and how do I fix it?
Unfortunately you can't access a private variable. So either you change it to a public property or you add getter/setter methods.
function person() {
//private Variable
var fName = null;
var lName = null;
// assign value to private variable
fName = "Dave";
lName = "Smith";
this.setFName = function(value){ fName = value; };
this.getFName = function(){ return fName; }
};
see javascript - accessing private member variables from prototype-defined functions
But actually this looks like what you are looking for:
Javascript private member on prototype
from that SO post:
As JavaScript is lexically scoped, you can simulate this on a per-object level by using the constructor function as a closure over your 'private members' and defining your methods in the constructor, but this won't work for methods defined in the constructor's prototype property.
in your case:
var Person = (function() {
var store = {}, guid = 0;
function Person () {
this.__guid = ++guid;
store[guid] = {
fName: "Dave",
lName: "Smith"
};
}
Person.prototype.fullName = function() {
var privates = store[this.__guid];
return privates.fName + " " + privates.lName;
};
Person.prototype.destroy = function() {
delete store[this.__guid];
};
return Person;
})();
var myPerson = new Person();
alert(myPerson.fullName());
// in the end, destroy the instance to avoid a memory leak
myPerson.destroy();
Check out the live demo at http://jsfiddle.net/roberkules/xurHU/
When you call person as a constructor, a new object is created as if by new Object() and assigned to its this keyword. It is that object that will be returned by default from the constructor.
So if you want your instance to have properties, you need to add them to that object:
function Person() {
// assign to public properties
this.fName = "Dave";
this.lName = "Smith";
};
Incidentally, by convention functions that are intended to be called as constructors are given a name starting with a capital letter.
You're declaring those variables as local to the function, instead of making them part of the object. In order to put them in the instance, you've got to use 'this' in the constructor as well. For example:
function person() {
this.fName = 'Dave';
this.lName = 'Smith';
}
person.prototype.fullName = function () {
return this.fName + " " + this.lName;
};
var myPerson = new person();
alert(myPerson.fullName());
In the constructor you should assign your variables to this:
this.fName = null;
this.lName = null;
But then they are not private. JavaScript does not have private variables like a "classic" Object Oriented language. The only "private" variables are local variables. An alternative to the above is to assign getter/setter methods to this within the constructor.

Categories