How do I write 'this' less often? - javascript

Using ES6 classes is great and all, but I find myself using this.variable everywhere, and it is always referring to my class. Is there a way to have implied globals within my class be implied this.variable instead? So if I write 'width' it will be defaulted to this.width instead of an implied global?
Or if there are some best practices that I might not be aware of to cut down on my 'this' addiction I'd love to read that too. In the file I'm currently working on there are about half as many this keywords as there are lines of code...

Using constructor functions / classes and this is just one way to use JavaScript. JavaScript is a multi-paradigm language and yes, it's entirely possible to use it largely without using this. One way is via closures.
Consider this class example:
class Person {
constructor(first, last) {
this.first = first;
this.last = last;
this.things = [];
}
sayHello() {
console.log(`Hi, I'm ${this.first} ${this.last}`);
}
grabThing(thing) {
this.things.push(thing);
}
}
const p1 = new Person("Joe", "Bloggs");
p1.sayHello();
p1.grabThing("thing1");
console.log(p1.first + "'s things: " + p1.things.join(", "));
const p2 = new Person("Suresh", "Kumar");
p2.sayHello();
p2.grabThing("thing2");
p2.grabThing("thing3");
console.log(p2.first + "'s things: " + p2.things.join(", "));
Now, consider this approach with closures:
function createPerson(first, last) {
const things = [];
return {
sayHello() {
console.log(`Hi, I'm ${first} ${last}`);
},
grabThing(thing) {
things.push(thing);
},
get things() {
return things;
},
get first() {
return first;
},
get last() {
return last;
}
};
}
const p1 = createPerson("Joe", "Bloggs");
p1.sayHello();
p1.grabThing("thing1");
console.log(p1.first + "'s things: " + p1.things.join(", "));
const p2 = createPerson("Suresh", "Kumar");
p2.sayHello();
p2.grabThing("thing2");
p2.grabThing("thing3");
console.log(p2.first + "'s things: " + p2.things.join(", "));
Notice how we just use the first and last parameters provided to the createPerson function directly in sayHello, and we just declare things as a local constant which grabThing closes over. In that example, we also provide getters for the various bits of information (first, last, things) so they can be used from the object we return, but if there were information we wanted to keep private, we could leave out the getter. (And some prefer to make those explicitly functions rather than getters.)
One downside to this approach is that there are separate function objects for sayHello, grabThing, the getters, etc., for each object created by createPerson, while in the class example, there's only one sayHello function object, which is shared amongst Person objects via prototypical inheritance. On the one hand, creating additional sayHello function objects seems wasteful; but modern JavaScript engines reuse the underlying function code even though there are distinct sayHello objects, and objects are fairly cheap in our modern world.
Upsides are the easy way to have private information and not having to use and manage this.
Douglas Crockford (amongst others) promotes this approach, if you want to learn more about it. (Note that in his writing, Crockford sometimes fails to clearly distinguish between fact and his opinion — and boy does he have opinions — but his writing is well worth reading regardless.)
(I'm not advocating either class or non-class, just noting there are options.)

I know this isn't a recommended practice, but a with statement is sortof what OP asks for.
with allows parsing an object, using the attributes as variables within the statement:
var MyClass = /** #class */ (function() {
function MyClass(name, age) {
this.name = name;
this.age = age;
}
MyClass.prototype.whoami = function() {
with(this) {
console.log(name, age);
}
};
return MyClass;
}());
var c = new MyClass("bob", 123);
c.whoami();
There is the issue that with is disabled in strict mode though, meaning that there are some contexts where it simply won't work.
ES6 classes is one such context, so if OP want's to use ES6 classes, then with is out.

Looking back at this old question the answer has become obvious with the release of hooks, just don't write class components and write function components instead :)

Related

How to declare private variables and private methods in es6 class [duplicate]

This question already has answers here:
How to work with private variables in ES6? [duplicate]
(4 answers)
Closed 7 years ago.
in es5 we use constructor function
function Person(name,gender){
var initial =""; // we use var key word to make variable private
function getNameWithInitial(){ // this is the private method to get name with initial
console.log(this);
initial = this.gender ==="male"?"Mr. ":"Mrs. ";
return initial + this.name;
}
this.name = name;
this.gender = gender;
this.getName = function(){
return getNameWithInitial.call(this);
}
}
var manas = new Person("Manas","male");
console.log(manas.getName());
My question is how to declare a private variable and private method in es6 class
One way to achieve this is using another ES2015 feature known as modules.
You may already be familiar with AMD modules, or commonJS modules (used by Nodejs). Well ES6 / ES2015 brings a standard for JS - we'll call them ES6 modules but they are part of the JS language now. Once you have modules, you have the ability to do information hiding for both private functions and object variables. Bear in mind, only what you "export" is visible to client calling code.
Lets work through your example code. Here is a first cut:
person.js
const getNameWithInitial = function () {
let initial = this._gender === 'male' ?
'Mr. ' :
'Mrs. ';
return initial + this._name;
}
export class Person {
constructor(name, gender) {
this._name = name;
this._gender = gender;
}
get name() {
return getNameWithInitial.call(this);
}
}
}
client.js
import {Person} from './person';
const manas = new Person('Manas', 'male');
console.log(manas.name); // this calls what was your getName function
Now, the getNameWithInitial function is effectively private, as it is not exported, so client.js cannot see it.
However, we still have a problem for the Person class, since this is exported. At the moment you can just walk up to manas object and do:
manas._name = 'Joe'
With properties like _name, we can combine modules and symbols. This is a powerful yet lightweight information hiding technique available with ES6+/ES2015.
Symbol is a new built-in type. Every new Symbol value is unique. Hence can be used as a key on an object.
If the client calling code doesn't know the symbol used to access that key, they can't get hold of it since the symbol is not exported.
Let's see our modified code to make use of symbols and modules to hide Class attributes.
person.js
const s_name = Symbol();
const s_gender = Symbol();
const getNameWithInitial = function () {
let initial = this[s_gender] === 'male' ?
'Mr. ' :
'Mrs. ';
return initial + this[s_name];
}
export class Person {
constructor(name, gender) {
this[s_name] = name;
this[s_gender] = gender;
}
get name() {
return getNameWithInitial.call(this);
}
}
So, now a client cannot just do:
manas._name = 'Joe'
because _name is not being used as the key for the name value.
However, symbols are exposed via reflection features such as Object.getOwnPropertySymbols so be aware they are not "completely' private using this technique.
import {Person} from './person';
const manas = new Person('Manas', 'male');
const vals = Object.getOwnPropertySymbols(manas);
manas[vals[0]] = 'Joanne';
manas[vals[1]] = 'female';
Takeaway message - Modules in general are a great way to hide something because if not exported then not available for use outside the module, and used with privately stored Symbols to act as the keys, then class attributes too can become hidden (but not strictly private). Using modules today is available with build tools eg. webpack / browserify and babel.
If you would like an analogue to the ES5 solution, it's quite simple; the constructor simply becomes what holds the closure, and you add any methods/objects which should remember the private state in there.
Prototyped methods have no access to the closure of the initial constructor, without using some privileged getters:
class Person {
constructor ({ name, age, deepDarkSecret }) {
const bribe = () => console.log(`Give me money, or everybody will know about ${ redactRandom(deepDarkSecret) }`);
Object.assign(this, { name, age }); // assigning publicly accessible values
Object.assign(this, { bribe }); // assign "privileged" methods (functions with closure-reference to initial values)
}
recallSecret () {
console.log("I'm just a prototyped method, so I know nothing about any secret, unless I use a privileged function...");
this.bribe();
}
}
If you look at what this nets you, you'll note that it's really not much different than your example (just using "cleaner" bells and whistles; especially when adding prototype/static methods). It's still prototype underneath.
If you have the luxury of using any kind of module/export (ES6 being the ideal), then with one other data-type, you can have true privacy and not have to clean up after yourself.
It's a little hackey-looking. It'll probably get less ugly, and hopefully be the basis for something cleaner, in the future, but if you want instance-based, private access, even for prototyped methods, then make one WeakMap, inside of the module that you're exporting your class from.
Use this as your key.
Rather than making privileged functions which have closure access, now all prototype methods have closure access to the weakmap...
...the downside being that any time you want private variables, you have to look them up in the WeakMap rather than pulling them off of / out of this.
const personalBaggage = new WeakMap();
class Person {
constructor ({ name, age, darkestMoment }) {
const privates = { name, age, darkestMoment };
personalBaggage.add(this, privates);
}
recallDarkestHour () {
const { darkestMoment } = personalBaggage.get(this);
console.log(darkestMoment);
}
}
export default Person;
As long as you aren't losing the reference inside of this, this should just work.
Unlike using Symbol, you can't get a reference to the private object, no matter how hard you try.
If you know the symbols on the object, you can look up the properties using the symbols.
And getting the list of symbols on any object is just a function call away.
Symbol isn't about keeping things private; it's about keeping things safe from naming collisions, and defining common symbols that can be used on any object/function, but won't be picked up in loops, won't be called or overwritten accidentally, et cetera.
Storing the private bag of data in a weakmap with this as a key gives you access to a completely hidden dataset, which is totally unaccessible outside of that module.
What's better, the key/value in weakmaps don't prevent the GC from cleaning them up.
Normally, if they were left in an array, they'd stay there. If the last place an object is used is as a key in a weakmap, then it gets collected and the weakmap value is erased automatically (in native ES6; the memory bonuses can't be polyfilled, but the object can).
here is a really good post on the subject. I didn't know much about doing this in ES6 before your question but after reviewing this it looks really cool. So you create a symbol that is indexed to the function.
here is the code straight from their sit.
var Person = (function() {
var nameSymbol = Symbol('name');
function Person(name) {
this[nameSymbol] = name;
}
Person.prototype.getName = function() {
return this[nameSymbol];
};
return Person;
}());
var p = new Person('John');
Private properties in JavaScript
You may accomplish it using Symbol.
const _name = Symbol();
class Person {
constructor(name) {
this[_name] = name;
}
}
const person = new Person('John');
alert(person.name);
// => undefined
Reference
Documentation

