Defining a constructor for a derived class in Javascript - javascript

Conventional wisdom is that to simulate OOP in Javascript, we do everything in terms of functions and prototypes:
var fooObject = function () {
//Variables should be defined in the constructor function itself,
//rather than the prototype so that each object will have its own variables
this.someProperty = 5; //Default value
};
//Functions should be defined on the prototype chain so that each object does not
//have its own, separate function methods attached to it for performing the same
//tasks.
fooObject.prototype.doFoo = function () {
//Foo
}
Now, to create a derived class, we do:
var derivedFromFoo = new foo();
But what happens if we want to do some other stuff in our constructor for the derived object? Like set other properties? Can we do something like
var derivedFromFoo = function () {
this = new foo();
};

new foo();
That's an instance, not a class.
To create a derived class, you need to make a new function, call the base ctor from inside of it, then set the new function's prototype to an object created from the base prototype:
function Derived() {
Base.call(this);
}
Derived.prototype = Object.create(Base.prototype);
For more details, and a longer, more-correct implementation, see my blog post.

Related

Is it possible to append a method to a constructor/function without prototype property?

function DoIHavePrototype()
{
var a = 10;
}
CheckIt = new DoIHavePrototype();
DoIHavePrototype.prototype.GetFnName = function()
{
return "DoIHavePrototype"
}
alert(CheckIt.GetFnName())
In the above code,I observe that prototype is an in-built property for the function using which we can append property/method to a function.
But if I remove the prototype keyword in the above code like the following:
DoIHavePrototype.GetFnName = function()
{
return "DoIHavePrototype"
}
I don't get error in function definition but instead I get error while calling the method
alert(CheckIt.GetFnName()) as "CheckIt.GetFnName is not a function"
What does the JS interpreter assume this to be??
In order to be able to invoke some function a method on an object, there are 4 ways to introduce it to the object.
The first way is what you've done in your original code, which is to assign the function to the object prototype:
Foo.prototype.myFunc = function () { .... }
Another way is to assign it to this within the constructor.
function Foo() {
this.myFunc = function () { .... }
}
We can also assign it directly to the instance:
var foo = new Foo();
var myFunc = function () { .... }
foo.myFunc = myFunc
Finally, we can bind a function to the instance:
var foo = new Foo();
var myFunc = function () { .... }
var myFuncFoo = myFunc.bind(foo)
The last case is a bit special since we have a function that's not a property of the instance, but behaves like an instance method because it's invocation context is affixed to the instance.
The most common way of defining instance methods is assignment to the prototype. The prototype property on the constructor is what the instances inherit from, so that's where we put stuff. It's important to keep in mind that the instances inherit from the prototype property, not the constructor function. Assigning anything to a constructor property does not make it available as an instance property.
Assignment to this can sometimes be used if we want to have a method that's bound. For instance:
function Foo() {
this.boundMeth = this.meth.bind(this)
this.val = "foo"
}
Foo.prototype.meth = function () {
console.log(this.val)
}
This is useful if we want to pass instance.boundMeth() as a value to another function (e.g., event handler). In JavaScript, unlike many OO languages, methods are unbound:
// Using Foo from the previous example
function runner(fn) {
fn()
}
var obj = new Foo()
runner(obj.meth) // Logs `undefined`
runner(obj.boundMeth) // Logs `foo`
When assigning to the constructor prototype, you can assign in bulk:
Foo.prototype = {
meth1: function () { .... },
meth2: function () { .... },
}
If you use ES6, you can also use the class keyword:
class Foo {
myFunc() { .... }
}
This is the same as Foo.prototype.myFunc = function () { .... }.
If you append your function straight to the class it will generate so called static method which you can only call from you class like in Array.from.
So in your case you should call it using you class (not its instances) like so DoIHavePrototype.GetFnName();
you can read about this on MDN
This can also be done, in case if you still want to use it as instance method.
function DoIHavePrototype()
{
var a = 10;
this.GetFnName = function() {
return "DoIHavePrototype";
}
}
CheckIt = new DoIHavePrototype();
alert(CheckIt.GetFnName())

How to access a property on a function?

