What's the recommended way to declare fields of a class in JavaScript? - javascript

Is it better to declare fields of a class in this way:
function MyClass() {
this.aMethod = function() {
// code
}
}
Or this way:
function MyClass() {
}
MyClass.prototype.aMethod = function() {
// code
}
Any why?
Thanks in advance.

The prototypal method, because it's more efficient as it adds the function to the prototype meaning any objects created with the constructor automatically get that method, while the former/first way those methods have to be created for each and every little object you make individually.
Though really it depends on what you're doing with the method. If you don't need it to be a public method then you may opt with this.method or a function statement.

As #meder said, the prototypal approach is the preferred way, since the the methods are declared in the constructor's prototype, but the first approach you show us is useful to implement private members, for example:
function MyClass() {
var privateValue = 'secret';
function privateMethod() { }
this.aMethod = function() {
// privateValue and privateMethod are accessible here.
return privateValue;
}
}
var foo = new MyClass();
foo.aMethod(); // "secret"
foo.privateValue; // undefined !
That's what Crockford calls a privileged method, because this method has access to all the identifiers created in the lexical scope of the constructor (a closure is created).

It depends on the usage. Use the first method when you are going to use the method frequently; the second, when you are going to make rare use of it. The reason is that when the object is created with the constructor, prototypal methods are not loaded, they are only loaded when called, which will save you some performance.

Related

Get class methods from a javascript function

Let's say I have a function, and I need to check if it has a class method of a certain name. For example:
function Foo() {
this.bar = function() {
console.log("I am bar!");
}
}
And I want to check if the Foo class actually has the bar method.
I can create a new instance of Foo and then check it, I was just wondering if there was a better way to do this.
I can create a new instance of Foo and then check it, I was just wondering if there was a better way to do this.
No, not if the method is added in the constructor as in your example. There's nothing to check until you create an instance. (Well, except the source code of the constructor function, as Pointy points out in a comment.)
If it were defined on Foo.prototype, it would be a different matter:
function Foo() {
}
Foo.prototype.bar = function() {
console.log("I am bar!");
};
Then you could check by looking for Foo.prototype.bar.
Side note: Calling them "class methods" is likely to confuse people. In class-based OOP, a "class method" is usually one that's not specific to instances, as opposed to being one that's specific to instances but defined by the class. And of course, JavaScript doesn't have class-based OOP (it has prototypical OOP instead, even as of ES6 which adds more class-like trappings).
There is no method until you do:
var x = new Foo();
So, you will have to do that and then test:
if (typeof x.bar === "function")
If your code was using the prototype for the bar method, then you could test the prototype directly without constructing an object, but since the method is only created inside the constructor, you have to run the constructor in order to see it.
TJ Crowder is correct in that you cannot examine the constructor to examine if the "class" Foo has a certain method. However, you can do this:
function Foo() { /* Constructor */ }
Foo.prototype.bar = function() { /* Whatever you want */ }
Then to test, you can simply do typeof Foo.prototype.bar === "function".
There are various advantages and disadvantages to this approach. (See Use of 'prototype' vs. 'this' in JavaScript?). If you really need to test if a certain constructor's instances will inherit a method, you can use the prototype approach.

How to make Constructor parameters available to prototype functions JavaScript

In the simplified example below, the MyService.doSomething function has access to someDependency because the prototype function is defined within the MyService constructor.
// Define MyService Class
function MyService(someDependency) {
MyService.prototype.doSomething = function(){
return someDependency.doSomething();
}
}
To use MyService with a given dependency:
// Construct MyService
var myService = new MyService(someDependency);
var result = myService.doSomething();
I am pretty sure that this is bad practice but how do I make the constructor parameter someDependency available to the function?
First of all, you should initialize the prototype at the same time as when you define the constructor, instead of redefining it every time you create a new instance.
// Define MyService Class
function MyService(someDependency) {
// ...
}
MyService.prototype.doSomething = function(){
// ...
}
After that, all that remains to go is to copy the parameters into instance variables explicitly
// Define MyService Class
function MyService(someDependency) {
this.someDependency = someDependency;
}
MyService.prototype.doSomething = function(){
return this.someDependency.doSomething();
}
All instance variables are piublic. If you want you can use a naming convention (like starting with an underscore) to mark "pseudo-private" variables.
If you want to use the function parameter directly instead of assigning instance variables you can have the methods be closures belonging to your object instead of a sharred function at the prototype. This lets you use variables from the constructor (and those variables are private!) but makes it harder to create subclasses.
function MyService(someDependency) {
this.doSomething = function(){
return someDependency.doSomething();
};
}
The version with closures can be slower than the prototype version but I wouldn't worry about i most of the time.
Well, the common way is - if an object has a property, it should actually have that property.
function MyService(someDependency) {
this.dependency = someDependency; // set it on the object
}
MyService.prototype.doSomething = function(){
return this.dependency.doSomething(); // now the prototype can access it
}
You're also right in that the way you're currently doing it is bad in at least one sense - the extra closure makes it slower. As for readability - I find it harder to read but that's debatable. It also makes subclassing and extending via prototypical inheritance a lot harder.