JavaScript oop: Designing classes correctly

Taking this list of similar questions:
How to set up JavaScript namespace and classes properly
Javascript namespace declaration with function-prototype
Best OOP approach to these two small JavaScript classes
I'd concluded there are two possible ways for implementing classes and instances in JS: using an inner function or using a prototype.
So let's say we have a Box class inside the namespace BOX_LOGIC with a simple code in it. I'm able to code the following:
BOX_LOGIC.Box = (function() {
// private static
var boxCount = 0;
var classDefinition = function(x) {
x = x || 0;
var capacity = x;
var id = ++boxCount;
// public methods
this.getCapacity = function() { return capacity; };
this.getId = function() { return id; };
this.add = function(weight) {
weight = weight || 0;
if (capacity >= weight) {
capacity -= weight;
}
return capacity;
};
};
return classDefinition;
})();
As well as I'm able to code:
BOX_LOGIC.Box = (function () {
var boxCount;
var Box= function (x) {
x = x || 0;
this.capacity = x;
this.id = ++boxCount;
};
Box.prototype = {
Constructor: Box,
add: function (weight) {
weight = weight || 0;
if (this.capacity >= weight) {
this.capacity -= weight;
}
return this.capacity;
}
};
return Box;
})();
Mi question are: what is exactly the difference in using the Box prototype or not? is any approach better for any reason(cost, legibility, standard...)?
Is in the second approach any way to emulate the static idvariable? THX!
Mi question are: what is exactly the difference in using the Box prototype or not?
is any approach better for any reason(cost, legibility, standard...)?
Functions (and other properties) on the prototype are shared between instances; if you create them in your constructor function, each instance gets its own copy of all of those functions.
The primary benefit is that you can add to the prototype, and even instances that already exist see the additions, since they use the prototype dynamically. In particular, this can help with aspect-oriented programming and various debugging and logging techniques, because you can dynamically wrap the functions on the prototype to capture calls. You can't do that when every instance has its own (unless you have a reference to every instance, which is unlikely).
In theory, using the prototype also means lower memory consumption. In practice, you'd have to have millions of instances to care, and modern engines are good at reusing the underlying code of the functions even though the function objects involved are distinct.
So unless you're going to augment the prototypes dynamically, one or the other is largely a matter of style.
Is in the second approach any way to emulate the static id variable?
I wouldn't have called it "static;" it's private to each instance. There are various ways to get close to private information with the prototype approach (that is, nearly-private information prototypical functions can access), but it's impossible to get truly get private information prototypical functions can access. There probably will be in ES7 (not ES6, which is currently being finalized; ES7). I address one of those near-private mechanisms in this blog post. The ES6 info in that post is now out of date; privacy stuff got pushed back to ES7, and "private Name" objects got morphed into Symbol which doesn't provide any real privacy at all.
I should flag up your third option, which you can use now with an ES6 transpiler: ES6's class:
// This is similar to the prototype version; `getCapacity` and
// `add` end up on `Box.prototype`
BOX_LOGIC.Box = (function () {
class Box {
constructor() {
x = x || 0;
this.capacity = x;
}
getCapacity() {
return this.capacity;
}
add(weight) {
weight = weight || 0;
if (this.capacity >= weight) {
this.capacity -= weight;
}
return this.capacity;
}
}
return Box;
})();
Side note: Since you used the word "correctly" in your title, I'll flag up a quite minor thing on your prototype example: You're messing up the constructor property. By default, Box.prototype has a property, constructor, that refers back to Box. But by replacing the object on Box.prototype with a completely different object, you're removing that. To be consistent with standard functions, I'd modify it like this:
Box.prototype = {
constructor: Box,
//...the existing stuff goes here...
};
Does it matter? Only if you end up with code that relies on the constructor property (and some libraries may). Nothing in JavaScript itself does, even though the JavaScript spec defines the property.

