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());
Related
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
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
my question here is about functions and objects in javascript. I have three questions that stems from one to other. In the below example, I try to access the value of 'a' in test, but I get undefined. but I create a new object of test, then I am able to access the 'a' value and change it.
//create a function called test
var test=function() {
this.a=2
this.b=3 };
test.a//undefined
//create a object called test1 using 'new'
test1 = new test();
test1.a//2
//change the value of a in test1
test1.a=4
test1 //Object { a=4, b=3}
while trying to find why this happens, I came across this javascript functions are objects? and another question popped out of this.
The accepted solution for that SO question is below
var addn = function func(a) {
return func.n + a;
};
addn['n'] = 3;
addn(3);
I changed the 'func.n' to 'this' and it no longer works
var addn=function func(a) {
return this.n+a;
};
addn['n']=3;
addn(3); //NaN
making anonymous function with 'this' also did not help
//anonymous function
var addn=function(a) {
return this.n+a;
};
addn['n']=3;
addn(3); //NaN
why using 'this' did not work?
one final question, what is the difference in using keyword 'new' and 'createObject'. Douglas Crokford suggests using 'CreateObject' in his book, but I fail to understand why. Thanks all for your comments
1. Functions are constructors for new objects
When you call new FuncName, the function acts as a constructor, and the value of this inside points to the object being constructed (not the function itself). When you remove new, this becomes undefined, falling back to the global object (unless you're in strict mode).
2. Functions are also objects
Every function is an instance of Function, so the functions themselves are objects and can have have their own properties. Those properties cannot be accessed with this.propName inside the function body, only with funcName.propName. That's because this inside a function is never the function object itself (unless you forced it to be, with bind, call, or apply).
I hope both topics above help you understand how functions work. As for your final question: Crockford's createObject is a different way to implement inheritance, doing basically what Object.create does in ES5-compliant browsers. It allows an object to inherit straight from another object, without requiring you to manually create a new constructor, set its prototype property (which is an example of a property on a function object), and create an instance with new. Crockford prefers that, and said he stopped using new in favor of this approach.
In response to the questions you asked in chat, here is an attempt to explain what functions are and what they do, with examples.
Functions can be just... functions
You call them, they do something:
function alertThis(what) {
alert(what)
}
alertThis("alerting something");
You can also pass them values, and have them return values
function timesTwo(num) {
return num * 2;
}
timesTwo(2); // 4
They can be passed and return anything, including objects...
function createPerson(firstName, lastName) {
return {
firstName : firstName,
lastName : lastName
}
}
var john = createPerson('John', 'Doe');
john.lastName; // "Doe"
...and other functions:
function timesN(n) {
return function(num) {
return n * num;
}
}
var timesThree = timesN(3);
timesThree(5); // 15
Functions are objects
Functions can be passed around and returned like any ordinary object. That's because they are objects. Like any object, they can have properties:
function countCalls() {
countCalls.timesCalled++;
}
countCalls.timesCalled = 0;
countCalls();
countCalls();
countCalls.timesCalled; // 2
One very important default property of functions is prototype. It's a special property, and we'll see why.
Functions can act as constructors for new objects
Functions can behave like class constructors do in regular OO languages. When called with new, they create a new object of a certain "class". This new object is called this inside the function, and is automatically returned:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
var john = new Person('John', 'Doe');
john.firstName; // "John"
john instanceof Person; // true
... unless you deliberately return something else:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
var fakePerson = {
firstName : firstName,
lastName : lastName
};
return fakePerson;
}
var notPerson = new Person('John', 'Doe');
notPerson.firstName; // "John"
notPerson instanceof Person; // false
// Note: the object called 'this' inside the function is created, but
// after the function is called there is no outside reference to it.
Objects created by constructors know who created them, and can see their prototype property
Back to a real person:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// Add something to the Person prototype
Person.prototype.sayHi = function() {
return "hi, I'm " + this.firstName;
}
var john = new Person('John', 'Doe');
john.sayHi(); // "Hi, I'm John"
john.constructor; // Person
The object john can sayHi() because it has access to everything inside its constructor's prototype property. But it cannot see other properties of Person directly (only through their own constructor property):
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
Person.timesCalled++;
// There is no 'this.timesCalled', only Person.timesCalled
}
Person.timesCalled = 0;
var john = new Person('John', 'Doe');
john.timesCalled; // undefined - john cannot be called, Person can
john.constructor.timesCalled; // 1
1.
addn['n'] = 3; //Means you add static property n to the function(object) addn.
so addn.n also work.
2
this.n means property n of the instance.
this.n === undefined so it returns NaN.
3 var addn=function func(a) means you give a second name to func.
var addn=function(a) is better format in most case.
4 createObject is not a native javaScript code. 'New' is.
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 :)
function Person(name) {
this.name = name;
this.say = function() {
console.info('I am ' + this.name);
}
}
var p=new Person('stackoverflow');
Someone tell me that the above codes are equals to :
function Person(name) {
this.name = name;
this.say = function() {
console.info('I am ' + this.name);
}
}
var p={};
Person.call(p,'stackoverflow');
Is this true?
If so, how about the prototype?
Each object in javascripte owns a prototype,and the prototype chain hold the releationship of the obejcts,I wonder if this prototype does something or not.
In this example, when the object of 'p' is created,does it call some build-in method of the superclass of Person?
BTW,what I want to know is what does the syntax var p=new Person('stackoverflow'); do ?
-----------------update------------------
function Person(name) {
this.name = name;
}
Person.prototype.say = function() {
console.info('I am ' + this.name);
}
How about if I put the defination of say inside the person function:
function Person(name) {
this.name = name;
Person.prototype.say = function() {
console.info('I am ' + this.name);
}
}
The code:
var p=new Person('stackoverflow');
creates a new instance of the Person class. You must remember that classes in javascript are functions, so when you call:
Person.call(p,'stackoverflow');
You are just calling the Person function and binding it to the p object (this means that in the function context the this will refer to the p object). Those pieces of code do the same thing, except for the fact that the first is an instance of the class so if you update the prototype object of person its properties will be updated.
Anyway the situation is different when you fill the prototype object of the Person function:
Person.prototype={test:"test"}
If you add this after the Person function declaration you will see that those pieces of code have a different behaviour. The object initialized with "new" will contain the test property, but the other one hasn't it. This happens because the prototype object is applied only to the instances of the class when using "new".
Well, actually
var p=new Person('stackoverflow');
is equivalent to:
var p={};
p.__proto__ = Person.prototype;
Person.call(p,'stackoverflow');
except that __proto__ is not standard JavaScript (but is supported by
some implementations).