Best Practices for "Abstract" functions in JavaScript? - javascript

I just wrote some JavaScript code that follows along with what I believe to be good practice for creating an object with closure and some functions:
var myStuff = (function() {
var number = 0;
var fn = {};
fn.increment = function() { number++; };
fn.decrement = function() { number--; };
fn.getNumber = function() { return number; };
return fn;
})();
myStuff.increment();
myStuff.increment();
alert(myStuff.getNumber()); // alerts '2'
I have no problem writing code like the previous snippet. I would like to write some code with functionality similar to a OOP "abstract" class. Here is the result of my effort:
var myStuff = (function () {
var number = 0;
var fn = {};
fn.increment = function () { number++; };
fn.decrement = function () { number--; };
fn.doSomethingCrazy = function () { throw new Error('not implemented'); }; // I want to specify later what this does.
fn.doSomethingCrazyTwice = function () { fn.doSomethingCrazy(); fn.doSomethingCrazy(); };
fn.getNumber = function () { return number; };
return fn;
})();
myStuff.doSomethingCrazy = function () { this.increment(); this.increment(); };
myStuff.doSomethingCrazyTwice();
alert(myStuff.getNumber()); // alerts '4'
The above code snippet works, but it doesn't seem graceful. Perhaps I'm trying to force JavaScript (a functional language) to do something it isn't designed to do (object inheritance)
What is a good way to define an object in JavaScript so that a function of that object can be defined later?

Just don't define the function.
Javascript is a duck-typed language. If it looks like a duck and it quacks like a duck, it is a duck.
You don't need to do anything special to make this work; as long as the function exists when you call it, it will work fine.
If you call it on an instance that doesn't have the function, you'll get an error at the callsite.

I agree with SLaks, there's no need to define the function, but I tend to anyway. That's because to me the important part is in the documentation. When somebody reads my class, I want it to be clear that you must implement these methods, what arguments will be passed and what should be returned.
This is from a file at work. There were multiple implementations of a feature with a base class that did the data loading at intervals.
/**
* Called when data is received and should update the data buffer
* for each of the charts
*
* #abstract
* #param {cci.ads.Wave[]} waves
* #void
*/
updateChartsData: function(waves){
throw "Abstract method updateChartsData not implemented";
},
2019 Update
Use TypeScript if you can Declaring abstract method in TypeScript

