What does `this` refer to? - javascript

I have a JavaScript class:
function Person(n){
// ...
}
Outside of the class, I have the following code:
Person.prototype.shower = function(){ this.dirtFactor=2 }
What does this in the above code refer to? Does it refer to prototype, or to the Person class?

The meaning of this depends on how you call the function, not how you define it.
Assuming you do something like:
var bob = new Person('whatever n is');
bob.shower();
Then this will be bob (which will be an instance of Person).

Okay, basics first: when you write function Person(o) { ... }, you are not declaring a class -- JavaScript does not class based, but object based. This statement simply declares a function (which incidentally, are objects as well).
Next, when you create an object like this:
var mellon = new Person('Mellon');
you are creating an object, whose constructor (of sorts) is Person.
Now, read this carefully: since mellon's constructor is Person, all methods in Person's prototype will be available in the object.
So if you write:
Person.prototype.shower = function(){ this.dirtFactor=2 }
then the method mellon.shower() will be available.
I recommend going through Mozilla's intro to OOP in Javascript for some details on this topic.
So to answer your question: this refers to the object with which the method shower was invoked. In the above case, it would be mellon.

It refers to the instance of the person
So when you do a
var Mike = new Person();
then this is Mike
Example
<input type="text" id="field" value="Bla" />
<script>
document.getElementById('field').onfocus=function() {
alert(this.value)
}
</script>
will alert the value of the field the function is assigned to

It reffers to a instance of Person class
var instance = new Person( ... );
instance.shower(); // Here will be this.dirtFactor assigned to instance.dirtFactor

This refers to the object upon which shower is called. Specifically, you will eventually end up doing
p = new Person(n);
This will execute the Person function and create a new, empty object which will be accessible as this in the constructor. That object will then be given a link to Person.prototype and any attribute references that fail on p will look on Person.prototype to see if it's found there.
If it's called on p, using p.shower(), then this will return to p. The point is though that there aren't instances and classes in javascript. Person.prototype is one object and all objects that are constructed by Person will share a reference to it.
Removing prototypes all together, you can just do
person = {'shower': function () {
this.dirtFactor = 2; }
}
person.shower();
console.log(person.dirtFactor);
and you will see that this still refers to the object upon which you called the method.

Related

Setting function prototype to a new object