The correct way to implement prototypal inheritance

There is already numerous threads about prototypal inheritance in JavaScript, but this is not a copy due to laziness. I have literally read them all and have found almost as many different syntactic approaches as I have found answers, so it appears that I am not the only one that is confused on this subject!
Specifics:
My current approach looks like this.
var Person = function(name) {
this.name = name;
this.greeting = function() {
alert("Greetings, I am " + name);
}
}
var bob = new Person("bob");
bob.greeting();
var Woman = function(name) {
Person.call(this, name);
this.gender = "female";
}
Woman.prototype = Object.create(Person.prototype);
var brenda = new Woman("brenda");
brenda.greeting();
Person.prototype.eats = true;
alert(brenda.eats);
Having tested the code I have found it works perfectly - as far as I can tell - but I have been told that this is not the best approach and that I should define the constructor like this:
Woman.prototype.constructor = Woman;
And not use the Person.call method in my actual constructor method. Two things, having been told that I can't see an easy way to then pass in the parameters using the 2nd approach, and also, just why? What I'm doing seems to work fine.
Am I missing something?
Is there some cases where what I'm doing will give unpredictable errors?
Can anyone give a definitive 'correct' approach and the reason for it?
What you have is, I think, considered to be the best approach. The point you raise however is irrelevant:
Woman.prototype.constructor = Woman;
is not a replacement for Person.call(...). In fact, those two things have nothing in common, they serve different purposes:
Calling the parent constructor in the child constructor ensures that the child instance is correctly initialized. It's like calling super() in ES6 or other languages.
Assigning to constructor simply restores the original value of Women.prototype.constructor. If you did not do that, brenda.constructor would refer to Person. This doesn't have an impact on the internal workings of your inheritance, but other code that consumes your object might rely on constructor having the correct value. See also Advantages of setting the "constructor" Property in the "prototype".
So the answer to your question is: you should do both.
Sometimes you see the assignment taking place as part of the Object.create call. This is even more accurate, since it recreates the original characteristics of the property (like non-enumerability):
Woman.prototype = Object.create(Person.prototype, {
constructor: {value: Woman, writable: true}
});
FWIW, I believe one of the reasons of introducing class in ES6 was to reduce the confusion around constructor functions and prototypes. That is not to say that you should not know about it, after all, class is more or less just syntactic sugar, but it just makes inheritance a bit easier:
class Woman extends Person { // almost like Woman.prototype = Object.create(Person.prototype)
constructor(name) {
super(name); // almost like Person.call, but enforced by the interpreter
this.gender = "female";
}
}
this is OOP approach in JS
var Person = function(name) {
this.name = name;
}
Person.prototype.greeting = function(){
var newPerson = new Person(this.name);
alert("Greetings, I am " + name);
return newPerson;
}
Person.prototype.toString=function(){
return '[Person "'+this.name+'"]';
}
Woman.prototype = new Person();
Woman.prototype.constructor=Woman;
function Woman(name){
this.name=name;
}
Woman.prototype.toString=function(){
return '[Woman "'+this.name+'"]';
}
var somePerson = new Person('Mr.');
var myPerson = new Woman('She');
alert('somePerson is '+somePerson); // results in 'somePerson is [Person "Mr."]'
alert('myPerson is '+myPerson); // results in 'myPerson is [Woman "She"]'
myPerson.greeting(); // calls a method inherited from Person