I am just starting to learn Javascript and was experimenting with functions. I wrote the following thinking that it would work. Is something like this possible or is it just wrong?
function foo() {
console.log(this.language);
}
foo.language = "English";
foo();
It is not possible, because to gain access to this as the current object, you'll need to instantiate the (constructor) function, which is what invoking new will do for you. Accessing this for a reference to the current instance is not only the case in Javascript though; in Java, this also isn't accessible from static context.
What you're looking for is something like:
function Foo(language) {
this.language = language;
}
Foo.prototype.log = function(){
console.log(this.language);
}
var bar = new Foo("English");
bar.log();
You can make a foo object (an instance of foo) using the new keyword. Then set the language property of that instance. If foo has a function to output its language property, then you can invoke that function on your instance to see its language.
function foo() {
this.outputLanguage = function() {
console.log(this.language);
}
}
var f1 = new foo();
f1.language = "English";
var f2 = new foo();
f2.language = "French";
f1.outputLanguage();
f2.outputLanguage();
In this example, we make 2 foo objects, and assign each a different language.
The foo() function is a constructor function. We usually pass the initial values of the instance variables to it, like this:
function foo(language) {
this.language = language;
this.outputLanguage = function() {
console.log(this.language);
}
}
var f1 = new foo("English");
var f2 = new foo("French");
f1.outputLanguage();
f2.outputLanguage();
Javascript only supports prototypal Inheritance. So to assign a property (in your case language is the property) to an Object (in your case foo) you need to use constructor. And by convention constructor are written Initcap.
function Foo(lang){
this.language = lang;
}
Foo.prototype.getLanguage = function(){
return this.language;
}
var lang1 = new Foo('english');
var lang2 = new Foo('bengali');
console.log(lang1.getLanguage()); // english
console.log(lang2.getLanguage()); // bengali
this is available on instance variables, in your case it's named function
function foo() {
console.log(foo.language); //instead of this, use function property
}
foo.language = "English";
foo();
If you want to dive more, checkout my other answer for the same topic

Difference between methods of defining JavaScript 'classes'

What's the difference between these two method of defining a 'class' in JavaScript?
Method One
Define method within the constructor:
function MyClass()
{
this.foo = function() { console.log('hello world!'); };
}
Method Two
Define method on the prototype:
function MyClass()
{}
MyClass.prototype.foo = function() { console.log('hello world!'); };
The first will create a new function object on each instantiation of your object, the second will assign a reference to a prototype method to each instance. In short: the second is more efficient, because all instances will share a single function object.
That's just the logic of a prototype chain, you can try and access anything via any object:
var objLiteral = {foo:'bar'};
When accessing objLiteral.foo JS will first look at the properties that the object itself has defined, and return the value if it is found. If JS can't find the property on the object itself, it'll check the object's prototype, hence:
objLiteral.valueOf();//method defined #Object.prototype
objLiteral.valueOf === Object.prototype.valueOf //true
But when you use your first method:
function SomeConstructor()
{
this.methd = function()
{
return true;
}
}
var f = new SomeConstructor();
var g = new SomeConstructor();
f.methd === g.methd;//FALSE!
That shows that we're dealing with 2 separate function objects. Move the function definition to the prototype and f.methd === g.methd; will be true:
function SomeConstructor()
{
}
SomeConstructor.prototype.methd = function()
{
return true;
}
var f = new SomeConstructor();
var g = new SomeConstructor();
f.methd === g.methd;//true!
In response to your comment:
Defining a method on a prototype-level allows you to change a method for a specific task, and then "reset" it back to it's default behaviour. Suppose you're in a function that's creating an AJAX request:
someObject.toString = function(){ return JSON.stringify(this);}
//when concatinating this object you'll get its json string
//do a lot of stuff
delete (someObject.toString);
Again JS will check if the object has the toString property defined on itself, which it has. So JS will delete the function you've assigned to the toString property. Next time the toString will be invoked, JS will start scanning the prototype chain all over again, and use the first occurance of the method (in the prototype). Let's clarify:
function SomeConstructor()
{
}
SomeConstructor.prototype.methd = function()
{
return true;
}
var f = new SomeConstructor();
var g = new SomeConstructor();
f.methd = function(){return false;};
g.methd();//returns true, still <-- method is gotten from the prototype
f.methd();//returns false <-- method is defined # instance level
delete (f.methd);
f.methd();//returns true, f doesn't have the method, but the prototype still does, so JS uses that.
Or even better, you can even replace an instance's method by a method from another prototype:
f.methd = Object.prototype.valueOf;//for as long as you need
the last example is pointless, because f has the valueOf method already: its inheritance chain looks like this: var f ---> SomeConstructor ---> Object, giving you access to all Object.prototype methods, too! Neat, isn't it?
These are just dummy examples, but I hope you see this is one of those features that make JS an incredibly flexible (sometimes too flexible, I must admit) and expressive language.
In first case the function will be created for each instance and set to the foo property in the object. In second case it is shared function. When you call obj.prop then it looks for it in object itself, if it is not there, then it looks for it in proto object and so on, it is called chain of prototypes.
For example this code provides foo:
function MyClass() {
this.foo = function () {};
}
var myVariable = new MyClass();
for (var i in myVariable) if (myVariable.hasOwnProperty(i)) console.log(i);
But this not:
function MyClass() {
}
MyClass.prototype.foo = function () {};
var myVariable = new MyClass();
for (var i in myVariable) if (myVariable.hasOwnProperty(i)) console.log(i);