I've been seeing this pattern in code recently:
function Person(){
this.name = "Dan";
}
Person.prototype = {
whatAmI: function(){
alert("I am a person")
}
}
On the above object person object, you can only reference the function whatAmI by calling Person.prototype.whatAmI() instead of Person.whatAmI() .
Is there any particular reason that this is done? Tt seems like its becoming popular and I cant see the benifit other than having methonds hidden on the prototype object instead of the Person object.
I understand the basics prototypes in Javascript, and I understand that using Person.prototype.whatAmI is a little unconventional in code instaed of just calling new Person(). However, I'm talking about places where the Person object is returned from another function call, and used as a normal object. Thus, the only way to call whatAmI is via Person.prototype.whatAmI
The purpose of the prototype property on functions is that it determines what prototype is assigned to objects created via the new expression when it's used with that function, e.g.:
var p = new Person();
Now, p's underlying prototype is the object that Person.prototype referred to when the new expression was evaluated, so:
p.whoAmI();
works.
In general, replacing the object on the prototype property isn't a great idea and you should only do it when setting up inheritance hierarchies. Instead, just add to the existing object:
function Person(){
this.name = "Dan";
}
Person.prototype.whoAmI = function(){
alert("I am a person")
};
A bit tangential, but:
You do have to replace the object, though, when setting up hierarchies.
// Base
function Person(name) {
this.name = name;
}
Person.prototype.whoAmI = function() {
alert("I am " + this.name);
};
// Derived
function Employee(name, position) {
Person.call(this, name);
this.position = position;
}
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
// Augmenting the derived prototype
Employee.prototype.whatDoIDo = function() {
alert("I hold the position " + this.position);
};
(That's not meant to be the be-all, end-all of hierarchies, just a quick example.)
whatmI is meant to be called on Person instances, e.g.:
var bob = new Person();
bob.whatAmI();
The prototype property of a constructor has properties that are accessible to all constructed instances of that constructor.
The ECMAScript 5 specification has a pleasantly readable explanation of the language's prototype-based inheritance:
Each constructor is a function that has a property named “prototype” that is used to implement prototype-based inheritance and shared properties. Objects are created by using constructors in new expressions; for example, new Date(2009,11) creates a new Date object...
Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s “prototype” property. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain. When a reference is made to a property in an object, that reference is to the property of that name in the first object in the prototype chain that contains a property of that name. In other words, first the object mentioned directly is examined for such a property; if that object contains the named property, that is the property to which the reference refers; if that object does not contain the named property, the prototype for that object is examined next; and so on.
Prototype is actually a built in way in JavaScript for accomplishing inheritance. An object that has already been defined can have methods and properties added to it by accessing it's prototype.
Go right to the authority on the subject and read up. This topic in particular is what makes JavaScript cool.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
There is no specific reason. It depends on what you want.
If the whatAmI function is needed on instances of the type Person, then you define it on the protoype. If you want it on the type, you can do,
Person.whatAmI = function(){
alert("I am a person")
}
They are both valid uses of the language. What you do depends on your application.

JavaScript prototype vs. this in practice

I've read many questions with valid and understandable answers here in Stack Overflow and other sites over the web, and I think I understand everything I need for using JavaScript to make object-oriented apps, save one thing: What is the real, practical purpose of using a class' prototype over this?
I've read that any method, even one set as a this member, will be called from the constructor (class) function, and not re-created for each instance.
I've seen many examples of using prototype for setting methods, implying that it would save memory by using the original class-function's method on the instance, and not a brand new attribute.
So, along with remarking which of the two options above is true, I'd like to know: is a prototype method accessing the constructor's this ("public") variables or the instance's (which may have been set as different from the constructor's)?
Edit - is using this.prototype.method = function() inside the constructor's scope wrong? All examples I've seen set a prototype method after the function has been created.
I'll try to answer your question regarding the relationship between the prototype method and this by example.
From the moz docs:
If the method is on an object's prototype chain, this refers to the
object the method was called on, as if the method was on the object.
Example:
// Our constructor function
function Example() {
this.publicGreet = "Hello World";
};
// Here the function is set as a property of the constructors prototype
Example.prototype.greet = function() {
alert(this.publicGreet);
};
// This creates a new object and invokes the constructor function
// Sets publicGreet as a property of that object and assigns it the value "Hello World"
var exampleInstance = new Example();
// Looks up the prototype chain and invokes it as a method of exampleInstance
// Remember our definition of `this` for methods on the prototype chain?
// Hence, `this` refers to exampleInstance, therefore `this.publicGreet` is "Hello World"
exampleInstance.greet();
This test should explain the performance problem: http://jsperf.com/prototype-vs-instance-functions/6
But yes, prototype saves memory because one callback is defined and instances simply points to this callback. There's no need to declare bunch of copies of the same callback.
Access issue: "this" declared within function inside this.prototype refers to "this" of instance: http://jsfiddle.net/pHtjK/
var b = Function;
b.prototype.a = function(){alert(this.b);};
var xyz = new b();
b.b = 'what';
b.a();

JavaScript OOP: method definition with or without "prototype"

Is this code,
function Person() {
function myMethod() {
alert ('hello');
}
this.method = myMethod;
}
equivalent to:
function Person() { }
Person.prototype.method2 = function() {
alert ('hello');
};
If yes, which method definition should I use and why?
They are functionally equivalent in your simple example, but behind the scenes work very differently. The prototype property on a function is really the "prototype template". It says "whenever an object is made and I am used as the object's constructor, give them this object as their prototype".
So all Persons created in your second example share the same copy of the method2 method.
In the first example, each time the interpreter encounters the function keyword, then it creates a new function object. So in the first example, each instance of Person has their own copy of the myMethod method. The vast majority of the time this doesn't matter. But this first approach uses more memory, and sometimes that does matter.
They are not functionally equivalent in more interesting cases. In the first example, myMethod can access local variables defined in Person, but the second example cannot, as one difference.
In the first scenario, when you create a new person, var person1 = new Person();, it will have its own copy of myMethod. If you create 100 Person objects, they will each have their own copy of this method.
Using a prototype, every new Person object will share the method definition. This is much more memory efficient since there will only be one copy of the method.
If you are planning on having several Person objects, the second way is better.. but if there are only a few Person objects, it won't matter that much.
It is not entirely equivalent.
In both cases, you define a function (constructor) Person() in the global namespace.
In the first case, you define a new function myMethod() in a closure inside the Person() function. Normally, the myMethod() function would not be available after the function/constructor Person() finishes. However, in this case you assign it to this.method. Thus, when you run the constructor
var myPerson = new Person();
A new object is created, then the Person() function is called with this set to the new object. Therefore, your new object receives a method field with myMethod function bound to it.
In the second case, method2 is defined inside the Person.prototype. In this case, when you call
var myPerson = new Person();
there will be no field defined directly inside your new object (as you do nothing with this in the function Person). However, every object contains a reference to its prototype. If the object is created by calling Person(), this reference is set to Person.prototype. Thus, your object will ultimately contain method2, though not directly in itself, but in the prototype. So when you call
myPerson.method2();
the interpreter looks for method2 inside the myPerson object and finds nothing, then it looks into the prototype of myPerson, which is Person.prototype and finds method2, so it calls it.
Long story short: in the first your constructor creates the method, so every time you call the constructor, a new method is created and inserted to the new object. In the second case, the method is stored in the prototype, so every object you create will have the reference to the same instance of your method.
No, they are not equivalent. Although, they are similar. The first method will create a new function myMethod for each new Person() created.
The second method will have one function method2 that is "shared" by all Person's.
They have similar functionality but you should use the second approach (prototype) because when you will create an object using new Person() every object will share the same method2 but using the first approach each new object will have it's own myMethod() that will consume moe memory.
A few days ago I asked a similar question and got this answer.