As our team is growing and our javascript project is getting more complex we have to start implementing OO features as well.
In our javascript 'abstract' method we simply throw an error, or pop up an alert. This is an example from out Page object:
Page.initialLoad = function() { //abstract
alert('Page.initialLoad not implemented');
};
In java world it is analagous to :
public void abstract initialLoad();
The Java code gives a compile time error, however in the Javascript we would get a runtime error. (a dirty error dialog saying that an implementing object hasn't implemented that method yet).
We have a number of disparate teams that use the Page object; the philosophy of 'duck typing' absolutely does not cut it with us. Without these pseudo 'abstract' methods we have a general lack of API communication, and sometimes we get sabotaging of the super object (ie. because a user has no idea they are supposed to implement the method).
I am tired of this 'duck typing' philosophy. I'm not sure if proponents have ever been in a complex Javascript project with 10+ developers.

If you don't find your way graceful there is probably a way to create some functions to stramline the process to make it look better. But back to the topic...
Yes, Javascript has builtin delegation, aka inheritance, via prototypes.
Given a prototypal object:
var proto = {
f: function(){ console.log(this.x); }
}
We can create a new object that inherits from it:
var obj = Object.create(proto);
obj.x = 42;
obj.f(); //should work!
for(var i in obj) console.log(i);
//should print x, f and some other stuff perhaps
Just note, that doing things directly via Object.create is not always supported (old browsers, etc). The old (and some may say, normal) way do do stuff is via the funky new operator (don´t think too much on the name - its confusing on purpose to distract the Java people)
function Constructor(arg){
this.x = arg;
}
Constructor.prototype = {
f: function(){ ... }
};
var obj = new Constructor(17);
obj.f();
An important difference to consider with prototypical inheritance is the lack of private variables. Only public variables can be inherited! Because of this, a common convention is to use underscore as a prefix for private and protected variables.

You might want to take a look at this previous post How do I create an abstract base class in JavaScript?
Just a few sites for some light reading for you on OOP and JavaScript, I am assuming that your new to JavaScript as an OOP langauge based of a comment you said
http://mckoss.com/jscript/object.htm
http://www.codeproject.com/KB/aspnet/JsOOP1.aspx
http://www.javascriptkit.com/javatutors/oopjs.shtml

Related

JavaScript syntax: what is ({ }) Is it a function or object?

as a developer with OOP background(c#, Java) OOP JavaScript is wild horse for me. I am trying learn nuts and bolts of language and then jump on libraries (Am I wrong?);
so, I checked dozen of books/tutorials about objects, functions...etc..learned several ways to create objects but syntax used in almost every JS library confuses me. namely
var Person = Backbone.extend.Model({
//pretty complex staff
})
what is Model behind the scenes? object? function?
That is not the correct backbone syntax. That should actually be:
Backbone.Model.extend({
});
In that case, extend is a function. Note that you are invoking it with (). However, functions in javascript are also objects (more on that in a moment). You may be confused about the {} inside of it. That is because you are passing that object as a parameter to the function.
If extend was a function that expected a string as a parameter/argument, it would look like this: extend('some string'). In this case, it is taking an object. For example:
var someObject = {
someProperty: 'someValue'
}
var Person = Backbone.Model.extend(someObject);
is the same as:
var Person = Backbone.Model.extend({
someProperty: 'someValue'
});
Here's just a sample of how that might look in the function:
Backbone.Model.extend = function(obj) {
console.log(obj.someProperty); //logs "someValue"
}
As I said, in javascript, functions are also objects. Actually, most things are objects. I recommend you study more on this. As it's not the focus of your question, I'll just briefly demonstrate:
var someObj = {
someProperty: '123'
};
console.log(someObj.someProperty); //logs "123"
var someFunction = function() {
};
someFunction.someProperty = '123';
console.log(someFunction.someProperty); //logs "123"
Though, it would be better to add to the prototype so that inheritance will work like this:
someFunction.prototype.someProperty = '123';
var foo = new someFunction();
console.log(foo.someProperty); //logs "123"
Here's a little demo you can mess with (click).
So.. in summary, JavaScript is win-sauce.
Are you sure you typed this in correctly? I think you reversed the order of Model and extend. I'm looking at the documentation now, and I see:
Models are the heart of any JavaScript application, containing the interactive data as well as a large part of the logic surrounding it: conversions, validations, computed properties, and access control. You extend Backbone.Model with your domain-specific methods, and Model provides a basic set of functionality for managing changes.
The extend function is implemented in many Javascript libraries: Backbone, Underscore, and jQuery for a few. What it does is to take an object and add methods and instance variables to it. After all in Javascript, objects are simply hashes. This creates an object that has a few methods and data.
var counter = {};
counter.count = 0;
counter.increment = function() {
this.count++;
}
counter.decrement = function() {
this.count--;
}
If you want inheritance, you use the object or its constructor's prototype property. The extend method is a way of simulating that. Here's more of the Backbone documentation:
extendBackbone.Model.extend(properties, [classProperties])
To create a Model class of your own, you extend Backbone.Model and provide instance properties, as well as optional classProperties to be attached directly to the constructor function.
extend correctly sets up the prototype chain, so subclasses created with extend can be further extended and subclassed as far as you like.
var Note = Backbone.Model.extend({
initialize: function() { ... },
author: function() { ... },
coordinates: function() { ... },
allowedToEdit: function(account) {
return true;
}
});
In conventional Javascript, you'd write:
function Note() {
this.initialize = function() {...};
this.author = function() {...};
this.coordinates = function() {...};
this.allowedToEdit = function(account) {
return true;
};
}
Note.prototype = new Model(); // Inheritance.
Inheritance in JavaScript reminds me of the Perl maxim: There's More than One Way to Do This.
Welcome to stackoverflow,
I strongly advise you to have a look at Douglas Crockford's Website and there are also insightfull videos in YUI Theater - start with the ones of Douglas. He's the one who discovered JavaScript has good parts. I also found John Resig's Secrets of the JavaScript Ninja very helpfull for grocking the language (John is the creator of the omnipresent jQuery Library). I would further advise you to look at some libraries (and their code - that's how I learned it - just start with jQuery). There are a ton of other libraries out there but one step at a time :-).
Now to your question:
The Backbone.Model is a constructor function, normally you would use it like in Java new Backbone.Model({ configOption: true, ... }). But juicy as JavaScript is it allows you to do crazy things under the hood. For example you can implement your own OOP Class implementation or you can program in a functional style like you would do in Scheme or Lisp. What you see here is Backbone's own subtyping wrapper in action (virtually any decent JS library provides some way to do this).
The code is actually doing something along the lines of this:
// Creating a sub type of the Backbone.Model *class* - it's not really
// a class like in Java or C# but rather a (constructor) function.
var Person = Backbone.Model.extend({
defaults: {
hasTheOneRing: true
},
initialize: function (hasTheOneRing) {
// Note that Backbone is implementing getters/setters
// under the hood so you can listen for change events later
this.set('hasTheOneRing', hasTheOneRing);
}
// More configuration ...
});
// Person now is a constructor function that creates instances
// of it's *class* when you create an object with it
var frodo = new Person(true),
sam = new Person(); // Note that you can supply as many arguments as you wish
// Frodo has the ring
console.log(frodo.get('hasTheOneRing'));
// Sam doesn't have the ring (well not all the time)
console.log(sam.get('hasTheOneRing'));
// In plain old JavaScript the sub typing mechanism works a little bit like this:
// A constructor function is just a function
function Person() {
// JS doesn't have the notion of *super* or *base* but you
// can emulate the behavior as many libraries do in the wild
Backbone.Model.call(this);
}
// The prototype of a person is based on that of a Backbone.Model
Person.prototype = Object.create(Backbone.Model.prototype);
// Object.create has not been there since the beginning. After
// Douglas Crockford discovered the good parts this function
// has been adapted into the standard portfolio of every modern browser
// what it does is essentially just:
function create(object) {
// There's actually more going on in here but you get the idea
function F() {}
F.prototype = object;
return new F();
}
// So this means almost the same
Person.prototype = new Backbone.Model();
My way of getting to love JS was to read library code - and Backbone is open source so have a read and be amazed by the awesomeness g. I think the fact that JS is just plain text send over the wire had a big influence on the language getting that strong in the ecosystem, even Microsoft couldn't stop it.
Give the language a try, when it clicks you'll most likely actually begin to like it :-).
Happy coding!

