Javascript prototype - Variable remains undefined - javascript

I have below code snipet -
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
}
var person=new Person("MyName","MySirname",14,"Black")
Person.prototype.FullName=this.firstName+" "+this.lastName
console.log(person.FullName)
Here in this example code is pronting undefined undefined; whereas I expect - MyName MySirname

The reason for this is that the line Person.prototype.FullName = this.firstName + " " + this.lastName is executed when the Person constructor is called and at that time, the value of this is the global object. Therefore, the value of this.firstName and this.lastName are undefined and hence the result is undefined undefined.
The correct way to set the FullName property would be to use the parameters passed to the constructor, like this:
Person.prototype.FullName = function() {
return this.firstName + " " + this.lastName;
};
Then you can call the FullName method on the person object like this:
console.log(person.FullName()); // MyName MySirname

Related

Are there problems in this code? Can someone explain how this works

This code is from sololearn.com in the JS course.
function person(name, age) {
this.name= name;
this.age = age;
this.yearOfBirth = bornYear;
}
function bornYear() {
return 2016 - this.age;
}
this.yearOfBirth = bornYear; why is bornYear just bornYear?
Shoudn't it be bornYear()
How does this even work?
I think this version would help you better to understand and is probably what the teacher wanted to write:
function Person(name, age) {
this.name= name;
this.age = age;
this.getYearOfBirth = function bornYear() {
return 2016 - this.age;
};
}
1- Always use Pascale case with a function that will be treated as class, that is why I renamed person to Person. That improves readability and confusions
2- I renamed yearOfBirth to getYearOfBirth, I agree the teacher should have given a better naming here too. Devs idiomatically use verbs to accessors (get/set) or methods (compute, parse, find...)
3- bornYear is a function within a class, so that an accessor is defined. Since bornYear is called without new operator, this will be equaled to window as default binding
Try it yourself, open your javascript console in the browser and type following:
function t() { console.log(this); }
t() returns window, the global/default scope
new t() returns a freshly created context t
bornYear is a function.
bornYear() is a value returned by burnYear function and equals 2016-this.age
What happens if this.yearOfBirth = bornYear
this.yearOfBirth = bornYear means you assign this.yearOfBirth=function(){return 2016-this.age}
Then lets say var me = new person("john",16) you can call me.yearOfBirth(); // 2000
What happens if this.yearOfBirth = bornYear(),
while you are declaring var me = new person("john",16) bornYear() was executed return 2016-this.age but this.age is not defined so returned undefined. Then, this.yearOfBirth=undefined.
function person(name, age) {
this.name= name;
this.age = age;
this.yearOfBirth = bornYear;
}
function bornYear() {
return 2016 - this.age;
}
var p = new person("A", 22);
document.write(p.yearOfBirth());
This code explains it.
A new object is created (new)
yearOfBirth is used because it returns a value
If you check the value, it's what it should be.
(Bad explaining)

How can I call a base method of the constructor's prototype with the same name as a method in the class?

Given that I have:
var PersonClass = function () {
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.name = function(){
return this.firstName + " " + this.lastName;
};
this.setName = function(a,b){
this.firstName = a;
this.lastName = b;
return this.firstName + " " + this.lastName;
}
}
Person.prototype.name = function () {
return "Proto_:"+this.firstName + " " + this.lastName;
};
Person.prototype.whoAreYou = function () {
return "Hi i'm " + this.name();
};
Person.prototype.setName2 = function(a,b){
this.firstName = a;
this.lastName = b;
};
return Person;
}(); //PersonClass
And I create an instance:
Me = new PersonClass("Steve","Benj");
me.name() // returns Steve Benj.
What will call the prototype name method and return Proto_:Steve Benj ?
The function defined in the Person constructor will overwrite/override the prototype definition that occurs below it, so there is no good way to invoke the prototyped function over the function defined in the constructor (see comments on your post for the "bad" way).
I would think about whether or not you want to use the same name for both of these functions, unless this is not your actual use case. I would say you would want to create a prototype function that is called protoName or something like that, if you want different behavior you should define different functions.
The relation between object and its prototype lies through constructor property. In your case the counstructor is Person function object. Person has direct coupling with its prototype. The last thing is to call a prototype method over a certain object to bind this keyword properly - and this can be achieved with Function.prototype.call() approach:
console.log(Me.constructor.prototype.name.call(Me));
The output will be:
Proto_:Steve Benj
The alternative approach is using Object.getPrototypeOf(x) function which would give the same result:
Object.getPrototypeOf(Me).name.call(Me)
The way you structure this, you invoked PersonClass function immediately after it's defined.
So PersonClass === Person.
So when you do Me = new PersonClass("Steve","Benj");, what you are really doing is Me = new Person('Steve', 'Benj');
So whenever you invoke those prototype methods, you are calling the prototype methods from Person.
You can verify this by doing
Me.constructor // => Person

difference between normal function declaration and inside return block function declaration in Javascript

What is the difference between normal function declaration and inside return block function declaration in Javascript.
Below code normal function name : updatename, inside function name : changeName
function person(firstName,lastName,age,eyeColor) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.eyeColor = eyeColor;
this.updatename = function (name) {
this.lastName = name;
}
return {
'changeName' : function (name) {
this.lastName = name;
}
};
}
var myMother = new person("Sally","Rally",48,"green");
console.dir(myMother);
console.log(typeof(myMother.changeName));
console.log(typeof(myMother.updatename));
myMother.changeName("Doe");
If you return an object from a function, then invoke that as a constructor with new, the original this of the function is THROWN AWAY AND IGNORED AND LOST FOREVER. In other words, the value of this.firstName is never again accessible in this world. What are you trying to accomplish by returning that object literal?
What is the difference between normal function declaration and inside return block function declaration in JavaScript?
The difference (assuming you mean method declaration) is that the normal declaration does what you would normally imagine it would do. The "inside return block function declaration" overrides and cancels the original value of this, and instead returns JUST THAT OBJECT with a single method, which is probably not what you want.

