Using the constructor method in JS [duplicate] - javascript

This question already has answers here:
Why is it necessary to set the prototype constructor?
(14 answers)
Defining a Javascript prototype
(5 answers)
What is the `constructor` property really used for? [duplicate]
(2 answers)
Closed 9 months ago.
I'm learning classes in JS and I'm almost losing my mind with something that seems to be quite simple in OOP.
CONTEXT: I learned that creating a function with methods inserted directly into it will create an unnecessary accumulation of memory, because every time the class is instantiated each instance would have its own method occupying a different space in memory. To solve this we could access the prototype property of the function and put the methods directly there; however automatically every function has a prototype with a constructor property that points directly to the function and if I create a prototype from the outside I will overwrite the function's prototype and leave it without the constructor property, so I added this property directly to the prototype created manually.
QUESTION: my question is what is the difference of the function without the constructor property, as apparently the two codes worked similarly?
Code source: The Objective Programmer.
CODE WITH CONSTRUCTOR:
function Person (name){
this.name = name;
}
Person.prototype = {
constructor: Person,
sayName: function (){
console.log(this.name);
},
toString: function(){
return "[Person" + this.name + "]";
}
}
CODE WITHOUT CONSTRUCTOR:
function Person2 (name){
this.name = name;
}
Person2.prototype = {
sayName: function (){
console.log(this.name);
},
toString: function(){
return "[Person" + this.name + "]";
}
}

A seen on this section of the MDN docs on this topic, there won't be a difference here, as you're not technically changing the constructor on either object.
Where this would matter, however, is if you changed the constructor of the function. Take the following code snippet from the aforementioned MDN page:
function Parent() { /* ... */ }
Parent.prototype.parentMethod = function parentMethod() {}
function Child() {
Parent.call(this) // Make sure everything is initialized properly
}
Child.prototype = Object.create(Parent.prototype) // re-define child prototype to Parent prototype
Child.prototype.constructor = Child // return original constructor to Child
The important part of this figure is that at the end, you can see the Child.prototype.constructor is set BACK to it's original constructor, just like you're doing in your example with the Person function.

Related

Why is `this` keyword necessary in calling methods declared in Class declarations in Javascript? [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
How to access the correct `this` inside a callback
(13 answers)
Closed 3 months ago.
This post was edited and submitted for review 3 months ago and failed to reopen the post:
Original close reason(s) were not resolved
In the MDN Docs,
When a static or prototype method is called without a value for this, such as by assigning the method to a variable and then calling it, the this value will be undefined inside the method.
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
const obj = new Animal();
obj.speak(); // the Animal object
const speak = obj.speak;
speak(); // undefined
Animal.eat() // class Animal
const eat = Animal.eat;
eat(); // undefined
I dont understand that when we save a normal/static method reference to a variable, why do we lose the reference of this?
Also speak() is like a normal class method. Is this method said to be a prototype method in the text above?
As a solution, it is written:
If we rewrite the above using traditional function-based syntax in non–strict mode, then this method calls are automatically bound to the initial this value, which by default is the global object. In strict mode, autobinding will not happen; the value of this remains as passed.
And the code provided as a solution:
function Animal() { }
Animal.prototype.speak = function () {
return this;
}
Animal.eat = function () {
return this;
}
const obj = new Animal();
const speak = obj.speak;
speak(); // global object (in non–strict mode)
const eat = Animal.eat;
eat(); // global object (in non-strict mode)
“ then this method calls are automatically bound to the initial this value, which by default is the global object.” - in which line does the this method call take place?
Link : MDN Docs link

Weird behavior of constructor instance for prototype property [duplicate]

This question already has answers here:
How does JavaScript .prototype work?
(26 answers)
Closed 6 years ago.
Refer to the given example:
Code:
var Person = function (name) {
this.name = name;
}
var john = new Person("John");
console.log(Person.prototype);//Object{}
console.log(john.prototype); //undefined
Person is a function so its prototype would be derived from object so its understandable that it gives an Object in return (which further has Constructor & proto) as its properties.
Coming to second console statement. As, john is an instance of Person, therefore it must have the same prototype as Person has. Means, I should have got an object in return. How am I getting undefined? Can someone explain?
A class has a prototype, an instance of a class doesn't have a prototype.
The class has to make new instances, so it has a prototype in it. john does not have to instantiate new instances, so there is no reason for him to have a prototype.
If you really must have a prototype in the instance of the class, you can do this (assuming the function doesn't change name):
var Person = function (name) {
this.name = name;
this.prototype=Person.prototype;
}
Keep in mind, it's more of a quick hack than a solution, who knows when it will prove inconvenient.
I think this question and this question will help you.
"Instances" doesn't have prototypes, they're linked to them via internal [[Prototype]], which is not accessible. Also there is a property named __proto__ which is non standard (not reliable), but points to prototype.

What is the best practice when it comes to making constructor functions in JavaScript? [duplicate]

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 7 years ago.
So I've been trying to figure out prototypal inheritance in Javascript and I'm still confused on one point. Let's say I want to make a constructor function for a person with a few functions of it's own.
function Person(name) {
this.name = name;
this.sayName = function() {
console.log("My name is " + name);
}
}
var john = new Person("John");
john.sayName();
So in this case I've created an object and called a function, however this doesn't seem to be the efficient way to do it. Another example I've seen this is this:
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log("My name is " + name);
}
var john = new Person("John");
john.sayName();
Now I've read that the second object is more efficient because it's not storing the sayName function within itself, instead it's going up the prototype chain until it finds it within Persons prototype object.
What I'm unsure about is which I should use for complicated constructor functions. The first snippet, in my opinion, is much much easier to read than the second because there is a clear hierarchical structure to it, but the second snippet is supposedly more efficient.
In a real world scenario, which style of constructor function would I be more likely to use?
Edit: I have a follow up question. Is there any way to make the second snippet more readable?
Generally if you are going to have a class from which several instances will be created, you should add the methods to the prototype object. The main reason I believe is that all the instances of a class would reference the prototype object, and won't copy it. So if the prototype object changes, it would be reflected in the prototype object referenced by all the instances.
This is better than the first option where each method is created (copied) on each instance. And so a lot of instances would also mean a lot of those methods will be created, occupying memory. But in the second option, they all use the single method created on the prototype object.
if you use the first one , you'll be creating a new function object for sayName each time the constructor is called, while in the second way you avoid that overhead.
if you use a reference type in your constructor it will be shared,
for ex :
function Person(name){
this.name = name;
this.hobbies = [..some hobbies];
}
now hobbies will be shared by every object you create with this constructor , so it's best to put shared properties on prototype and only use unique one's in the constructor
In the first approach will create method function for every single instance. In the second one, all instances share the method defined in the prototype. So the second approach is better because of saving memory.
However, ECMAScript 6 is officially released several months ago, so why not try class:
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log("My name is " + this.name);
}
}
var john = new Person("John");
john.sayName(); // "My name is John"
The feature is not well supported yet, if you want backward compatibility in browsers, use Babel.
Another syntax introduced in ECMAScript 5 for create instances of Classes is:
Object.create(prototype [, propertiesObject ] )
Example:
var MyClass = function (param) {
this.field1 = param;
}
MyClass.prototype.changeField = function(param){
this.field1 = param;
}
var instance = Object.create(MyClass.prototype);
If you are interested in learn advanced things about javascript I suggest a book called "Mastering Javascript design patterns".