A few questions about Javascripts Prototype

I am coming at Javascript from a classical OOP background and am having trouble with understanding the prototype.
Given the code example below:
How would I call/execute bar in foo?
why use the "privileged" function instead of putting it on the prototype?
This is probably answered in Q1 but can bar1 and bar2 call each other?
function foo()
{
this.property = "I'm a property";
this.privileged = function()
{
// do stuff
}
}
foo.prototype.bar = function()
{
// do stuff
}
foo.prototype.bar2 = function()
{
// stuff
}
There's a lot of FUD about this to this day.
1). Simple usage:
var xxx = new foo(); // Create instance of object.
xxx.privileged(); // Calls the internal closure.
xxx.bar(); // First looks for internals, then looks to the prototype object.
2). This basically creates a closure that can only be modified on the instance. Not a private at all (since anything can talk to it through the object instance), but rather an individual copy of a function, where each instance of the object gets a new copy of the function. You can alter the function itself, but you cannot alter it globally. I'm not a big fan of this method of creating things.
3). Yes:
foo.prototype.bar = function(){
this.bar2();
}
foo.prototype.bar2 = function(){
this.bar();
}
// Although... NEVER do both. You'll wind up in a circular chain.
For edification, I built you a fiddle which should help show how things get called:
http://jsfiddle.net/7Y5QK/
1) frist is some as Clyde Lobo's an answer:
var f = new foo();
f.bar();
2) write a function on consturctor (privileged), every instance will create a new one, if defined a method on prototype, every instance share the same prototype's method:
var f1 = new foo(), // instance 1
f2 = new foo(); // instance 2
f1.privileged === f2. privileged // -> false , every instance has different function
f1.bar === f2.bar // -> true, every instance share the some function
3) You can call bar2 in bar' bythis.bar()`, code like this:
function foo() {
this.property = "I'm a property";
this.privileged = function() {
// do stuff
};
}
foo.prototype.bar = function() { // defined a method bar
alert('bar called');
this.bar2(); // call bar2
};
foo.prototype.bar2 = function() { // defined a method bar2
alert('bar2 called');
};
var f = new foo();
f.bar(); // alert 'bar called' and 'bar2 called'
f.bar2(); // alert 'bar2 called'
You can execute bar in foo by doing this.bar();
but it will only work if you use new foo(); and have an object inheriting from foo. Otherwise, if you just call foo();, this will point to the global object.
It's essentially the same thing only the properties and methods you give the inheriting object inside the function have access to any arguments you pass to foo.
Yes, they can call each other since functions are "hoisted". They have access to all the variables and objects in their nearest outer scope, and in their functional context.
You actually have syntax errors in your code. Where you were assigning the prototype you didn't create a function. You meant:
foo.prototype.bar = function() { /* ... */ };
1.You can create an instance of foo like
var f = new foo();
and then call f.bar() and f.bar2()
points 2 & 3 are already explained by David

Setting javascript prototype function within object class declaration