Javascript Modular Prototype Pattern

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";
};

JavaScript Code Architecture - Use Constructor Functions Or Not

Please help me decide whether I should use a function's prototype object and the "new" keyword or completely stay away from constructor functions.
Situation:
Function called widget() that will be called 10-15 times to initialize each widget on the page. widget() contains quite a few internal methods.
Each time widget() is called, the function needs to return an object that acts as an API to operate on the widget.
Question
1) Do I put all the internal methods inside Widget() under its prototype property? It does not make sense but the main reason for this is to not re-instantiate the internal functions every time widget() is called.
But if I do put the internal functions in prototype, each instantiated w object (w = new Widget();) has access to internal private methods.
2) If I stay away from constructor functions and new keyword and structure my code as down below, how do I fix the performance concern of the internal functions getting re-instantiated every time widget() is called.
function widget()
{
var returnObj = {};
/* Add internal functions but this will be re-instantiated every time */
return returnObj;
}
You have a bit of a tradeoff here. As you seem to already understand, methods you put on the .prototype are publicly available, but that is the most efficient places to put methods as they are automatically added to all new copies of that object in a very efficient manner. When using .prototype for methods, there is only one copy of your methods and a reference to that single copy is automatically added to all new instantiations of that object.
But, javascript doesn't have private methods built-in and the only work-around for that involves not using the .prototype for them or for any methods that need to call the private methods.
This article by Doug Crockford is a pretty good description of how you can create privacy for either data or methods in any object.
In either case, I don't see any reason to avoid using the new keyword to create new objects. You can make either .prototype or private methods work with new.
But, if you want to achieve truly private methods, then you can't use .prototype for either the private methods or any methods that need to access them so you have to decide which is more important to you. There is no single correct answer because your need for privacy is situation-specific.
In my coding, I generally don't enforce privacy and I do use .prototype and new. I designate "non-public" methods on the prototype by starting their name with an underscore. This is a notational convention, not an access enforcement scheme.
In answer to your second question about avoiding the new operator and reinstantiating methods, I'd just ask why you're doing this? What are you gaining? I'm not aware of any downsides to using new. As best I understand your decision about whether to use .prototype vs. manually create/assign methods in your constructor should be about the need for private methods.
FYI, 15 objects is hardly going to create a significant difference in performance either way here. I would evaluate your need for true privacy and make your decision based on that. If you HAVE to enforce privacy, then go with the Crockford method for implementing private methods. If you don't HAVE to have true privacy, then use .prototype. I don't see a reason here to avoid using new in either case.
You can use a metaconstructor* pattern to get around this.
function defineCtor(metaCtor) {
var proto = new metaCtor();
var ctor = proto.hasOwnProperty('constructor') ?
proto.constructor : new Function();
return (ctor.prototype = proto).constructor = ctor;
}
Now you have a function that constructs constructors (or more accurately constructs prototypes and returns constructors).
var Widget = defineCtor(function() {
function doInternalStuff() {
// ...cant see me
}
// this function ends up on the prototype
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
Explanation
defineCtor takes a single anonymous function as a property. It invokes the function with new, creating an object. It assigns the object as the prototype property of a new constructor function (either an empty function, or the generated prototype object's own constructor property), and returns that function.
This provides a closure for your internal functions, addressing your question 1, and sets up the constructor/prototype pair for you, addressing question 2.
Comparison
Compare the defineCtor technique to the following two examples.
This example uses the prototype, and has problem 1: the internal stuff is not encapsulated.
function Widget(options) {
this.options = options;
}
Widget.prototype = {
getFoo: function() {
return doInternalStuff();
}
};
// How to encapsulate this?
function doInternalStuff() { /* ... */ }
This example sets up everything in a constructor, and has problem 2: each time it constructs an object, it instantiates new function objects for each property.
function Widget(options) {
this.options = options;
function doInternalStuff() { /* ... */ }
this.getFoo = function() {
return doInternalStuff();
};
}
This example uses the technique described above to provide encapsulation while still leveraging the prototype:
var Widget = defineCtor(function() {
// ^
// This function runs once, constructing the prototype.
// In here, `this` refers to the prototype.
// The real constructor.
this.constructor = function(options) {
// In function properties, `this` is an object instance
// with the outer `this` in its prototype chain.
this.options = options;
};
function doInternalStuff() { /* ... */ }
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
This approach has a few benefits, some more immediately obvious than others.
It provides encapsulation. You could do this by wrapping the first "comparison" example in an immediately invoked function, but this approach may be cleaner and more easily "enforced" in a team setting.
It's extensible. You can give your "metaconstructor" functions their own prototypes, with function properties like "extends", "mixin", etc. Then, inside the body of metaCtor, you can write things like this.extends(BaseWidget). The defineCtor API never needs to change for any of this to happen.
It "tricks" Google Closure Compiler, Eclipse, jsdoc, etc. into thinking you are defining the actual constructor function rather than a "meta function." This can be useful in certain situations (the code is "self-documented" in a way these tools understand).
* As far as I know, the word "metaconstructor" is completely made up.

Creating functions for an object in javascript

As far as I can tell, there are two main ways of creating functions for an object in javascript. They are:
Method A, make it in the constructor:
function MyObject() {
this.myFunc1 = function() {
...
}
this.myFunc2 = function() {
...
}
...
}
Method B, add it to the prototype:
function MyObject() {
...
}
MyObject.prototype.myFunc1 = function() {
...
}
MyObject.prototype.myFunc2 = function() {
....
}
Obviously if you did:
MyObject.myFunc3 = function() {
....
}
then myFunc3 would become associated with MyObject itself, and not any new objects created with the new keyword. For clarity, we'll call it method C, even though it doesn't work for creating new objects with the new keyword.
So, I would like to know what the differences between the two are. As far as I can tell they have the same effect logically, even if what's happening on the machine is different.
If I were to guess I would say that the only real difference is when you're defining them in the constructor like in method A, it creates a whole new function object for each object that's created, and Method B only keeps one copy of it (in MyObject), that it refers to any time it's called. if this is the case, why would you do it one way over the other. Otherwise, what is the difference between method A and method B.
The advantage of giving a separate function to each object is that you can close over variables in the constructor, essentially allowing for "private data".
function MyObject(a,b) {
var n = a + b; //private variable
this.myFunc1 = function() {
console.log(n);
}
};
vs
function MyObject(a,b) {
this.n = a + b; //public variable
}
MyObject.prototype.myFunc1 = function() {
console.log(this.n);
}
Whether this is a good idea or not depends on who you ask. My personal stance is reserving constructor functions for when I actually use the prototype, as in option #2 and using plain functions (say, make_my_object(a,b)) when using closures, as in option #1.
The idea is that you can modify the prototype at any time and all objects of the type (even those created before the modification) will inherit the changes. This is because, as you mentioned, the prototype is not copied with every new instance.
The MyObject in method A is an instance for inner functions.
You cannot call its functions explicitly outside of it unless object (you can call it a class) was instantiated.
Assume this:
MyObject.MyFunc1(); // will not work
var obj = new MyObject();
obj.MyFunc1(); // will work
so this is the same as any class in other languages. Describing usefulness of classes and their usages goes beyond that question though.
Also to notice:
function MyObject() {
var privateVar = "foo";
this.publicProperty = "bar";
// public function
this.publicFunc = function() {
...
}
// private function
function privateFunc () {
...
}
}
For method B it's same as with method A, the only difference is prototyping is a style of creating object. Some use prototypes for readability or out of preference.
The main advantage in prototypes is that you can extend existing object without touching the original source. You need to be careful with that though.
(as example Prototype framework)
For method C you can call them a static functions. As you said they can be called explicitly by referring through object like:
MyObject.MyFunc1();
So which one to use depends on situation you're handling.

Categories

Resources