What’s the purpose of prototype? [duplicate]

This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 2 years ago.
Possible Duplicate:
Use of 'prototype' vs. 'this' in JavaScript?
OK, So I am somewhat new to the idea of OOP in JS.
What is the difference between these two snippets of code written below:
function animal(){
this.name = 'rover';
this.set_name = function(name){
this.name = name;
}
}
function animal(){
this.name = 'rover';
}
animal.prototype.set_name = function(name){
this.name = name;
}
They both do the same thing, so what’s the difference?
Using the prototype makes faster object creation since properties/methods on the prototype don't have to be re-created each time a new object is created.
When you do this:
function animal() {
this.name = 'rover'
this.set_name = function (name) {
this.name = name
}
}
The set_name method is created every time you create an animal. But when you do this
animal.prototype.set_name = function (name) {
this.name = name
}
The method does not have to be re-created each time; it exists in one place in the prototype. So when you call someAnimal.set_name("Ubu"); the this context will be set to someAnimal and (the one and only) set_name method will be called.
There is one advantage to using the first syntax though: methods created in this manner will have access to private data:
function animal() {
var privateData = 'foo'
this.name = 'rover'
this.set_name = function (name) {
this.name = name
alert(privateData) //will alert 'foo'
}
}
Douglas Crockford calls methods created like this "privileged" for that reason: they have access to both public and private data.
The difference appears when you create new object from these function
var animal1 = new animal();
All objects created by the first function will have different name and set_name properties. However, all objects created by the second function will share the set_name property.
In the first example, each separate animal has an own property for the set_name function, while in the second example they share the same function via their prototype.
The advantage of the first version is that the methods can access local (private) variables declared inside the constructor.
The advantage of the second method is that it needs less memory (since you only store the method once instead of a million times) and is more performatic in current JS engines.
Using the second method you can also modify or add methods to a class in a way that also affects instances that were already created.

JavaScript prototype function not overriding the original one

Learning javascript when I came across the concept of prototype. I succeeded in adding new methods to the cat class but failed in overriding the original talk method.
function cat(name) {
this.name = name;
this.talk = function() {
alert( this.name + " : I'm a girl!" )
}
}
cat.prototype.talk = function() {
alert( this.name + " : I'm a dude!" )
}
cat1 = new cat("felix")
cat1.talk()
Why doesn't this alert the new text?
‘function cat’ is just a function. Its prototype is an empty Object ({}). ‘new cat’ can be called to add members ‘name’ and ‘talk’ to a new Object. Beneath that new Object will be the function prototype, which is still {}.
var c= new cat('Tiddles');
c ownProperties: { 'name': 'Tiddles', 'talk': function() {...} }
c inherited: {}
Now when you write to ‘cat.prototype.talk’, you are adding members to that underlying object:
c ownProperties: { 'name': 'Tiddles', 'talk': function() {...} }
c inherited: { 'talk': function() {...} }
The ‘talk’ function set directly on the instance ‘c’ takes precedence over the ‘talk’ set indirectly on c's constructor prototype.
So you've mixed up two styles of inheritance here, the ‘this’-assigning method and the ‘prototype’ method.
Writing methods to prototypes has the advantage that you don't get redundant copies of the same members copied into every object instance; writing to instances has the advantage that it resolves the problem of bound methods. Which one you choose is up to you, but don't mix the two. If you want to go the prototype route, only ‘name’ should be written to ‘this’, because that's the only property that's specific to each instance.
the function attached in the beginning is attached to the object (1 function for each instance). the other one is attached to the prototype (1 function shared by all instances).
members at the object level override those at the prototype level.

Categories

Resources