javascript "static imports"

Is there anything in javascript that is the equivalent of java static imports? For example, if I have a Math class that looks like
com.example.Math = function() {
function1(...) {}
function2(...) {}
}
Now some of these functions are naturally chained together such that the output to one is the input to another. I can do something like
com.example.Math.function2(com.example.Math.function1());
This is a little ugly looking, and I would really like to do something like:
function2(function1())
But I don't want to put function1 and function2 in the global namespace. Is this possible?
Yes, there is. It's called with.
with (com.example.Math) {
function2(function1());
}
That said:
Using with is not recommended, and is forbidden in ECMAScript 5 strict mode. The recommended alternative is to assign the object whose properties you want to access to a temporary variable.
For example:
var m = com.example.Math;
m.function2(m.function1());
How about:
var Math = com.example.Math;
and then:
Math.fn1( Math.fn2(...) );
I'm assuming of course that your code is not global code. (If you're not familiar with the concept of avoiding global code in JS, read about the module pattern.)
You can go one step further:
var Math = com.example.Math,
func1 = Math.func1,
func2 = Math.func2;
and then:
func1( func2(...) );
I would do something like this:
var O = function() {
var that = {};
var PI = Math.PI;
that.circ = function(r) {
return 2*PI*r;
};
return that;
};
var o = O();
console.log(o.circ(1));
Notice how PI is used without the Math namespace in the O.prototype.circ method.
In JavaScript, there is no distinction between a namespace and an object, so some would argue that Math is not a namespace, but since JavaScript doesn't support the concept, it is as much a namespace as com.mycompany.somelibrary.
One option is to use a closure to wrap the object. It doesn't necessarily eliminate the object itself, but it helps with readability and if you are using a JS compressor can help reduce the output file size:
(function(Math) {
Math.function2(Math.function1(...));
}(com.example.Math);)
You can also pass in multiple objects (ie: function(Math, Foo) {...}(com.example.Math, com.example.Foo)).
If you want to use just a few functions directly, just pass them in like this:
(function(function1, function2) {
function2(function1(...));
}(com.example.Math.function1, com.example.Math.function2);)
This, however, removes the relationship between the Math instance and the functions, so you might get some weird behavior if your methods depend on instance variables. As an example of how that won't work, imagine this class:
com.example.Counter = {
counter: 0,
increment: function() { this.counter++; }
}