what is the meaning of word this near the property in JavaScript

Hello I'm a newcomerin JavaScript language.
I started to see some examples of JavaScript code.
and i cant understand the following code segment:
function Employee(name,salary)
{
this.name=name;
this.salary=salary;
this.paycheck=function()
{
var monthly=this.salary/12;
document.write(this.name+ ": " +monthly);
};
}
var emp= new Employee("Fred",10000);
emp.paycheck();
My question: what is the meaning of word this near the property inside class (i.e. ,this.name=name; this.salary=salary; )?
Thank you in advance!
The use of this could be explained as meaning "properties that apply to this instance". Since Employee is a constructor function (you create instances of it using the new operator), every instance has its own values for those properties:
var me = new Employee("James", 2000000); //Instance of Employee
console.log(me.name); //Prints James
var you = new Employee("Michael", 2000000); //Another instance
console.log(you.name); //Prints Michael
Note that this also means every instance of Employee has its own copy of the paycheck method. This is not particularly efficient, as a separate copy of the function has to be stored in memory for every instance of the object. You could instead declare the method on the prototype of the Employee object, which would mean the method would be shared between all instances.
In JavaScript this always refers to the “owner” of the function we're
executing, or rather, to the object that a function is a method of.
When we define our faithful function doSomething() in a page, its
owner is the page, or rather, the window object (or global object) of
JavaScript. An onclick property, though, is owned by the HTML element
it belongs to.
For further reading see these links:
http://www.quirksmode.org/js/this.html
http://justin.harmonize.fm/index.php/2009/09/an-introduction-to-javascripts-this/
http://javascriptweblog.wordpress.com/2010/08/30/understanding-javascripts-this/
this is a reference to the calling context of the function.
Its value will be different based on how a function is invoked.
In your case, because Employee is invoked using new, it's a reference to the new object being constructed.
So when you do...
this.name=name;
...what's happening is that the new object you're creating is being assigned a property name, and its value is being set to whatever was passed to the name parameter of the function.
Here's one way to demonstrate it.
Simplify your function like this...
var foo;
function Employee() {
foo = this;
}
So now all Employee does is set its this value to the outer variable foo.
Now lets create a new object
var bar = new Employee();
So bar has been assigned whatever Employee returned. If this is the new object constructed, and we assigned it to foo, then foo and bar should have the same object.
foo === bar; // true
In this case the Employee function is used a constructor. When the new Employee() syntax is used (as opposed to simply calling Employee()), this refers to an object that you are about to create, which is later assigned to emp variable.
it's a definition of properties inside the class.
You can read short information about it here http://www.phpied.com/3-ways-to-define-a-javascript-class/
this always refers to the “owner” of the function we're executing

Understanding prototypal inheritance in JavaScript

