Jump to content
NotionCommotion

Constructor for a function object

Recommended Posts

Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model, I have a SalesPerson which extends Employee as shown below.

What is the purpose of these two lines?  It doesn't seem to have any effect.

SalesPerson.prototype = Object.create(Employee.prototype);
SalesPerson.prototype.constructor = SalesPerson;

Also, why would one wish to add in the SalesPerson function such as method2() versus adding them afterwards using prototype such as method3()?

Thanks

function Employee(foo) {
    this.foo = foo;
    this.name = '';
    this.dept = 'general';

    this.method1=function(){
        console.log('method1: '+this.foo);
    }
}

function SalesPerson(foo, bar) {
    Employee.call(this, foo);
    this.bar = bar;
    this.dept = 'sales';
    this.quota = 100;

    this.method2=function(){
        console.log('method2: '+this.bar);
    }
}
//What is the purpose of these two lines?
SalesPerson.prototype = Object.create(Employee.prototype);
SalesPerson.prototype.constructor = SalesPerson;

SalesPerson.prototype.method3=function() {
    console.log('method3: '+this.bar);
}

function Engineer(foo, bar) {
    Employee.call(this, foo);
    this.bar = bar;
    this.dept = 'sales';
    this.quota = 100;
}
Engineer.prototype = Object.create(Employee.prototype);
Engineer.prototype.constructor = Engineer;

salesPerson = new SalesPerson('foo', 'bar');
salesPerson.method1();
salesPerson.method2();
salesPerson.method3();

 

Share this post


Link to post
Share on other sites
5 hours ago, NotionCommotion said:

What is the purpose of these two lines?  It doesn't seem to have any effect.


SalesPerson.prototype = Object.create(Employee.prototype);
SalesPerson.prototype.constructor = SalesPerson;

 

Not with the way your code is written, no. I trust you're familiar with prototyping? Employee and SalesPerson both set up their methods through assignment. It works, but it's not modern Javascript.

Using prototyping the code would be

function Employee(foo) {
    this.foo = foo;
    this.name = '';
    this.dept = 'general';
}
Employee.prototype.method1 = function() {
	console.log('method1: ' + this.foo);
}

Now see what happens with and without those two lines.

6 hours ago, NotionCommotion said:

Also, why would one wish to add in the SalesPerson function such as method2() versus adding them afterwards using prototype such as method3()?

Using a prototype gives you "inheritance" without any additional work. There's one copy of the method2 function around and everybody uses it. With the older style, every single instance has its own separate method2.

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, requinix said:

I trust you're familiar with prototyping? Employee and SalesPerson both set up their methods through assignment. It works, but it's not modern Javascript.

Not too familiar with anything JavaScript.  Do you mean my approach of placing methods in Employee is not modern JavaScript or prototyping isn't?

1 hour ago, requinix said:

Now see what happens with and without those two lines.

I see.  I was using prototyping for some of the SalesPerson's methods but not for Employee's and thus didn't see it.  I take it that Employee.call(this, foo) is still applicable, true?

1 hour ago, requinix said:

There's one copy of the method2 function around and everybody uses it. 

And how does one get it?  Something like the following?

var myLibrary={
    method1: function() {console.log('method1: ' + this.foo);},
    method2: function() {console.log('method2: ' + this.foo);},
    method3: function() {console.log('method3: ' + this.foo);}
};

Employee.prototype.method1 = myLibrary.method2;


Thanks!

Share this post


Link to post
Share on other sites

I could write a huge reply, but it'll be easier for me to just point you to MDN.

Share this post


Link to post
Share on other sites

I had been reviewing that source as well as several others with similar information.   It becomes confusing due to Javascript's multiple wildly differing approaches to accomplish similar goals which is further complicated with different tutorials, and I will limit myself to just that one for now.

Can you comment or point me in the right direction how one allows a single copy of a function to be available for everybody to use?. 

Share this post


Link to post
Share on other sites
55 minutes ago, NotionCommotion said:

Can you comment or point me in the right direction how one allows a single copy of a function to be available for everybody to use?. 

By putting it in the prototype instead of directly on the object instance. Using the prototype means everyone calls the same function, literally, while putting it on the instance means everybody is calling their own version of the function.

Or are you asking how that mechanism works?

Share this post


Link to post
Share on other sites
12 hours ago, NotionCommotion said:

why would one wish to add in the SalesPerson function such as method2() versus adding them afterwards using prototype such as method3()?

One reason people would define methods in the constructor rather than on the prototype is to simulate private properties.  In Javascript all properties are public so anything you attach to an object could be manipulated by other code.  To work around that people would keep these "private properties" as regular variables inside the constructor rather than as actual properties on the object.  In order to do that and still access them from the methods, the methods need to be defined in the constructor so they can access the constructors variable scope.