javascript inheritance pattern comparison

I have read through some tutorials about javascript prototypal inheritance patterns but I am not sure which is the best practice out of the following two. I noted that many people do this inheritance pattern:
var A = function (){}
A.prototype = {}
var B = function () {
A.apply(this, arguments); // Calling the constructor of A
}
B.prototype = new A(); // Inherit from A through an instance
Alternative, there are some sources that do the following pattern instead:
var A = function (){}
A.prototype = {}
var B = function () {
A.apply(this, arguments); // Calling the constructor of A
}
for (var prop in A.prototype) {
B.prototype[prop] = A.prototype[prop]; // Inherit from A by copying every property/methods from A
}
Although both patterns work, I rarely see people use the latter inheritance pattern (ie. copying each property/methods from the parent's prototype) - why? Is there something wrong with copying properties/methods directly from parent to child? Also, are these two patterns intrinsically different in some ways?
Thank you.
These patterns are very different, and as you may have guessed, the first is better (but not the best possible). Let us compare:
The Most Modern, Best Pattern
B.prototype = Object.create(A.prototype);
This uses the Object.create function to set B.prototype to a new object, whose internal [[Prototype]] is A.prototype. This is basically exactly what you want: it will make B instances delegate to A.prototype when appropriate.
The Original Pattern
B.prototype = new A();
This was how things used to be done, before ES5's Object.create came about. (Although there were workarounds, even if they were not widely used.) The problem with this approach is that any instance-only data properties also end up on B.prototype, which is not desired. Additionally, any side effects of calling A's constructor will happen. Essentially this approach muddles two related, but different concepts: object instantiation, and object construction.
The Non-Standard Pattern from Your Post
for (var prop in A.prototype) {
B.prototype[prop] = A.prototype[prop];
}
This pattern has several problems:
It will copy properties from everywhere in A's prototype chain, all the way down to Object, directly into B.prototype. This defeats much of the purpose of prototypal inheritance, wherein you should be delegating up the prototype chain, instead of squashing it into one single level.
It only gets enumerable properties from A.prototype and its prototype chain, since for ... in skips non-enumerable properties.
It messes up any getters or setters defined on A.prototype (or its prototype chain), simply copying over their value instead of the getter/setter functions.
It will look effin' weird to anyone trying to read your code.
Here is another method using the factory pattern, no prototypes:
/* parent */
function Animal(name, legs)
{
/* members and methods declared within a new object */
var obj =
{
name: name,
legs: legs,
description: function ()
{
return this.name + " is an animal";
},
printNumLegs: function ()
{
return this.name + " has " + this.legs + " legs";
}
}
return obj;
}
/* subclass */
function Cat()
{
/* apply parent arguments in the context of the current object */
var obj = Animal.apply(this, arguments);
/* public member */
obj.furColor = "black";
/* private member */
var sleeping = false;
/* private method */
function printSleepingState()
{
/* can access public member ('name') without it being passed as constructor argument */
return obj.name + " is " + (sleeping ? "sleeping" : "not sleeping");
}
/* declare a new method */
obj.printFurColor = function ()
{
return obj.name + " has " + obj.furColor + " fur";
}
/* overloading */
/* save parent method if needed */
var oldDescription = obj.description;
obj.description = function ()
{
return oldDescription.apply(obj) + " and " + printSleepingState();
}
return obj;
}
/* create object without new */
var kitty = Cat("Kitty", 4);
kitty.furColor = "yellow";
There is no "best" method anyway...it's all a matter of taste.
The first variant looks like a common prototypal inheritance. It has a small minus, that if function A takes some required arguments, you should pass them when setting a prototype for function B. It also creates an instance of a parent object for a prototype. If you don't need such a behavior the second variant looks useful.
By the way:
Take a look at The third variant to make prototypal inheritance. This is also very useful sometimes.
EDIT: As far as I understood, the third variant is an old-fashioned variant of Domenic's solution (for old browsers that have no Object.create function).
I realize this answer is late, but I thought I would add comments for future readers.
I would like to add that there are other options than the those described above.
An alternative to inheritance is mix-ins. Visit http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/
There are some similarities between mix-ins, and approach #2, but they are different.
In many situations, Mixins can be much more flexible than the inheritance techniques described above because they allow one object to be mixed (take on behaviour) from several mix-ins.
Although mix-ins add behaviour, they typically do not add state to your object.

Prototypal Inheritance best practices?

I'm just getting into JavaScript and I'm trying to wrap my head around prototypal inheritance. It appears that there's multiple ways to achieve the same effect, so I wanted to see if there is any best practices or reasons to do things one way over the other. Here's what I'm talking about:
// Method 1
function Rabbit() {
this.name = "Hoppy";
this.hop = function() {
console.log("I am hopping!");
}
}
// Method 2
function Rabbit() {}
Rabbit.prototype = {
name: "Hoppy",
hop: function() {
console.log("I am hopping!");
}
}
// Method 3
function Rabbit() {
this.name = "Hoppy";
}
Rabbit.prototype.hop = function() {
console.log("I am hopping!");
}
// Testing code (each method tested with others commented out)
var rabbit = new Rabbit();
console.log("rabbit.name = " + rabbit.name);
rabbit.hop();
All of these appear to have the same effect individually (unless I'm missing something). So is one method preferred over the other? How do you do it?
When you put a method on the prototype, every instance object shares the same reference to the method. If you have 10 instances, there is 1 copy of the method.
When you do what you did in example 1, every instance object has its own version of the same method, so if you create 10 of your objects, there are 10 copies of the code running around.
Using the prototype works because javascript has machinery for associated a function execution with a instance, i.e. it sets the this property for the execution of the function.
So using the prototype is highly preferred since it uses less space (unless of course, that is what you want).
In method 2, you are setting the prototype by setting it equal to an object literal. Note that here you are setting a property, which I think you don't intend to do, since all instances will get the same property.
In Method 3, you are building the prototype one assignment at a time.
I prefer method 3 for all things. i.e. In my constructor I set my property values
myObj = function(p1){
this.p1; // every instance will probably have its own value anyway.
}
myObj.prototype.method1 = function(){..} // all instances share the same method, but when invoked **this** has the right scope.
Let's look at your examples one at a time. First:
function Rabbit() {
this.name = "Hoppy";
this.hop = function() { //Every instance gets a copy of this method...
console.log("I am hopping!");
}
}
var rabbit = new Rabbit();
The above code will work, as you have said in your question. It will create a new instance of the Rabbit class. Every time you create an instance, a copy of the hop method will be stored in memory for that instance.
The second example looked like this:
function Rabbit() {}
Rabbit.prototype = {
name: "Hoppy",
hop: function() { //Now every instance shares this method :)
console.log("I am hopping!");
}
}
var rabbit = new Rabbit();
This time, every instance of Rabbit will share a copy of the hop method. That's much better as it uses less memory. However, every Rabbit will have the same name (assuming you don't shadow the name property in the constructor). This is because the method is inherited from the prototype. In JavaScript, when you try to access a property of an object, that property will first be searched for on the object itself. If it's not found there, we look at the prototype (and so on, up the prototype chain until we reach an object whose prototype property is null).
Your third example is pretty much the way I would do it. Methods shared between instances should be declared on the prototype. Properties like name, which you may well want to set in the constructor, can be declared on a per-instance basis:
function Rabbit(rabbitName) {
this.name = rabbitName;
}
Rabbit.prototype.hop = function() {
console.log("Hopping!");
}
This is an important issue that is often misunderstood. It depends what you're trying to do. Generally speaking, hvgotcode's answer is right on. Any object that will be instantiated frequently should attach methods and properties to the prototype.
But there are advantages to the others in very specific situations. Read this, including the comments: http://net.tutsplus.com/tutorials/javascript-ajax/stop-nesting-functions-but-not-all-of-them/
There are occasions when method 1 above helps, enabling you to have "private" readable/writable properties and methods. While this often isn't worth the sacrifice in heavily instantiated objects, for objects instantiated only once or a few times, or without many internal assignments, or if you're in a dev team environment with lots of different skill levels and sensibilities, it can be helpful.
Some devs incorporate another good strategy that attempts to bridge some of the shortcomings of the others. That is:
var Obj = function() {
var private_read_only = 'value';
return {
method1: function() {},
method2: function() {}
};
};
// option 4
var Rabbit {
constructor: function () {
this.name = "Hoppy";
return this;
},
hop: function() {
console.log("I am hopping!");
}
};
var rabbit = Object.create(Rabbit).constructor();
console.log("rabbit.name = " + rabbit.name);
rabbit.hop();
When doing prototypical OO using new and constructor functions is completely optional.
As has already been noted, if you can share something through the prototype do so. Prototypes are more efficient memory wise and they are cheaper in terms of instantiation time.
However a perfectly valid alternative would be
function Rabbit() {
// for some value of extend https://gist.github.com/1441105
var r = extend({}, Rabbit);
r.name = "Hoppy";
return r;
}
Here your extending "instances" with the properties of the "prototype". The only advantage real prototypical OO has is that it's a live link, meaning that changes to the prototype reflect to all instances.
Do some performance testing (declare around 1 milion rabbit variables) . First method will be the most time and memory consuming.

Categories