I am new to JavaScript OOP. Can you please explain the difference between the following blocks of code? I tested and both blocks work. What's the best practice and why?
First block:
function Car(name){
this.Name = name;
}
Car.prototype.Drive = function(){
console.log("My name is " + this.Name + " and I'm driving.");
}
SuperCar.prototype = new Car();
SuperCar.prototype.constructor = SuperCar;
function SuperCar(name){
Car.call(this, name);
}
SuperCar.prototype.Fly = function(){
console.log("My name is " + this.Name + " and I'm flying!");
}
var myCar = new Car("Car");
myCar.Drive();
var mySuperCar = new SuperCar("SuperCar");
mySuperCar.Drive();
mySuperCar.Fly();
Second block:
function Car(name){
this.Name = name;
this.Drive = function(){
console.log("My name is " + this.Name + " and I'm driving.");
}
}
SuperCar.prototype = new Car();
function SuperCar(name){
Car.call(this, name);
this.Fly = function(){
console.log("My name is " + this.Name + " and I'm flying!");
}
}
var myCar = new Car("Car");
myCar.Drive();
var mySuperCar = new SuperCar("SuperCar");
mySuperCar.Drive();
mySuperCar.Fly();
Why did the author add the Drive and Fly methods using prototype, and did not declare them as a this.Drive method inside the Car class and as this.Fly in the SuperCar class?
Why does SuperCar.prototype.constructor need to be set back to SuperCar? Is the constructor property overridden when prototype is set? I commented out this line and nothing changed.
Why call Car.call(this, name); in the SuperCar constructor? Won't properties and methods of Car be 'inherited' when I do
var myCar = new Car("Car");
To add to Norbert Hartl's answer, SuperCar.prototype.constructor isn't needed, but some people use it as a convenient way of getting the constructing function of an object (SuperCar objects in this case).
Just from the first example, Car.call(this, name) is in the SuperCar constructor function because when you do this:
var mySuperCar = new SuperCar("SuperCar");
This is what JavaScript does:
A fresh, blank object is instantiated.
The fresh object's internal prototype is set to Car.
The SuperCar constructor function runs.
The finished object is returned and set in mySuperCar.
Notice how JavaScript didn't call Car for you. Prototypes being as they are, any property or method that you don't set yourself for SuperCar will be looked up in Car. Sometimes this is good, e.g. SuperCar doesn't have a Drive method, but it can share Car's one, so all SuperCars will use the same Drive method. Other times you don't want sharing, like each SuperCar having its own Name. So how does one go about setting each SuperCar's name to its own thing? You could set this. Name inside the SuperCar constructor function:
function SuperCar(name){
this.Name = name;
}
This works, but wait a second. Didn't we do exactly the same thing in the Car constructor? Don't want to repeat ourselves. Since Car sets the name already, let's just call it.
function SuperCar(name){
this = Car(name);
}
Whoops, you never want to change the special this object reference. Remember the 4 steps? Hang onto that object that JavaScript gave you, because it's the only way to keep the precious internal prototype link between your SuperCar object and Car. So how do we set Name, without repeating ourselves and without throwing away our fresh SuperCar object JavaScript spent so much special effort to prepare for us?
Two things. One: the meaning of this is flexible. Two: Car is a function. It's possible to call Car, not with a pristine, fresh instantiated object, but instead with, say, a SuperCar object. That gives us the final solution, which is part of the first example in your question:
function SuperCar(name){
Car.call(this, name);
}
As a function, Car is allowed to be invoked with the function's call method, which changes the meaning of this within Car to the SuperCar instance we're building up. Presto! Now each SuperCar gets its own Name property.
To wrap up, Car.call(this, name) in the SuperCar constructor gives each new SuperCar object its own unique Name property, but without duplicating the code that's already in Car.
Prototypes aren't scary once you understand them, but they're not much like the classic class/inheritence OOP model at all. I wrote an article about the prototypes concept in JavaScript. It's written for a game engine that uses JavaScript, but it's the same JavaScript engine used by Firefox, so it should all be relevant.
The two blocks differ in a way that in the first example Drive() will only exist once while at the second approach Drive() will exist per instance (Every time you do new Car() the function drive() will be created again). Or different said the first uses the prototype to store the function and the second the constructor. The lookup for functions is constructor and then prototype. So for your lookup of Drive() it finds it regardless if it is in the constructor or in the prototype. Using the prototype is more efficient because usually you need a function only once per type.
The new call in javascript automatically sets the constructor in the prototype. If you are overwriting the prototype so you have to set the constructor manually.
Inheritance in javascript has nothing like super. So if you have a subclass the only chance to call the super constructor is by its name.
Norbert, you should note that your first example is pretty much what Douglas Crockford calls pseudoclassical inheritance. Something things to note about this:
You will call the Car constructor twice, once from the SuperCar.prototype = new Car() line and the other from the "constructor stealing" line Car.call(this...you can create a helper method to inherit prototypes instead and your Car constructor will only have to run once making the setup more efficient.
The SuperCar.prototype.constructor = SuperCar line will allow you to use instanceof to identify the constructor. Some folks want this others just avoid using instanceof
Reference vars like: var arr = ['one','two'] when defined on the super (eg Car) will get shared by ALL instances. This means inst1.arr.push['three'], inst2.arr.push['four'], etc., will show up for all instances! Essentially, static behavior that you probably don't want.
You second block defines the fly method in the constructor. This means for every time that it's called, a "method object" will be created. Better to use a prototype for methods! You CAN however keep it in the constructor if you'd like - you just need to guard so you only actually initialize the prototype literal once (pseudo): if (SuperCar.prototype.myMethod != 'function')...then define your prototype literal.
'Why call Car.call(this, name)....': I don't have time to look carefully at your code so I may be wrong but this is usually so that each instance can keep it's own state to fix the 'staticy' behavior issue of prototype chaining that I described above.
Lastly, I'd like to mention that I have several examples of TDD JavaScript Inheritance code that works here: TDD JavaScript Inheritance Code and Essay I'd love to get your feedback as I'm hoping to improve it and keep it open source. The goal is to help classical programmers get up to speed with JavaScript quickly and also supplement the study both Crockford and Zakas books.
I am not 100% sure, but I believe the difference is that the second example simply duplicates the contents of the Car class into the SuperCar object, while the first links the SuperCar prototype to the Car class, so that run-time changes to the Car class affect the SuperCar class as well.
function abc() {
}
Prototype methods and property created for function abc
abc.prototype.testProperty = 'Hi, I am prototype property';
abc.prototype.testMethod = function() {
alert('Hi i am prototype method')
}
Creating new instances for function abc
var objx = new abc();
console.log(objx.testProperty); // will display Hi, I am prototype property
objx.testMethod();// alert Hi i am prototype method
var objy = new abc();
console.log(objy.testProperty); //will display Hi, I am prototype property
objy.testProperty = Hi, I am over-ridden prototype property
console.log(objy.testProperty); //will display Hi, I am over-ridden prototype property
http://astutejs.blogspot.in/2015/10/javascript-prototype-is-easy.html
There are several questions here:
Can you please explain the difference between the following blocks of code. I tested and both blocks work.
The first only creates one Drive function, the second creates two of them: one on myCar and another one on mySuperCar.
Here is code that would give different results when either the first or second block was executed:
myCar.Fly === mySuperCar.Fly // true only in the first case
Object.keys(myCar).includes("Fly") // true only in the second case
Object.keys(Car.prototype).length === 0 // true only in the second case
What's the best practice and why?
Why did the author add Drive and Fly methods using prototype, but doesn't declare them as this.Drive method inside Car class and this.Fly in SuperCar class?
It is better practice to define methods on the prototype, because:
each method is only defined once
each method is also available to instances that were created without executing the constructor (which is the case when calling Object.create(Car.prototype));
you can inspect at which level in an instance's prototype chain a certain method got defined.
Why does SuperCar.prototype.constructor need to be set back to SuperCar? Is constructor property overridden when prototype is set? I commented out this line and nothing changed.
The constructor property is not overridden when prototype is set. But the constructor of new Car() is Car, so if you set new Car() to SuperCar.prototype, then obviously SuperCar.prototype.constructor is Car.
As long as you don't reassign to prototype, there is an invariance: Constructor.prototype.constructor === Constructor. For example, this is true for Car: Car.prototype.constructor === Car, but it is equally true for Array, Object, String, ...etc.
But if you reassign a different object to prototype, that invariance is broken. Usually this is not a problem (as you have noticed), but it is better to reinstate it, because it answers the question "Which constructor uses this prototype object when creating new instances?" Some code may do such inspection and depend on it. See "Why is it necessary to set the prototype constructor?" for such cases.
Why call Car.call(this, name); in SuperCar constructor? Won't properties and methods of Car be 'inherited' when I do
var myCar = new Car("Car");
If you don't do Car.call(this, name); then your SuperCar instance will not have a name property. You could of course decide to just do this.name = name; instead, which just copies the code that is in the Car constructor, but in more complex situations it would be bad practice to have such code duplication.
It would not be helpful to call new Car(name) within the SuperCar constructor, as that will create another object, while you really need to extend the this object. By not using new (using call instead) you actually tell the Car function to not run as a constructor (i.e. to not create a new object), but to use the object you pass to it instead.
Times have changed
In modern versions of JavaScript you can use super(name) instead of Car.call(this, name):
function SuperCar(name) {
super(name);
}
Today, you would also use the class syntax and write the first code block from the question as follows:
class Car {
constructor(name) {
this.name = name;
}
drive() {
console.log(`My name is ${this.name} and I'm driving.`);
}
}
class SuperCar extends Car {
constructor(name) {
super(name);
}
fly() {
console.log(`My name is ${this.name} and I'm flying!`);
}
}
const myCar = new Car("Car");
myCar.drive();
const mySuperCar = new SuperCar("SuperCar");
mySuperCar.drive();
mySuperCar.fly();
Note how you don't even have to mention the prototype property to achieve the goal. The class ... extends syntax also takes care of setting the prototype.constructor property as the first block in your question did.

Categories

Resources