So I define classes by using their constructor functions, and in these functions I define all their properties, and do constructor-y things like setting up listeners and such. After defining the constructor, I then go and add all of it's functions directly to its prototype.
To do inheritance, I essentially do this:
namespace.Class = function(param) {
namespace.BaseClass.call(this, param);
//Other constructor stuff
}
namespace.Class.prototype = new namespace.BaseClass();
namespace.Class.constructor = namespace.Class;
The problem is that the BaseClass' constructor gets called when creating the prototype, which causes the prototype to be an instance of that type. This may not be a problem, but it just feels "messy" and performance lagging, and potentially buggy because I have to check if the params are defined.
So my question is: Is it possible to extend a base class without calling its constructor? Or will I have to use tricks such as checking if param is undefined, or using a loop to do stuff?
Sorry if I've missed the whole point of prototypal inheritance, I am being taught Java in uni, and Java doesn't approve of this type of stuff.
Yes it is possible. The preferred way is to use Object.create [MDN]:
namespace.Class.prototype = Object.create(namespace.BaseClass.prototype);
This creates a new, empty object which inherits from BaseClass.prototype, which is all you need at this point.
This is a much cleaner solution than creating an instance of the parent class, because, as you already mentioned, if the super class expects arguments, you don't know which ones to pass.
Related
So I'm trying to wrap my head around the different ways to create an object.
I came accross the Protoype pattern for creating objects.
Now I wrote two functions below but I can't see what the functional difference between both would be? When would you use the Constructor pattern and when would you use the Prototype pattern?
Constructor Pattern
function Fruit(){}
Fruit.color = "Yellow",
Fruit.fruitName = "Banana",
Fruit.nativeTo = "SomeValue"
Prototype Pattern
function Fruit(){}
Fruit.prototype.color = "Yellow",
Fruit.prototype.fruitName = "Banana",
Fruit.prototype.nativeTo = "SomeValue"
Reusability of the components...
Constructor
When you create a new constructor you will create a new instance of everything and importantly any change made to the instances will only affect them and not the others.
Prototype
When you create a new object using the prototype it will reuse the logic and any change to the prototype chain will affect everyone else.
This is a nice explanation: Javascript prototypes and instance creation
When to use each pattern is based on needs - very ambiguous answer but never-the-less the situation.
Think of the Object, Function, Array they are used throughout JS and would make sense that they live on the prototype chain as any changes we have to them we would want to propagate - a side note: which is why we should never alter these as it can screw up their behavior.
Best explanation here: JavaScript constructors, prototypes, and the new keyword
Change in properties of prototype will apply to all the instances including already exist , where as change in property that was created by constructor will only change it for the instance
Constructor
Basically constructor is used to create an object with new operator.
It used to initialize the instance properties of the constructor.So,constrctor with new is nothing but the implementation of class that Object oriented language like C++,JAVA have.
Every constructor has propertied prototype which hold the reference to constructor.
Prototype
JavaScript lack Class based inheritance.
In JavaScript to implement inheritance,we used Prototype which used to implement single level of inheritance.
So,to achieve code re-usability in JavaScript,prototype is used.It is nothing but prototypical inheritance.
In prototypical inheritance, method or properties added on prototype is immediately available to object created from same constructor
Constructor pattern:
Constructor pattern is one of the most popular way of creating Objects in JS.
The disadvantage is that for every object we create a copy of the functions gets created which is very inefficient way.
Prototype in JS:
Its a shared area for every object where if you add something then its readily available to all the objects created from same constructor.
Prototype Pattern:
Prototype Pattern is an enhanced way of writing Constructor pattern where we move the functions from the Constructor to the Constructor prototype. (We do it because of the disadvantages explained in constructor pattern above)
Now coming back to use initial questions ==> "When would you use the Constructor pattern and when would you use the Prototype pattern?"
If we have to create simple objects with no functions then Constructor pattern is good to go but if there are functions then Prototype pattern will be efficient way.
In the past when creating "classes" in JavaScript, I have done it like this:
function Dog(name){
this.name=name;
this.sound = function(){
return "Wuf";
};
}
However, I just saw someone do it like this instead:
var Dog = (function () {
function Dog(name) {
this.name = name;
}
Dog.prototype.sound = function () {
return "Wuf";
};
return Dog;
})();
Can you do it both ways, or is the way I've done it wrong? In that case, why? And what exactly is the difference between the two in terms of what we end up with? In both cases we can create an object by saying:
var fido = new Dog("Fido");
fido.sound();
I hope someone will enlighten me.
There are two important differences between your way and theirs.
Wrapping in a self invoking function ((function() { ... })();)
Using the .prototype property over this. for methods.
Wrapping things in a self invoking function, then assigning the result (as defined in the return statement to a variable is called the module pattern. It's a common pattern to ensure scope is more controlled.
Using Dog.prototype.sound = function() {} is preferable to this.sound = function(). The difference is that Dog.prototype.sound is defined once for all objects with the Dog constructor, and the this.sound = function() {} is defined again for each Dog object created.
The rule of thumb is: Things that are individual to an object (usually its properties) are to be defined on this, while things that are shared to all objects of the same type (usually functions) are to be defined on the prototype.
With your code, you're creating a new function sound for every new Dog instance that's being created. Javascript's prototype avoids this by creating only a single function which all object instances share; basically classical inheritance.
In the second code you're showing that's just additionally wrapped in an IIFE, which doesn't do much in this case.
The first is the traditional method of creating a constructor. The second an immediately invoked function expression that returns a constructor. This method allows you to keep variables within the module without leaking out into the global scope which could be an issue.
And what exactly is the difference between the two in terms of what we end up with?
They both, as you've seen, have the same result. The others have talked about prototype so I won't mention it here.
The second is preferable because it takes advantage of Javascript's prototypal inheritance mechanism.
Prototypes
Javascript inheritance is a cause of confusion, but it's actually fairly simple: every object has a prototype, which is an object that we will check when we try to access a property not on the original object. The prototype will, itself, have a prototype; in a simple case, like Dog, this will probably be Object.prototype.
In both of your examples, because of how the new operator works, we will end up with a prototype chain that looks like this: fido->Dog.prototype->Object.prototype. So, if we try to look for the name property on Fido, we'll find it right there on the object. If, on the other hand, we look for the hasOwnProperty property, we'll fail to find it on Fido, fail to find it on Dog.prototype, and then reach Object.prototype, where we'll find it.
In the case of sound, your examples define it in two different places: in the first case, fido and every other dog we create will have their own copy of the function. In the second case, Dog.prototype will have a single copy of the function, which will be accessed by individual dogs when the method is called. This avoids wasting resources on storing duplicates of the sound function.
It also means that we can extend the prototype chain; maybe we want a Corgi class that inherits the sound function from Dog. In the second case, we can simply ensure that Dog.prototype is in Corgi.prototype's prototype chain; in the first, we would need to create an actual Dog and put it in the prototype chain.
I often use the pattern of a main JavaScript constructor function and adding methods to its prototype object so they can be called intuitively by the user, for example:
function Slideshow(options) {
this.options = options
this.slideshow = $('#slideshow')
//more variables here
}
Slideshow.method1 = function () {
this.slideshow.addClass('test') // do something with slideshow variable
};
Slideshow.method2 = function () {
// another method
};
The one thing that really bugs me about this pattern is how in order to make variables accessible across all prototype methods, I have to add "this" in front of each variable inside the constructor function. It's a major pain, and I can't help but think there's a more elegant way to do this.
If I forgo using the prototype object and just add the methods as instance methods, I know I can't get around this problem, but I like the efficiency? and self encapsulating nature of this pattern. Any other suggestions for a better pattern? Thanks!
It's a major pain
No, it's really not. Every single JavaScript developer uses this syntax. If you were in Ruby or Python, you'd use self., in PHP you'd use $this->. Some languages like C++ don't require any special decorator, but JavaScript does.
and I can't help but think there's a more elegant way to do this.
No, there isn't.
This is JavaScript's syntax, you cannot change it, and you cannot work around it. If you want to access a property of this, you need this. before the property name. Otherwise, you're talking about global variables.
If you want a different syntax, consider a different language like CoffeeScript, which compiles to JavaScript.
meager has pretty much summed things up if you're talking about accessing public instance properties or methods. You have to use this in front of it as that's just how the language works.
But, if you have private instance properties or methods, you can define those as local variables inside the constructor and you can access them without this.
function slideshow(options) {
// no need to resave the options arguments as they can be used
// directly from the argument variable
// define a per-instance private variable that other methods defined
// within the constructor can use directly without the use of `this`
var theShow = $(options.selector || '#slideshow');
// define public methods
this.method1 = function() {
// can access private instance variable here without this in front of it
theShow.addClass('test');
}
this.method2 = function() {
theShow.addClass(options.decoaration);
}
}
This general design pattern is described here: http://javascript.crockford.com/private.html
Practically speaking, this works because the constructor function with the public methods declared inside it creates a closure that lasts for the duration of the object lifetime so the local variables in the constructor become per-instance variables accessible only from the functions declared within the constructor.
This question already has answers here:
Defining methods via prototype vs using this in the constructor - really a performance difference?
(7 answers)
Closed 8 years ago.
I know it's possible to mimic private variables in JS:
function ConstructorPattern() {
var privateVar = 'hi there';
this.getVar = function() {
return privateVar;
};
};
But according to Learning JavaScript Design Patterns when referring to some similar code with class Car and method toString:
The above is a simple version of the constructor pattern but it does suffer from some problems. One is that it makes inheritance difficult and the other is that functions such as toString() are redefined for each of the new objects created using the Car constructor. This isn't very optimal as the function should ideally be shared between all of the instances of the Car type.
So the solution given in my case would be to add the getVar function via the prototype:
ConstructorPattern.prototype.getVar = function() {
return privateVar;
};
But of course that function has no idea what privateVar is so it doesn't work. I am aware of the module pattern but I specifically want to be able to instantiate multiple instances.
Is there any way to use the constructor pattern "properly" with prototypes while still getting "private" functionality?
EDIT: If there isn't a way to accomplish this, is it really that bad for methods to be redefined for each class instance? I've recently started working on a code base that takes this approach. It seems like the only thing I'm missing out on is inheritance?
EDIT2: Marking as a duplicate based on link from the accepted answer.
Is there any way to use the constructor pattern "properly" with prototypes while still getting "private" functionality?
No. This pattern with privileged functions is based on closure scope, and cannot work with shared functions. All privileged methods must be instance-specific.
If there isn't a way to accomplish this, is it really that bad for methods to be redefined for each class instance?
No. Modern JavaScript engines optimize this pattern very well. Sure, there's a little overhead but you won't notice in typical setups.
It seems like the only thing I'm missing out on is inheritance?
Inheritance is still possible, see Define Private field Members and Inheritance in JAVASCRIPT module pattern. Sure, derived subclasses cannot directly access private variables that are declared in a parent constructor, but usually they don't need to anyway.
When you're creating getVar on the object's prototype, it wont be called when you do something like:
objectName.getVar();
Because the prototype's methods come AFTER object methods. An example below will show you what i mean:
function Car() {
var privy = "hidden";
this.getPrivy = function() {
return privy;
}
}
Car.prototype = {};
Car.prototype.getPrivy = function() {
return 'i came from prototype';
}
var obj = new Car;
obj.getPrivy();
JS follows a call chain such as:
Object method -> prototype method -> prototype prototype method etc.... all the way back to Object.prototype. It stops and returns when a valid method is found. In your case, your instance's method comes BEFORE your prototype's method.
There's a rule/option in JSHint that I've never clearly understood: the nonew rule:
This option prohibits the use of constructor functions for
side-effects. Some people like to call constructor functions without
assigning its result to any variable:
new MyConstructor();
There is no advantage in this approach over
simply calling MyConstructor since the object that the operator new
creates isn't used anywhere so you should generally avoid constructors
like this one.
Here's what I don't understand:
What's an example of a "side effect" that would result from invoking an object constructor?
What's the proper way to invoke an object constructor if you have no need to reference the instance as a variable?
What is meant by saying there is no advantage over calling MyConstructor() without new? Obviously that wouldn't create an object as intended.
To help elicit helpful responses, how should the code below be refactored to instantiate the object when there is no further need for referencing the instance after invoking the constructor?
var Module = require('./module');
(function (Module) {
new Module({
el: '#module',
tpl: '#tpl-module',
status: false
});
})(Module);
What's the proper way to invoke an object constructor if you have no need to reference the instance as a variable?
Don't invoke the constructor if you don't need an instance.
What is meant by saying there is no advantage over calling MyConstructor() without new? Obviously that wouldn't create an object as intended.
If the purpose of the call is to execute side effects, you don't need to create an object. You should use a plain function (I'm tempted to call it "procedure"), instead of a constructor, if you need such.
In case the constructor does use the instance (and binds it somewhere), this is considered a bad practise. The constructor should only create and initialise the object. Everything else should be done in a separate method.