API.js | |
---|---|
This | |
this.js is a tiny library for writing OO JavaScript. A JavaScript library that tries its best not to be a library. Rules are being broken but this just does not care. This adds functionality to globals already in JavaScript (Often frowned upon). But I'm all about not choosing a big library until the project needs it. this.js is all about deferring decisions and writing just what you need, for some hard core true agile TDD. We're not saying never use Backbone, Ember or Sencha. We are just suggesting deferring the decision until it actually has to be made. We have tried to not repeat other libraries. I have not made any utilities as you can use great libraries like Underscore. What we are preaching is nothing new. I suggest that you go check out Clean Coders by Uncle Bob. | |
Writing Classes | var Class = function () {}; |
With this, you can write your classes however you like. I prefer writing them in a closure like TypeScript. | var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
}()); |
Inheritance | |
The main ability of this is inheritance. Every Function Object can be extended with this. Simply use the Extend function after you have created the constructor to extend the 'Super' class and all the classes it also inherits. | |
extend
| Function.prototype.extend(superClass: Function); |
Example:Our base class we want to extend. | var Person = (function () {
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.speak = function (words) {
console.log(words);
};
return Person;
}()); |
As our SuperHeroes are based on people we will extend the Person class. | var SuperHero = (function () {
function SuperHero(name, age, power) {
this.power = power; |
We can call the constructor of our super class with the call method. | Person.call(this, name, age);
} |
Extends the Person class. | SuperHero.extend(Person); |
Adds any public function SuperHero needs. | SuperHero.prototype.useSuperPower = function () {
console.log("Using " + this.power);
};
return SuperHero;
}()); |
You must extend after you have defined the constructor. Here we add the Person or super class to the Prototype Object, which means you have to add all your public methods after extending. | |
Scope | |
Losing scope can always be a problem in JavaScript. Especially if you are working with events and callbacks. Working with callbacks you often use a closure to get around loss of scope. | |
Closure example: | |
Account class. | var Account = (function () {
function Account() {}
Account.prototype.getUser = function (userId, onComplete) {
/* Get the user somehow */
if (onComplete) {
onComplete(/* Some data */);
}
};
Account.prototype.deleteUser = function () {};
return Account;
}()); |
Accounts main view. | var AccountView = (function () {
function AccountView() {
this._account = new Account();
}
AccountView.prototype.displayUser = function (userId) {
var _this = this;
this._account.getUser(userId, function (userData) {
/* Some jQuery here */
_this.deleteUser();
});
};
return AccountView;
}()); |
This is very common is JavaScript. It is not really wrong, however functions should perform one task. this gives us a binding function, so we can keep our classes separated out. | |
bind
| Function.prototype.bind(scope: Object, ...); |
Example:Looking at the AccountView from the earlier example. | var AccountView = (function () {
function AccountView() {
this._account = new Account();
}
AccountView.prototype.displayUser = function (userId) {
this._account.getUser(userId, this.renderUserDataToDom.bind(this));
};
AccountView.prototype.renderUserDataToDom = function (userId) {
/* Some jQuery here */ |
We can use the this keyword here knowing we have the scope that we intended. | this.deleteUser();
};
return AccountView;
}()); |
bind() is a cross browser implementation of the function that already appears in modern browsers like Chrome. If the function already exists we do not override it. | |
Performance | |
Built to help with high process functions. | |
memorize
| Function.prototype.memorize(); |
Example: | function fibonacci (num) {
if (num < 2) {
return 1;
}
return fibonacci(num - 1) + fibonacci(num - 2);
} |
The Fibonacci sequence is very expensive. It takes a lot of processing power to run. Memoization can drastically help improve performance. | var memFibRun = fibonacci.memoize(), |
resultThree will not run again. It will get the result from cache. | resultOne = memFibRun(50),
resultTwo = memFibRun(25),
resultThree = memFibRun(50); |
Events | |
this creates a global EventDispatcher class for native style events. | |
EventDispatcher | var eventDispatcher = new EventDispatcher(); |
Normally you will not create new instances of EventDispatcher. The classes main purpose is to be extended to give you modules event based functionality. | var Work = (function () {
function Work() {} |
Adds event functionality to the Work class. | Work.extend(EventDispatcher); |
Adds any public function SuperHero needs. | Work.prototype.addEmployee = function (employee) {
/* Add an employee */
this.dispatchEvent({type: 'added', employee: employee});
};
return Work;
}()); |
| |
addEventListenerRegisters an event listener object with an EventDispatcher object so that the listener receives notification of an event. If you no longer need an event listener, remove it by calling removeEventListener(), or memory problems could result.
| EventDispatcher.prototype.addEventListener(eventType: String, listener: Function, listenerScope: Object): Boolean |
Example: | eventDispatcher.addEventListener('complete', function () {}, this); |
| |
dispatchEventDispatches an event into the event flow. The event target is the EventDispatcher object upon which the dispatchEvent() method is called.
| EventDispatcher.prototype.dispatchEvent(event: Object): Boolean |
Example: | eventDispatcher.dispatchEvent({
type: 'added',
data: [1, 2, 3]
}); |
| |
hasEventListenerChecks whether the EventDispatcher object has any listeners registered for a specific type of event.
| EventDispatcher.prototype.hasEventListener(eventType: String): Boolean |
Example: | if (!eventDispatcher.hasEventListener('added')) {
eventDispatcher.addEventListener('added', function () {}, this);
} |
| |
removeEventListenerRemoves a listener from the EventDispatcher object. If there is no matching listener registered with the EventDispatcher object, a call to this method has no effect.
| EventDispatcher.prototype.removeEventListener(eventType: String, listener: Function) |
Example: | function addedHandler(event) {
/* Some code */
}
eventDispatcher.removeEventListener('added', addedHandler); |
IMPORTANT - Event listeners can easily create memory leaks if you do not clean up your code. Be sure to use removeEventListener once your event is no longer needed. | |
Event ObjectsThis can be as simple as a basic object, extend the native JavaScript event or create your own class. It does not mater which you use. The only property your object requires is 'type'. | |
Example: | var basicEvent = {
type: 'added'
};
var nativeEvent = new Event('added');
var myApp.events.Event = function (type) {
this.type = type;
}; |
License | |
Copyright (c) 2013 Ricky Clegg Licensed under the MIT license. | |