Normally, I've seen prototype functions declared outside the class definition, like this:
function Container(param) {
this.member = param;
}
Container.prototype.stamp = function (string) {
return this.member + string;
}
var container1 = new Container('A');
alert(container1.member);
alert(container1.stamp('X'));
This code produces two alerts with the values "A" and "AX".
I'd like to define the prototype function INSIDE of the class definition. Is there anything wrong with doing something like this?
function Container(param) {
this.member = param;
if (!Container.prototype.stamp) {
Container.prototype.stamp = function() {
return this.member + string;
}
}
}
I was trying this so that I could access a private variable in the class. But I've discovered that if my prototype function references a private var, the value of the private var is always the value that was used when the prototype function was INITIALLY created, not the value in the object instance:
Container = function(param) {
this.member = param;
var privateVar = param;
if (!Container.prototype.stamp) {
Container.prototype.stamp = function(string) {
return privateVar + this.member + string;
}
}
}
var container1 = new Container('A');
var container2 = new Container('B');
alert(container1.stamp('X'));
alert(container2.stamp('X'));
This code produces two alerts with the values "AAX" and "ABX". I was hoping the output would be "AAX" and "BBX". I'm curious why this doesn't work, and if there is some other pattern that I could use instead.
EDIT: Note that I fully understand that for this simple example it would be best to just use a closure like this.stamp = function() {} and not use prototype at all. That's how I would do it too. But I was experimenting with using prototype to learn more about it and would like to know a few things:
When does it make sense to use prototype functions instead of closures? I've only needed to use them to extend existing objects, like Date. I've read that closures are faster.
If I need to use a prototype function for some reason, is it "OK" to define it INSIDE the class, like in my example, or should it be defined outside?
I'd like to understand why the privateVar value of each instance is not accessible to the prototype function, only the first instance's value.
When does it make sense to use prototype functions instead of closures?
Well, it's the most lightweight way to go, let's say you have a method in the prototype of certain constructor, and you create 1000 object instances, all those objects will have your method in their prototype chain, and all of them will refer to only one function object.
If you initialize that method inside the constructor, e.g. (this.method = function () {};), all of your 1000 object instances will have a function object as own property.
If I need to use a prototype function for some reason, is it "OK" to define it INSIDE the class, like in my example, or should it be defined outside?
Defining the members of a constructor's prototype inside itself, doesn't makes much sense, I'll explain you more about it and why your code doesn't works.
I'd like to understand why the privateVar value of each instance is not accessible to the prototype function, only the first instance's value.
Let's see your code:
var Container = function(param) {
this.member = param;
var privateVar = param;
if (!Container.prototype.stamp) { // <-- executed on the first call only
Container.prototype.stamp = function(string) {
return privateVar + this.member + string;
}
}
}
The key point about your code behavior is that the Container.prototype.stamp function is created on the first method invocation.
At the moment you create a function object, it stores the current enclosing scope in an internal property called [[Scope]].
This scope is later augmented when you call the function, by the identifiers (variables) declared within it using var or a FunctionDeclaration.
A list of [[Scope]] properties forms the scope chain, and when you access an identifier (like your privateVar variable), those objects are examined.
And since your function was created on the first method invocation (new Container('A')), privateVar is bound to the Scope of this first function call, and it will remain bound to it no matter how do you call the method.
Give a look to this answer, the first part is about the with statement, but in the second part I talk about how the scope chain works for functions.
Sorry for resurrecting an old question, but I wanted to add something that I recently discovered somewhere else here on SO (looking for the link, will edit/add it once I find it): found it.
I personally like the below methodology because I can visually group all my prototype and 'instance' definitions together with the function definition, while avoiding evaluating them more than once. It also provides an opportunity to do closures with your prototype methods, which can be useful for creating 'private' variables shared by different prototype methods.
var MyObject = (function () {
// Note that this variable can be closured with the 'instance' and prototype methods below
var outerScope = function(){};
// This function will ultimately be the "constructor" for your object
function MyObject() {
var privateVariable = 1; // both of these private vars are really closures specific to each instance
var privateFunction = function(){};
this.PublicProtectedFunction = function(){ };
}
// "Static" like properties/functions, not specific to each instance but not a prototype either
MyObject.Count = 0;
// Prototype declarations
MyObject.prototype.someFunction = function () { };
MyObject.prototype.someValue = 1;
return MyObject;
})();
// note we do automatic evalution of this function, which means the 'instance' and prototype definitions
// will only be evaluated/defined once. Now, everytime we do the following, we get a new instance
// as defined by the 'function MyObject' definition inside
var test = new MyObject();
You need to put the function on each specific instance instead of the prototype, like this:
Container = function(param) {
this.member = param;
var privateVar = param;
this.stamp = function(string) {
return privateVar + this.member + string;
}
}
To get the behavior you want you need to assign each individual object separate stamp() functions with unique closures:
Container = function(param) {
this.member = param;
var privateVar = param;
this.stamp = function(string) {
return privateVar + this.member + string;
}
}
When you create a single function on the prototype each object uses the same function, with the function closing over the very first Container's privateVar.
By assigning this.stamp = ... each time the constructor is called each object will get its own stamp() function. This is necessary since each stamp() needs to close over a different privateVar variable.
That is because privateVar is not a private member of the object, but part of stamp's closure. You could get the effect by always creating the function:
Container = function(param) {
this.member = param;
var privateVar = param;
this.stamp = function(string) {
return privateVar + this.member + string;
}
}
The value of privateVar is set when the function is built, so you need to create it each time.
EDIT: modified not to set the prototype.

Categories