Code Monkey home page Code Monkey logo

augment's Introduction

augment

The world's smallest and fastest classical JavaScript inheritance pattern (augment) is a seven line function which allows you to write CoffeeScript style classes with a flair of simplicity; and it still beats the bejesus out of other JavaScript inheritance libraries.

Inspired by giants like Jeremy Ashkenas and John Resig, augment is an augmentation of ideas. Classes created using augment have a CoffeeScript like structure, and a syntax like John Resig's; but they are more readable, intuitive and orders of magnitude faster. Plus they work on every JavaScript platform.

Installation and Usage

You can install augment on node.js using the following npm command:

npm install augment

You can also install augment on RingoJS using the following rp command:

rp install augment

Similarly you can install augment for web apps using the following component command:

component install javascript/augment

You may use augment with the Asynchronous Module Definition (AMD) API as follows:

define(["augment"], function (augment) {
    // Note that you may also use `require` instead of `define`.
});

You can easily include it in fiddles and benchmarks using the following HTML code:

<script src="https://raw.github.com/javascript/augment/master/lib/augment.js"></script>

Otherwise you may simply browse the source code and stick it into your program.

Creating your First Class

I am a huge follower of keeping things simple and learning by example. So let's begin:

var augment = require("augment");

var Rectangle = augment(Object, function () {
    this.constructor = function (width, height) {
        this.height = height;
        this.width = width;
    };

    this.area = function () {
        return this.width * this.height;
    };
});

The augment function augments objects. However if you pass it a function as the first parameter instead then it augments the prototype of the function. It's equivalent to:

var augment = require("augment");

var Rectangle = augment(Object.prototype, function () {
    this.constructor = function (width, height) {
        this.height = height;
        this.width = width;
    };

    this.area = function () {
        return this.width * this.height;
    };
});

The augment function is also available as a method on Object.prototype and Function.prototype allowing you to alternatively write the above code as follows:

var augment = require("augment");

var Rectangle = Object.augment(function () {
    this.constructor = function (width, height) {
        this.height = height;
        this.width = width;
    };

    this.area = function () {
        return this.width * this.height;
    };
});

Looks like normal JavaScript right? No mysterious dollar signs or dangling underscores. It's so simple that I don't even need to explain it using comments.

Now let's create our first object:

var rectangle = new Rectangle(3, 7);
console.log(rectangle.area());

That's it.

Creating your Second Class

Now let's create another class which augments our first class. It's as simple as:

var Square = Rectangle.augment(function () {
    this.constructor = function (side) {
        Rectangle.call(this, side, side);
    };
});

Now let's create an object:

var square = new Square(5);
console.log(square.area());

So simple.

Creating your Third Class

What about accessing base class prototype methods from the derived class? Let's see:

var Cube = Square.augment(function (base) {
    this.constructor = function (side) {
        base.constructor.call(this, side);
        this.side = side;
    };

    this.area = function () {
        return 6 * base.area.call(this);
    };

    this.volume = function () {
        return this.side * base.area.call(this);
    };
});

As you can see the second argument passed to the anonymous class body function is the prototype of the base class Square, which we named base. It can be used to access the methods on the prototype of the base class.

Also notice that instead of invoking the super class constructor as Square.call we are using base.constructor.call instead. Yes there's an additional property lookup but it's essentially the same.

Creating the final object:

var cube = new Cube(5);
console.log(cube.volume());
console.log(cube.area());

Redefining the Module Pattern

The module pattern in JavaScript is used to provide privacy and state via an anonymous closure. It may also optionally return an object. You may use augment as achieve the same result. As long as you don't define this.constructor, augment will return a module instead of a class:

var MODULE = Object.augment(function () {
    var private = true;
    this.public = true;
});

You may also import values as follows:

var MODULE = Object.augment(function ($, YAHOO) {
    // now have access to globals jQuery (as $) and YAHOO in this code
}, jQuery, YAHOO);

By default the prototype of the function you are augmenting (in this case Object) is always imported. It's passed at the end of the argument list.

Functional Programming Utilities

The augment framework was designed keeping code reuse in mind. Hence all the utility functions used to write the actual framework are made available to the user as well. These utilities aid in functional programming in JavaScript. They are documented below:

Function.bindable

The bindable function allows you to create a bindable version of an existing function which when called returns a new function bound to the given arguments. For example:

Function.prototype.defer = function () {
    setTimeout.bind(null, this, 0).apply(null, arguments);
};

var deferrable = Function.bindable(Function.prototype.defer);

var deferredAlert = deferrable(alert);

deferredAlert("This will be displayed later.");
alert("This will be displayed first.");

The bindable function is equivalent to bind.bind (i.e. it takes a function foo and returns another function equivalent to foo.bind, or to put it simply bindable(foo) === foo.bind). Hence bindable(bind) is equivalent to bind.bind or bindable itself. In fact bindable is itself is implemented as bind.bind(bind). Confusing? I think not.

As a thumb rule the name of the bindable version of a function should be an adjective with the suffix "able". For example a bindable bind would be bindable itself (which is what it actually is). A bindable call would be callable. A bindable apply would be appliable. You get my drift. Concise and descriptive names are very helpful.

Function.callable

The callable function allows you to create a callable version of an existing function which when called calls the existing function with the given arguments and this pointer. For example:

var defer = Function.callable(Function.prototype.defer);
defer(alert, "This will be displayed later.");
alert("This will be displayed first.");

To make things more clear assume that you pass a function foo to callable as follows - Function.callable(foo). This is equivalent to foo.call (without actually calling call). Hence Function.callable(foo)(that, arg1, ...) is equivalent to foo.call(that, arg1, ...).

Array.from

The Array.from function allows you to slice an array from a start index to an end index. You can use it to create a one-level deep copy of an array or to convert an array-like object into an array. For example:

var primes = [2, 3, 5, 7];
var oddPrimes = tail(primes); // [3, 5, 7]

function tail(list) {
    return arrayFrom(list, 1);
}

Object.ownPropertyOf

The ownPropertyOf function is used to check if an object has own property. It's particularly useful if the object you're testing doesn't have the Object constructor in its prototype chain. For example:

var object = Object.create(null);
Object.ownPropertyOf(object, "property"); // false

That's all folks!

augment's People

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.