JS Private methods not redefined at each constructor call

How do you make a Javascript private method that is not redefined each time you call the constructor ?
As far as I know, in OOP-JS, private methods are methods defined in the "constructor method" of one's "class", called each time one instantiates a new "object". I was thinking maybe a function declaration (i.e. function name(), as opposed to function expression var name = function()) would do the trick, but how can I be sure that the following code only declares my function once ?
​function Tester() {
function test () {
console.log("executed");
}
}
var t1 = new Tester();
var t2 = new Tester();
How do you make a Javascript private method that is not redefined each time you call the constructor ?
You can't (well, see below for a bit of wiggle room). But unless you're going to have thousands of instances of Tester, don't worry about it too much; most engines probably reuse the underlying code across the multiple function objects that get created. (The code, mind; not the function object or the context it closes over, which must be unique and allocated each time. But they need not be large. Of course, quite a function functions are fairly small as well...)
...how can I be sure that the following code only declares my function once ?
You can be sure that it doesn't; it declares the function each time Tester is called. Witness:
​function Tester() {
this.test = test;
function test () {
console.log("executed");
}
}
var t1 = new Tester();
var t2 = new Tester();
console.log(t1.test === t2.test); // "false"
Note that you can have functions that are private to the implementation, but not assigned to any instance of the object. The module pattern is handy for doing that:
var Tester = (function() {
function Tester(name) {
this.name = name;
}
Tester.prototype.publicFunction = function() {
privateFunction.call(this);
};
function privateFunction() {
console.log("My name is " + this.name);
}
return Tester;
})();
var t = new Tester("Fred");
t.publicFunction(); // Outputs "My name is Fred" via the private function
There, privateFunction is completely private, accessible only to the code within the anonymous function. And there's only one copy of it, but you can call it as though you were calling a method of a Tester instance using privateFunction.call(this).
Alternately, of course, since using call is slightly slower than doing a normal call, you could just pass the instance as an argument:
var Tester = (function() {
function Tester(name) {
this.name = name;
}
Tester.prototype.publicFunction = function() {
privateFunction(this);
};
function privateFunction(t) {
console.log("My name is " + t.name);
}
return Tester;
})();
var t = new Tester("Fred");
t.publicFunction(); // Outputs "My name is Fred" via the private function
Of course, the extra cost of call is only a problem if and when it's a problem; unless you're calling something hundreds of thousands of times in a tight loop, it's unlikely to matter. So whether to use call and this or pass an argument would be primarily a style choice.
It took me a while (coming form an ActionScript 3 background), but I feel that I should share with you how I learned to stop worrying and love the lack of private methods ;)
Many popular JavaScript libraries, such as Backbone.js and js-Signals simply make use of a naming convention where a leading underscore denotes private members as opposed to using slightly esoteric syntax (although each to their own!). Just to give this some additional context, Python's documentation goes as far as saying that Python does not support private members at all and suggests using an underscore instead.
JavaScript is a very dynamic language; there's no strict type checking and some really exciting scoping; and there are some really cool libraries out there which take advantage of those facts, such as SinonJS which makes it effortless to achieve meaningful test coverage in your codebase; for example:
var instance = new Car("ford");
// Replace the car's engine with test stub.
// Alternative syntax: sinon.stub(instance, '_engine');
instance._engine = sinon.stub(instance._engine);
car.start();
// As the '_engine' object has been mocked it gains new attributes.
ok(instance._engine.checkOil.calledOnce, 'Oil level was checked');
Sorry this answer doesn't really answer your question (T.J's answer is pretty much textbook in that regard) - I just thought it would be worthwhile to offer another possible solution.

