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.
Related
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:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 8 years ago.
Let me put first two examples.
Example 1:
function Gallery() {
this.a = "I am 'A'";
this.trace = function() {
console.log(this.a);
}
}
Example 2:
function Gallery() {
this.a = "I am 'A'";
}
Gallery.prototype.trace = function () {
console.log(this.a);
}
Obviously, both things do the same. My question is: is there any drawback to using the method definition in the constructor function over the prototype one? What exactly is the difference anyway?
Is the prototype more memory friendly? I assume that if I define the method inside the constructor function, every single Gallery instance will have its 'own instance' of the method so will consume more memory while the prototype defines only one function that's shared across all the Gallery instances. Is this correct?
Thanks a lot!
The method definition in constructor is slower because it's executed every single time you create a new object.
On the other hand, with a prototype, the VM will be able to optimize access to it, to optimize the functions (since they're shared - it wouldn't be able to do if it every instance had its own functions).
(not going too much into details because it's been explained already, but basically, VMs (I know v8 does that, not sure what others do) will usually a "hidden class" for every prototype, with optimized fields, instead of just having it as a map of any => any)
This also allows a lot more of flexibility to add functions at a later time.
The only good thing about adding methods on the object is that you can fake "private" fields more easily.
You're right that each Gallery object will have its own .trace() function object if you put .trace() in the constructor, so it's more efficient to make methods in the .prototype object unless you absolutely want to use encapsulation to hide your arguments passed into the constructor instead of saving them as properties on the instance. The .prototype object is also easier for the browser to optimize.
Both methods are almost indistinguishable in practice unless a coder tries to inspect your JavaScript code with his JavaScript console in which case it'll be much easier for them to read the methods to be on the .prototype object instead of inside the constructor altogether with everything. Take of that what you will.
Is it possible to restrict inheritance in javascript ? I searched internet about restricting of inheritance in javascript but didn't find any useful information.Can someone explain on this topic of inheritance restriction ? I would like to restrict inheriting properties of my singleton object in other objects.
You cannot restrict inheritance in javascript. If you have a public constructor function that initializes an object, any other object can use it to make a derived object.
You can make many instance variables or even methods private with certain methods of declaration (see here for reference) which can reduce the usefulness or capabilities of a derived object though still doesn't prevent it.
Perhaps if you explain what problem you're really trying to solve, we could offer more concrete ideas on how to solve it.
OK, now that you've explained that you just want a singleton, then I'd suggest you use a singleton design pattern like this:
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
The constructor is private (contained within the closure) so it can't be called by other code and the means of getting the object is a function that only ever returns the single instance. Of course, any properties/methods on an object in JS can be copied, but a singleton like this can keep instance data in the closure if it wants where it cannot be copied.
References:
Learning Javascript Design Patterns - The Singleton Pattern
Singleton Design Pattern
Javascript Singleton Design pattern
Javascript Design Patterns: Singleton
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.
I'm learning Javascript and have several questions concerning Javascript and OOP. I've noticed different declarations of functions in "classes" in various tutorials. First is the inside constructor:
Class = function () {
this.doSomething = function() {....};
}
And the other one is:
Class = function () {}
Class.prototype.doSomething = function() {....};
In which situations should the first construction be used, and in which situation should the second construction be used?
And the other question is: have I understood correctly that there's no protected properties or methods in js? What is to be used instead?
Thank you in advance!
When you define a function inside the constructor as this.myFunction=..., it is specific to your instance. This means that it must be constructed and kept in memory for all instances, which may be heavy. It also can't be inherited .
The only valid reason to do this are :
the enclosing of specific values
other types of specific functions (you might build a different function each time)
Most often, what you really need is a function defined on the prototype.
From the MDN on objects :
All objects in JavaScript are descended from Object; all objects
inherit methods and properties from Object.prototype, although they
may be overridden. For example, other constructors' prototypes
override the constructor property and provide their own toString
methods. Changes to the Object prototype object are propagated to all
objects unless the properties and methods subject to those changes are
overridden further along the prototype chain.
Regarding your additional question : the following code builds a non directly accessible function :
Class = function () {
var imprivate = function(){...};
this.doSomething = function() { uses imprivate};
}
A downside is that you have a different function instance for each instance of Class. This is most often done for modules (from which you have only one instance). Personally, I prefer to do exactly as suggested by ThiefMaster in comment : I prefix my private functions with _ :
// private method
XBasedGrapher.prototype._ensureInit = function() {