I understand how private static mechanism works in javascript; but that screws in
inheritance.
For example:
var Car = (function() {
var priv_static_count = 0;
return function() {
priv_static_count = priv_static_count + 1;
}
})();
var SedanCar = function () {};
SedanCar.prototype = new Car();
SedanCar.prototype.constructor = SedanCar;
Is there any way to avoid this pitfall ?
First of all, there's no such thing as "private static" in JavaScript. What you use here is a simple closure, which is created by a Immediately-Invoked Function Expression.
Your question is not quite clear, but I guess you want to count the Car instances that were created, and it doesn't work, because when you instantiate the subclass the counter won't increment (problem 1). Instead, the counter is incremented only once, when you define your subclass (problem 2).
Since JavaScript has a prototype based inheritance model, you have to create an object that can be used as prototype. But I suggest you to do it without calling the parent class' constructor (this will solve the second part of the problem). This is a very common pattern used everywhere in the JavaScript world (see Simple JavaScript Inheritance, Backbone, CoffeScript, etc.), and it is very simple to implement if you don't need to support very old browsers (IE6-8). It goes like this:
SedanCar.prototype = Object.create(Car.prototype)
Now the first part of the problem is quite simple to fix. Just call the parent constructor every time the child is instantiated. This is also a quite good pattern, and it is built into many other languages (Java, etc.). In JavaScript, you will have to do it manually, like this:
var SedanCar = function () {
// Parent class initialization
Car.call(this /*, and, other, arguments, to, the, parent, constructor */)
// Child class initialization
};
This will call the parent constructor with this bound to the newly created object. The parent constructor does the initialization, and then the child does it's share of the work. In your example, the parent will increment the counter as you would expect.
Related
I'd like to understand when it is appropriate to use prototype methods in js. Should they always be used? Or are there cases where using them is not preferred and/or incurs a performance penalty?
In searching around this site on common methods for namespacing in js, it seems that most use a non-prototype based implementation: simply using an object or a function object to encapsulate a namespace.
Coming from a class-based language, it's hard not to try and draw parallels and think that prototypes are like "classes" and the namespace implementations I mentioned are like static methods.
Prototypes are an optimisation.
A great example of using them well is the jQuery library. Every time you obtain a jQuery object by using $('.someClass'), that object has dozens of "methods". The library could achieve that by returning an object:
return {
show: function() { ... },
hide: function() { ... },
css: function() { ... },
animate: function() { ... },
// etc...
};
But that would mean that every jQuery object in memory would have dozens of named slots containing the same methods, over and over.
Instead, those methods are defined on a prototype and all jQuery objects "inherit" that prototype so as to gain all those methods at very little runtime cost.
One vitally important part of how jQuery gets it right is that this is hidden from the programmer. It's treated purely an optimisation, not as something that you have to worry about when using the library.
The problem with JavaScript is that naked constructor functions require the caller to remember to prefix them with new or otherwise they typically don't work. There is no good reason for this. jQuery gets it right by hiding that nonsense behind an ordinary function, $, so you don't have to care how the objects are implemented.
So that you can conveniently create an object with a specified prototype, ECMAScript 5 includes a standard function Object.create. A greatly simplified version of it would look like this:
Object.create = function(prototype) {
var Type = function () {};
Type.prototype = prototype;
return new Type();
};
It just takes care of the pain of writing a constructor function and then calling it with new.
When would you avoid prototypes?
A useful comparison is with popular OO languages such as Java and C#. These support two kinds of inheritance:
interface inheritance, where you implement an interface such that the class provides its own unique implementation for every member of the interface.
implementation inheritance, where you extend a class that provides default implementations of some methods.
In JavaScript, prototypical inheritance is a kind of implementation inheritance. So in those situations where (in C# or Java) you would have derived from a base class to gain default behaviour, which you then make small modifications to via overrides, then in JavaScript, prototypical inheritance makes sense.
However, if you're in a situation where you would have used interfaces in C# or Java, then you don't need any particular language feature in JavaScript. There is no need to explicitly declare something that represents the interface, and no need to mark objects as "implementing" that interface:
var duck = {
quack: function() { ... }
};
duck.quack(); // we're satisfied it's a duck!
In other words, if each "type" of object has its own definitions of the "methods", then there is no value in inheriting from a prototype. After that, it depends on how many instances you allocate of each type. But in many modular designs, there is only one instance of a given type.
And in fact, it has been suggested by many people that implementation inheritance is evil. That is, if there are some common operations for a type, then maybe it's clearer if they are not put into a base/super class, but are instead just exposed as ordinary functions in some module, to which you pass the object(s) you want them to operate on.
You should use prototypes if you wish to declare a "non-static" method of the object.
var myObject = function () {
};
myObject.prototype.getA = function (){
alert("A");
};
myObject.getB = function (){
alert("B");
};
myObject.getB(); // This works fine
myObject.getA(); // Error!
var myPrototypeCopy = new myObject();
myPrototypeCopy.getA(); // This works, too.
One reason to use the built-in prototype object is if you'll be duplicating an object multiple times that will share common functionality. By attaching methods to the prototype, you can save on duplicating methods being created per each new instance. But when you attach a method to the prototype, all instances will have access to those methods.
Say you have a base Car() class/object.
function Car() {
// do some car stuff
}
then you create multiple Car() instances.
var volvo = new Car(),
saab = new Car();
Now, you know each car will need to drive, turn on, etc. Instead of attaching a method directly to the Car() class (which takes up memory per each instance created), you can attach the methods to the prototype instead (creating the methods only once), therefore giving access to those methods to both the new volvo and saab.
// just mapping for less typing
Car.fn = Car.prototype;
Car.fn.drive = function () {
console.log("they see me rollin'");
};
Car.fn.honk = function () {
console.log("HONK!!!");
}
volvo.honk();
// => HONK!!!
saab.drive();
// => they see me rollin'
Put functions on a prototype object when you're going to create lots of copies of a particular kind of object and they all need to share common behaviors. By doing so, you'll save some memory by having just one copy of each function, but that's only the simplest benefit.
Changing methods on prototype objects, or adding methods, instantly changes the nature of all the instances of the corresponding type(s).
Now exactly why you'd do all these things is mostly a function of your own application design, and the kinds of things you need to do in client-side code. (A whole different story would be code inside a server; much easier to imagine doing more large-scale "OO" code there.)
If i explain in class based term then Person is class, walk() is Prototype method. So walk() will have its existence only after you instantiate new object with this.
So if you want to create the copies of object like Person u can create many users Prototype is good solution as it saves memory by sharing/inheriting same copy of function for each of the object in memory.
Whereas static is not that great help in such scenario.
function Person(){
this.name = "anonymous";
}
// its instance method and can access objects data data
Person.prototype.walk = function(){
alert("person has started walking.");
}
// its like static method
Person.ProcessPerson = function(Person p){
alert("Persons name is = " + p.name);
}
var userOne = new Person();
var userTwo = new Person();
//Call instance methods
userOne.walk();
//Call static methods
Person.ProcessPerson(userTwo);
So with this its more like instance method.
The object's approach is like Static methods.
https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript
Just including a video link here for reference, when not to use prototypes: https://youtu.be/JCXZhe6KsxQ?t=2m30s
Here is Ben Lesh's talk from NGConf, why rxjs removed patching prototype (chainable functions) in favor of pipeable functions.
I am reviewing a JavaScript code from a colleague and he wrote an Object prototype function that I believe is not correct regarding the principles of Object-Oriented Programming.
Game.prototype.reset = function() {
if (game.over) {
game.over = false;
game = new Game(players);
}
}
A couple of lines below, the game variable was declared as a global variable.
var game = new Game(players);
So, is it correct to create a new Game object from one of its constructors? The code perfectly runs. Thanks!
He should not reference the variable game inside the prototype method, as game is the name of the instance. Instead he should use this to refer to the current object.
Inside the reset method he should not created the new game instance but truly reset the Game fields, something along below:
Game.prototype.reset = function() {
if (this.over) {
this.over = false;
this.initialize(this.players);
}
}
Game.prototype.initialize = function(players) {
this.players = players;
:
}
I guest this broke the encapsulation principle, each instance is responsable to deal with his own behavior, not with other global instance.
http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
If was me, i would choose Max Zoom alternative to model my solution.
I would say that this is "incorrect" code inasmuch as it disobeys the principle of encapsulation, because one instance of a class is affecting the state another instance of that class, without that second instance being passed as a parameter (it just comes out of nowhere).
I'd also say that it's not particularly useful to define a module part way between a constructor and a singleton.
If game is to be a singleton, then define it as a singleton, attach it to the global scope (or better, use a module loader), and use it as a singleton. Give it a reset method that uses this to change its own internal state back to initial values.
If Game is to be a constructor, of which there can be many instances, then define it as a constructor and create instances when necessary, then pass those instances around as parameters where needed.
Personally I would use a constructor, and I wouldn't have a reset method at all. When the game is reset by the user, I'd just create a new instance of Game. But a properly defined singleton would be better than the code that's in the question.
I don't think there is anything wrong in using Game constructor inside prototype of Game.
See the below example. it has a method named cloneMe and it creates new object with current objects value.
function Game(name, team) {
this.playerName = name;
this.teamName = team
this.points = 0;
}
Game.prototype.goal = function() {
this.points += 1;
}
Game.prototype.cloneMe = function() {
return new Game(this.playerName, this.teamName);
}
var gameInst = new Game('jack', 'X-team');
gameInst.goal();
gameInst.points // will print 1
gameInst.goal();
gameInst.points // will print 2
// game varible got replaced with new variable
var gameCloneInst = game.cloneMe();
gameCloneInst.goal();
gameCloneInst.points // will print 1
The problem with functional inheritance is that if you want to create many instances then it will be slow because the functions have to be declared every time.
The problem with prototypal inheritance is that there is no way to truly have private variables.
Is it possible to mix these two together and get the best of both worlds? Here is my attempt using both prototypes and the singleton pattern combined:
var Animal = (function () {
var secret = "My Secret";
var _Animal = function (type) {
this.type = type;
}
_Animal.prototype = {
some_property: 123,
getSecret: function () {
return secret;
}
};
return _Animal;
}());
var cat = new Animal("cat");
cat.some_property; // 123
cat.type; // "cat"
cat.getSecret(); // "My Secret"
Is there any drawbacks of using this pattern? Security? Efficiency? Is there a similar pattern out there that already exists?
Your pattern is totally fine.
There are a few things that you'd want to keep in mind, here.
Primarily, the functions and variables which are created in the outermost closure will behave like private static methods/members in other languages (except in how they're actually called, syntactically).
If you use the prototype paradigm, creating private-static methods/members is impossible, of course.
You could further create public-static members/methods by appending them to your inner constructor, before returning it to the outer scope:
var Class = (function () {
var private_static = function () {},
public_static = function () {},
Class = function () {
var private_method = function () { private_static(); };
this.method = function () { private_method(); };
};
Class.static = public_static;
return Class;
}());
Class.static(); // calls `public_static`
var instance = new Class();
instance.method();
// calls instance's `private_method()`, which in turn calls the shared `private_static();`
Keep in mind that if you're intending to use "static" functions this way, that they have absolutely no access to the internal state of an instance, and as such, if you do use them, you'll need to pass them anything they require, and you'll have to collect the return statement (or modify object properties/array elements from inside).
Also, from inside of any instance, given the code above, public_static and Class.static(); are both totally valid ways of calling the public function, because it's not actually a static, but simply a function within a closure, which also happens to have been added as a property of another object which is also within the instance's scope-chain.
As an added bonus:
Even if malicious code DID start attacking your public static methods (Class.static) in hopes of hijacking your internals, any changes to the Class.static property would not affect the enclosed public_static function, so by calling the internal version, your instances would still be hack-safe as far as keeping people out of the private stuff...
If another module was depending on an instance, and that instance's public methods had been tampered with, and the other module just trusted everything it was given... ...well, shame on that module's creator -- but at least your stuff is secure.
Hooray for replicating the functionality of other languages, using little more than closure.
Is it possible to mix functional and prototypical inheritance together and get the best of both worlds?
Yes. And you should do it. Instead of initializing that as {}, you'd use Object.create to inherit from some proto object where all the non-priviliged methods are placed. However, inheriting from such a "class" won't be simple, and you soon end up with code that looks more like the pseudo-classical approach - even if using a factory.
My attempt using both prototypes and the singleton pattern combined. Is there a similar pattern out there that already exists?
OK, but that's something different from the above? Actually, this is known as the "Revealing Prototype Pattern", a combination of the Module Pattern and the Prototype Pattern.
Any drawbacks of using this pattern?
No, it's fine. Only for your example it is a bit unnecessary, and since your secret is kind of a static variable it doesn't make much sense to me accessing it from an instance method. Shorter:
function Animal(type) {
this.type = type;
}
Animal.prototype.some_property = 123;
Animal.getSecret = function() {
return "My Secret";
};
Are there any important/subtle/significant differences under the hood when choosing to use one of these four patterns over the others? And, are there any differences between the them when "instantiated" via Object.create() vs the new operator?
1) The pattern that CoffeeScript uses when translating "class" definitions:
Animal = (function() {
function Animal(name) {
this.name = name;
}
Animal.prototype.move = function(meters) {
return alert(this.name + (" moved " + meters + "m."));
};
return Animal;
})();
and
2) The pattern that Knockout seems to promote:
var DifferentAnimal = function(name){
var self = this;
self.name = name;
self.move = function(meters){
return alert(this.name + (" moved " + meters + "m."));
};
}
and
3) a similar, simple pattern I've often seen:
var DifferentAnimalWithClosure = function(name){
var name = name;
var move = function(meters){
};
return {name:name, move:move};
}
and
4) The pattern that Backbone promotes:
var OneMoreAnimal= ClassThatAlreadyExists.extend({
name:'',
move:function(){}
});
Update 1: Changed pattern #2 and added pattern #3 in response to Elias' response // minor formatting
Just to be clear: JS doesn't know of classes, just objects and custom, self-defined constructor functions, but that's besides the point.
To answer your question in short: yes, there are some small and even some fairly large differences between the various ways of creating a new object you're posting here.
CoffeeScript:
This is actually the most clear-cut and traditional way to create your own constructor, but it has been "optimized" in the sense that it's been ready set-up to use (optional) closure variables.
Basically, what this code does, is use an IIFE, to wrap both the constructor definition and the proptotype method assignments in their own, private scope, that returns a reference to the new constructor. It's just clean, simple JS, no different from what you might write yourself.
Knockout:
Now this threw me a little, because to me, at least, the snippet you provide looks either like part of a module pattern, or a power constructor. But since you're not using strict mode, omitting the new would still make for dangerous situations, and since the entire function goes trough the trouble of creating a new instance of DifferentAnimal, only to then construct a second object literal, assigning all properties of DifferentAnimal to that secondary object, I'd say you're missing something. Because, truth be told, omitting the last return {}; statement here, would probably make no difference at all. Plus: as you can see, you're declaring a method (move) in what is, in essence, a constructor. This means that every instance will be assigned its own function object move, rather then getting it from the prototype.
In short: have another close look at where you got this snippet from, and double-check if this is the full version, because if it is, I can only see arguments against this.
Using a variable, defined inside the constructor is simply: a closure, suppose your properties have a distinct initial state, determined by some arguments, passed to that constructor:
function MyConstructor(param)
{
var paramInit = param/2;//or something
this.p = paramInit;//this property can change later on, so:
this.reInit = function()
{//this method HAS to be inside constructor, every instance needs its own method
this.p = paramInit;//var paramInit can't, it's local to this scope
};
}
var foo = new MyConstructor(10);
console.log(foo.p);//5
foo.p = 'hi';
console.log(foo.p);//hi
foo.reInit();
console.log(foo.p);//5
console.log(foo.paramInit);//undefined, not available outside object: it's a pseudo-private property
That's all there is too it, really. When you see ppl using var that = this; or something, that's often to create a reference to the main object that is available anywhere, without having to deal with the headaches of this (what does this reference? What should the method do when applied to an object other than the one it was originally intended for? etcetera...)
Backbone:
Here, we're dealing with another case: extending objects (IE: using methods, properties of either an existing "class" (constructor) or a particular instance) is not the same as simply creating an object.
As you well know, JS objects can be assigned new properties at any given time. Those properties can be removed, too. Sometimes, prototype properties can be redefined on the instance itself (masking the prototypal behaviour) etc... So it all depends on what you want the resulting object (the newly created object, that extends the given instance) to look like: do you want it to take all properties from the instance, or do you want both objects to use the same prototype somewhere down the line?
Both of these things can be achieved by using simple JS, too, but they just take a bit more effort to write yourself. However, if you write, for example:
function Animal(name)
{
this.name = name;
}
Animal.prototype.eat= function()
{
console.log(this.name + ' is eating');
};
That could be deemed the equivalent of writing:
var Animal = Object.extend({name:'',eat:function()
{
console.log(this.name + ' is eating');
}});
A lot shorter, but lacking the constructor.
new vs Object.create
Well, that's an easy one: Object.create just is a lot more powerful that new: you can define prototype methods, properties (including weather or not they are enumerable, writeable etc...) right at the time you need to create an object, instead of having to write a constructor and a prototype, or create an object literal and mess around with all those Object.defineProperty lines.
The downsides: Some people still aren't using ECMA5 compliant browsers (IE8 is still not quite dead). In my experience: it does become quite hard to debug sizeable scripts after a while: though I tend to use power-constructors more than I do regular constructors, I still have them defined at the very top of my script, with distinct, clear and quite descriptive names, whereas object-literals are things I just create "on-the-fly". Using Object.create, I noticed I tend to create objects that are really a little too complex to qualify as actual object literals, as though they are object literals:
//fictional example, old:
var createSomething = (function()
{
var internalMethod = function()
{//method for new object
console.log(this.myProperty || '');
};
return function(basedOn)
{
var prop, returnVal= {};
returnVal.myProperty = new Date();
returnVal.getCreated = internalMethod;//<--shared by all instances, thx to closure
if (!basedOn || !(basedOn instanceof Object))
{//no argument, or argument is not an object:
return returnVal;
}
for (prop in basedOn)
{//extend instance, passed as argument
if (basedOn.hasOwnProperty(prop) && prop !== '_extends')
{
returnVal[prop] = basedOn[prop];
}
}
returnVal._extends = basedOn;//<-- ref as sort-of-prototype
return returnVal;
};
}());
Now this is pretty verbose, but I've got my basic constructor ready, and I can use it to extend an existing instance, too. It might seem less verbose to simply write:
var createSomething = Object.create(someObject, {getCreated:function()
{
console.log(this.myProperty);
},
myProperty:new Date()});
But IMO, this makes it harder on you do keep track of what object is created where (mainly because Object.create is an expression, and will not be hoisted.Ah well, that's far from a conclusive argument of course: both have their pro's and con's: I prefer using module patters, closures and power constructors, if you don't that's just fine.
Hope this cleared up a thing or 2 for you.
The first example puts the move function in the prototype which will be shared between all Animal instances.
The second example creates a new move function for every the animal instance.
The third example generates a Animal class with the move function in the prototype similar to the first example but with allot less code.
(In your example the name is also shared between all instances, which you probably don't want)
Putting the function in the prototype makes instantiating Animals faster, and because of the way JIT engines work even the execution of the function is faster.
Is this code idomatic, or should I just acess the properties directly?
self.isAlive = function() {
return self.alive;
}
It all depends on implementation.
If you feel the property is always going to be the value, accessing the property is adequate. If you feel like there's going to be some logic that determines returning a "properly formatted" value, I would use a method (or if the value could possibly be dynamic based on other factors, a method is a good idea).
To go a step further, other languages like C# have properties making it safe to expose values, but not necessarily alter them. JS doesn't have such a method of protecting it, so often get<Var> is used to expose the property, but in a read-only fashion.
It's all about how you would like the data, while also trying to anticipate what the worst-case scenario could be if you expose the property directly vs. through a method.
It seems that you are speaking of properties in the classical OOP sense, i.e., properties of classes. In the current version of Javascript, simulating this behavior is not completely clean. Consider the following example:
var Widget = function() {
var private = 'private';
}
'Widget' is a constructor function, and 'private' will be instantiated in the scope of just the constructor function. That means there is only one way to get access to 'private' from outside the constructor function scope:
var Widget = function() {
var private = 'private';
this.getPrivate = function() {
return private;
}
}
This will hide the private variable for each instance of Widget, but unfortunately, 'getPrivate' must now be added to each instance of Widget. You can see this occurring in the constructor function by the statement this.getPrivate = .... Every time you make an instance of Widget using var widget1 = new Widget(), that specific instance will have a new function, 'getPrivate', added to it.
The normal way to make reusable components in Javascript is to use its implementation of Prototypical Inheritance. You assign a prototype object to the constructor function that will have shared methods and properties across all instances of the component. I will provide an example below to explain, but there are caveats to prototypical inheritance that you should become aware of if you are doing object-oriented javascript. A great resource.
Here's an example of how this might come in to play for your example:
var Widget = function() {
this.alive = true;
}
Widget.prototype.isAlive = function() {
return this.alive;
}
var widget1 = new Widget();
widget1.isAlive(); // returns true
The problem here is that the property alive is being added to the object, and thus, it is publicly available, i.e., any user of your Widget can simply look through the DOM in their favorite variation of FireBug and see (as well as freely modify) this property.
Consider a variation where you attempt to hide alive to external users. Because alive is a property of Widget instances, you would want to include the code to hide it in the constructor, as shown below:
var Widget = function() {
var alive = true;
}
However, as stated at the beginning of this post, alive in this case is only exposed to the constructor function's scope; therefore, it would not be accessible to methods on the prototype. The reason for this is that each of those methods do not have the same scope as the constructor function, since Javascript only has function scope.
In conclusion, if you're trying to hide data in a reusable component, javascript does not provide a clean way to do it. If you don't mind having new memory allocated on each component instance for the same methods, then you can use my second code example in this post. However, if you prefer to have your methods allocated in memory only once, then you will need to expose properties on the object instance, e.g., this.alive = true.
That's subjective. Use of getters and setters is very discussed. Some people (like me) say you should always use getters and setters to follow the encapsulation principle, while others say that you shouldn't since your application would become unmaintainable.
This is good practice if you don't want outside js code to modify your property. If this is the desired effect you might consider assigning that property using var instead of making it a property of that object. That way your code within the object can modify it but it can only be accessed through your getter
var alive = false;
function isAlive(){ return alive;}
You can use:
function isAlive(){
return arguments.callee.alive;
}
isAlive.alive=true;
This appears to be ok still in strict mode.
Another way to accomplish this is
function isAlive(){
return isAlive.alive;
}
isAlive.alive=true;
But the problem is that someone can use the name as a string, or rename the function etc... and you can loose the status.