function Counter(){
	var count = 0;
	this.increment = function(){
		count++;
	};
	this.decrement = function(){
		count--;
	};
	this.current = function(){
		return count;
	};
}

As mentioned, one downside to this is that each instance of the object ends up with it's own instance of the function rather than a single instance being shared.   On modern desktops with lots of memory that's probably not an issue unless your creating many thousands of instances of the object.  However on older systems or mobile systems with less memory it can cause issues much faster.

 

Share this post


Link to post
Share on other sites
13 hours ago, requinix said:

Or are you asking how that mechanism works?

Kind of.  Or more so how to allow everyone to get a copy of a given function.

I can do the following, but it doesn't seem right:

var method1=function() {console.log('method1: ' + this.foo);};
var method2=function() {console.log('method2: ' + this.foo);};
var method3=function() {console.log('method3: ' + this.foo);};

Employee.prototype.method1 = method2;
SomethingElse.prototype.method1 = method2;

This is a little better, but still doesn't seem right:

var myLibrary={
    method1: function() {console.log('method1: ' + this.foo);},
    method2: function() {console.log('method2: ' + this.foo);},
    method3: function() {console.log('method3: ' + this.foo);}
};

Employee.prototype.method1 = myLibrary.method2;
SomethingElse.prototype.method1 = myLibrary.method2;

Another approach is as follows but still expect it is not right:

var myLibrary=function(){
    var methods={
        method1: function() {console.log('method1: ' + this.foo);},
        method2: function() {console.log('method2: ' + this.foo);},
        method3: function() {console.log('method3: ' + this.foo);}
    };
    if(typeof methods[method] === 'undefined') {
        throw method+" does not exist";
    }
    return method[method];
}(method);

Employee.prototype.method1 = myLibrary('method2');
SomethingElse.prototype.method1 = myLibrary('method2');

While  there is a million ways to do so, I expect there is a de facto standard way to do so.

Share this post


Link to post
Share on other sites
Posted (edited)

Just adding it to the prototype means every instance of the object will share the same instance of the function.

Given code like this:

function Employee(foo) {
    this.foo = foo;
    this.name = '';
    this.dept = 'general';
}

Employee.prototype.method1 = function(){
    console.log('Method1 called');
};

function SalesPerson(foo, bar) {
    Employee.call(this, foo);
    this.bar = bar;
    this.dept = 'sales';
    this.quota = 100;
}

SalesPerson.prototype = Object.create(Employee.prototype);
SalesPerson.prototype.constructor = SalesPerson;

SalesPerson.prototype.method2=function() {
    console.log('Method 2 called');
}

When you this:

var p = new SalesPerson();
p.method1();

Javascript looks up method1 by roughly doing:

  1. Does p have a property named method1? => No
  2. Does SalesPerson.prototype have a property named method1? => No
  3. Does SalesPerson.prototype.prototype (Which is Employee.prototype) have a property named method1? => Yes
  4. Execute SalesPerson.prototype.prototype.method1.call(p);

So only one instance of the method1 function exists on the Employee.prototype object, it's just reused for the other objects.

You can see this kind of chain if you console.log(p):

prototype.png.437f257cc08527cd2a029ba777a8c48e.png

 

If you want to share a single function across multiple objects that are not related via their prototype chain, then you'd do define your function elsewhere and assign a reference to it to each object.  This kind of setup is often called a mixin. For example if you had some logging code you wanted to include in each class.

var LoggerInterface = {
    log: function(msg){
        console.log(msg);
    }
};


function Employee(foo) {
    this.foo = foo;
    this.name = '';
    this.dept = 'general';
}

Object.assign(Employee.prototype, LoggerInterface);
Employee.prototype.method1 = function(){
    this.log('Method1 called');
};


function Equipment(){
    this.name = '';
}

Object.assign(Equipment.prototype, LoggerInterface);
Equipment.prototype.method2 = function(){
    this.log('Method2 called');
}

Both Employee and Equipment would have their own independent .log properties, but they would both reference the same underlying function so the function itself isn't duplicated.

 

Edited by kicken
  • Like 1

Share this post


Link to post
Share on other sites
On 4/18/2020 at 10:02 AM, kicken said:

If you want to share a single function across multiple objects that are not related via their prototype chain, then you'd do define your function elsewhere and assign a reference to it to each object.  This kind of setup is often called a mixin. For example if you had some logging code you wanted to include in each class.

Thanks kicken,  That is exactly what I was asking about.  And now I even know what to call it (i.e. "mixin").

And also thanks to both of you regarding the other prototype help.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.