JavaScript: Inheritance by prototype, without using prototype to define/call methods

I've been making several libraries and extension libraries, and it's not practical for me to use prototype because in the real-world you actually have private variables that do not need to be accessed from an instantiated object.
var parent_class = function(num) {
var number = num;
this.method = function(anum) {
number += anum;
};
this.getNumber = function() {
var fnumber = number + 2;
return fnumber;
};
};
var child_class = function(num1, num2) {
var sum = num1 + num2;
parent_class.call(this, sum); // initialize parent class
this.method = function() {
sum -= 1;
base.method(sum); // what to do here
};
};
child_class.prototype = new parent_class(); // inherit from parent
child_class.prototype.constructor = child_class; // maintain new constructor
var c = new child_class(1, 4); // child_class.sum = 5, parent_class.number = 5
c.method(); // child_class.sum = 4, parent_class.number = 9
var num = c.getNumber(); // returns 11
Now, without declaring and relying on methods being prototyped, how can I get the what to do here line to work? I understand that I could call this.method(); inside child_class and store it as a variable, but I want overridable methods.
My previous topic was not very forthcoming, as everyone assumes I can just prototype everything or use private variables to get around the problem. There has to be a way to do this without prototyping.
I want to call .method(); from inside an instance of child_class without storing the previous .method(); as a private variable or using prototype methods that, for obvious reasons, cannot access private members.
Just use the prototype, you can mark "private" properties and methods with NULL character prefix or whatever to discourage people from using them, which is all you really need.
MyClass.prototype = {
"\0privateMethod": function(){}
};
If you're using chrome you will see this in console:
Object
privateMethod: function (){}
__proto__: Object
Yet one cannot do myClass.privateMethod(), this should be enough of a hint that this is a private property. To actually call it, you'd need to write myClass["\0privateMethod"]().
After going back to using prototype, your problem should automatically become easy to solve.
You're trying to make JavaScript into something it's not.
Stop doing that.
JavaScript does inheritance through the prototype. Get used to it.
ADDENDUM
Okay, let's clarify.
JavaScript doesn't implement OOP like C++, Java, C#, VB.NET, or any other object oriented language. You have the prototype. You can extend the prototype. If you want to "override a method", you need a reference to the version that previously existed.
Now, the caveat is going to be that anyone, at any time, can come along and replace anything, anywhere. So any assumptions about the stability of your object model are flimsy, at best.
Let the prototype do its job. Any framework you build around it to try to mimic inheritance, abstract base classes, superclasses, and what not, is going to have its own headaches and become a maintenance nightmare.

Pseudo-classical vs. "The JavaScript way"