"this" keyword in javascript(as instance)

AFAIK "this" is used when there is clash between "property" & "parameter" of function.
Please find my code below.
<script>
function person(firstName, lastName, age, eyeColor) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = function() {
return this.firstname + " " + this.lastname
}
}
var p = new person();
document.write("fullname is " + p.fullName());
</script>
Here please correct me if I am wrong with following things
this.firstName contains "this" because person contains firstName as parameter and wants to be as property of person.
My doubt is that
this.fullName also has "this" in it even thought there is no parameter with fullName.May be I am wrong(Read that "this" actually creates an instance).
If above is true that it actually creates an instance
then my problem is
it is creating instance in var p = new person() and why would we create instance of fullName property inside of person
Hope this helps
this.firstname contains "this" because person contains firstname as parameter and wants to be as property of person. - wrong
this is used to assign any value to the property of the object (instance of Person class)
this.firstName = your_var this will assign value of your_var to firstName property of Person's object it doesn't matter if your_var is in parameters or some local var created by you
You can assign any value to property of an object
Read that "this" actually creates an instance - wrong
this refers to the created instance and does not create instance
you are not creating instance full name here, what you are doing is creating an instance method for person object which you can later on use to get full name of the person
You'll notice if you run this code you get the following error:
Uncaught TypeError: p.fullname is not a function on line 10
There is an error in the capitalization of your method call.
Corrected code is below:
document.write("fullname is " + p.fullName());
your properties are like fooBar and you are returning them as foobar, these places:
this.firstName = firstName; // firstName
this.lastName = lastName; // lastName
//but below as firstname, lastname instead of firstName and lastName
return this.firstname + " " + this.lastname
also on here:
this.fullName = function(){ ... }
but you call the function as p.fullname()
Also I think, since the fullName() returns firstName and lastName, you probebly need to pass these values when creating the instance if you are going to call the fullName() because this function requires them, otherwise you'd get undefined, like below:
var p = new person('Foo', 'Bar');
Now it is working: JS Fiddle
function person(firstName, lastName, age, eyeColor) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = function() {
return this.firstName + " " + this.lastName
}
}
var p = new person('Foo', 'Bar');
// check the console
console.log("fullname is " + p.fullName());

why does this return undefined - javascript

i'm pretty new to js. i'm sorry if this sounds dumb.
but why does the following code return "undefined"
function NewPerson(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
this.getName = function(){
//alert(this.name);
alert("The age is "+this.age);
};
}
var obj1 = new NewPerson("Mark",25,"Male");
alert("The age is as follows "+obj1.getName());
// output:
The age is 25
The age is as follows undefined
Because you don't return anything.
You have to explixitly return in you function
Following should work
function NewPerson(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
this.getName = function(){
//alert(this.name);
alert("The age is "+this.age);
return this.age
};
}
var obj1 = new NewPerson("Mark",25,"Male");
alert("The age is as follows "+obj1.getName());
No one else mentioned it so I will - it is more efficient to put functions that will be the same for all instances on the constructor's prototype. Then you only have one instance of the function that is used by all instances, e.g.
function NewPerson(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
}
NewPerson.prototype.getName = function() {
alert("The age is "+this.age);
return this.name;
}
If you want to get some value from called function you must use
return value;
So try
function NewPerson(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
this.getName = function(){
alert("The age is "+this.age);
return this.name;
};
}
var obj1 = new NewPerson("Mark",25,"Male");
alert("The name is as follows "+obj1.getName());
will work as you expected.
As stated before, you didn't return anything in getName.
It looks like you don't really want to alert age in getName. Also, adding getName to each instance of the object in the constructor is inefficient. Use the prototype method instead. I am submitting the cleaned-up code for what you are probably going for:
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
};
Person.prototype.getName = function() {
return this.name;
};
var obj1 = new Person("Mark",25,"Male");
alert("The name is: "+obj1.getName());
By placing getName on the prototype, all instances of Person will have access to the same function, thus saving memory :) By using the statement this.getName = ... in the constructor function Person, you are making a new function for each instance of Person.
#Davenewton 's answer is correct and while I like it for its
straightforwardness, it takes that
famous a-ha! moment for you to fully
realize why. Here's what's really going on:
So to elaborate
If we had something like this:
function i_am(){
var a = 'very smart person';
console.log(this.a);
}
var a = 'monkey';
i_am();
Depending on what linter or browser you might be using, this might either return
> "monkey" // (try the snippet)
or also
> "monkey"
> undefined // check the sreenshot
This is because of one simple reason, best understood if we go step-by-step how compiler "reads" the code.
hoist the function i_am() declaration to top (undefined)
hoist the var a declaration to top (undefined)
assign 'monkey' to variable a (now string "monkey")
execute/invoke the i_am() a function we have pre-declared
create a local variable a and assign string "very smart person"
console.log(this.a) returns 'monkey', because this refers to var/property a (same thing in this case) of the global object - call-site is from global object : i_am();
Finish execution - but uh oh! We executed function and returned no value!
Now, depending on your environment, either it hides the undefined result from you, or it prints it out! Why? Because functions are looking to return a value. Just like with variable declaration, if you do
var a;
console.log(a);
it has not been assigned a value, hence it results after RHS in undefined.
Similar principle applies to function, where it's looking to return a value, but it doesn't return anything, hence resulting in undefined
In other words, it's not this that returns undefined. It's the invokation of i_am(); that returns undefined!
Hopefully it's clear to everybody now :)

Categories

Resources