Just finished reading Crockford's "JavaScript: The Good Parts" and I have a question concerning his stance on the psuedo-classical vs. prototypal approaches. Actually I'm not really interested in his stance; I just want to understand his argument so I can establish a stance of my own.
In the book, Crockford seems to infer that constructor functions and "all that jazz" shouldn't be used in JavaScript, he mentions how the 'new' keyword is badly implemented - i.e. non-Constructor functions can be called with the 'new' keyword and vice versa (potentially causing problems).
I thought I understood where he was coming from but I guess I don't.
When I need to create a new module I would normally start of like this:
function MyModule(something) {
this.something = something || {};
}
And then I would add some methods to its prototype:
MyModule.prototype = {
setSomething : function(){},
getSomething : function(){},
doSomething : function(){}
}
I like this model; it means I can create a new instance whenever I need one and it has its own properties and methods:
var foo = new MyModule({option1: 'bar'});
// Foo is an object; I can do anything to it; all methods of the "class"
// are available to this instance.
My question is: How do I achieve the above using an approach more suited to JavaScript? In other words, if "JavaScript" were a person, what would she suggest?
Also: What does Crockford mean when he says a particular design pattern "is more expressive" then another?
See: Is JavaScript's “new” Keyword Considered Harmful?
It's important to remember that Crockford, like so many other JavaScript programmers, first approached the language with an eye toward "fixing" it - making it more like other (so-called "classical") OO languages. So a large amount of structural code was written, libraries and frameworks built, and... then they started to realize that it wasn't really necessary; if you approach JS on its own terms, you can get along just fine.
The prototypal variant for the example you have looks like the following in my understanding:
Object.beget = function (o) { /* Crockfords replacement for the new */ }
var myModule = {
something : null,
getSomething : function () {},
setSomething : function () {},
doSomething : function () {}
};
And then you can do:
var foo = Object.beget(myModule);
foo.something = bar;
UPDATE: You can also use the builder pattern to replace a constructor like this:
var myModuleBuilder = {
buildMyModule : function (something) {
var m = Object.beget(myModule);
m.something = something || {};
return m;
}
}
so then you can do:
var foo = myModuleBuilder.buildMyModule(something);
Your implementation is problematic because you're replacing the entire prototype object, losing the properties of the inherited function prototype and it would also break, or at least make it more difficult, the ability to make use of inheritance later on if you wrote other classes the same way.
A method more suited to Javascript would be:
var MyClass = function (storeThis) {
this.storage = storeThis
}
MyClass.prototype.getStorage = function (){
return this.storage;
}
MyClass.prototype.setStorage = function (newStorage){
this.storage = newStorage;
}
Use it:
var myInstance = new MyClass("sup");
alert("myInstance storage: " + myInstance.getStorage());
myInstance.setStroage("something else");
As for the 'new' keyword and Crawford's problems with it, I can't really answer, because I haven't read the book, but I can see how you could create a new object by calling any function with the new keyword, including functions that are supposed to be methods of a class.
And when someone says something, such as a design pattern, is more 'expressive', he or she generally means that the design pattern is clear and simple to understand as to what it is achieving and how.
Javascript isn't a person so she can't really suggest what you do.
None of the answers above have mentioned the plain-old functional style of inheritance, which I tend to find is the simplest.
function myModuleMaker(someProperty){
var module = {}; //define your new instance manually
module.property = someProperty; //set your properties
module.methodOne = function(someExternalArgument){
//do stuff to module.property, which you can, since you have closure scope access
return module;
}
}
Now to make a new instance:
var newModule = myModuleMaker(someProperty);
You still get all the benefits of pseudoclassical this way, but you suffer the one drawback that you're making a new copy of all your instance's methods every time you instantiate. This is probably only going to matter when you start having many hundreds (or indeed, thousands) of instances, which is a problem most people seldom run into. You're better off with pseudoclassical if you're creating truly enormous data structures or doing hard-core animations with many, many instances of something.
I think it's hard to argue that either method is "bad practice" per se.

Categories

Resources