Статьи

Шаблоны разработки приложений Javascript, на примере

В разработке Javascript преобладают библиотеки, такие как Backbone, Spine и, конечно, jQuery (удивительно!). Однако вопрос не в том, какую библиотеку использовать, а в том, как ее использовать.

Понимание того, как некоторые фреймворки предоставляют леса и архитектуру для кажущегося недетерминированного шара javascript, может быть ключевым компонентом в нашем арсенале трюков javascript. Наличие этих знаний, по сути, открывает последнюю дверь для создания действительно великолепных и захватывающих веб-приложений, позволяя разработчику логически разделять проблемы и зависимости.

В этой статье мы пройдемся по некоторым базовым шаблонам JavaScript:

  • Модули IIFE
  • Модули Dojo
  • Модули jQuery
  • AMD Модули
  • CommonJS Модули
  • Фасадные Узоры
  • Медиаторные модули

Шаблоны модулей — функции немедленного вызова выражений (IIEF) используют контекст выполнения для создания конфиденциальности.

var module = (function(){
    /**
     * private variables are declared only inside the module
     */
    var basket = [];

    /**
     * public variables are declared in the returned object
     */
    return {
        add: function(value){ ... },
        count: function() { ... }
    };
}());

module.add('a');
module.add('b');
module.add('c');

var total = module.count();

Модуль Pattern — Dojo

 /**
 * traditional method
 */
var store = window.store || {};
store.basket = store.basket || {};

/**
 * dojo method
 */
dojo.setObject("store.basket.object", function(){
    var basket = [];
    function privateFunc(){ ... }
    return {
        add: function(value){ ... },
        count: function(){ ... }
    }
});

Шаблон модуля — jQuery

 function library(module) {
    $(function(){
        if (module.init) {
            module.init();
        }
    });
    return module;
}

var myLibrary = library(
    function(){
        return {
            init: function() {
                /*implementation*/
            }
        };
    }()
);

Лучше — определение асинхронного модуля или AMD

 /**
 * AMD: define()
 * define a signature with define(id /*optional*/, [dependencies], /*factory module instantiation of fn*/);
 */

define(
    /*module id*/
    'myModule',

    /*dependencies*/
    ['foo', 'bar;, 'baz'],

    /*definition for the module export*/
    function(foo, bar, baz){

        /*module object*/
        var module = {};

        /*module methods go here*/
        module.hello = foo.getSomething();
        module.goodbye = bar.getSomething();

        /*return the defined module object*/
        return module;
    }
);

/**
 * AMD: require()
 * load top-level code for JS files or inside modules for dynamically fetching dependencies
 */

/* top-level: the module exports (one, two) are passed as function arguments ot the object */
require(['one', 'two'], function(one, two){
    ...
});

/*inside: the complete example*/
define('three', ['one', 'two'], function(one, two){
    /**
     * require('string') can be used inside the function to get the module export
     * of a module that has already been fetched and evaluated
     */

    var temp = require('one');

    /*this will fail*/
    var four = require('four');

    /* return a value to define the module export */
    return function(){ ... };
});

Лучшее: CommonJS — широко распространенный формат на стороне сервера

 /**
 * basically contains two parts: an exports object that contains the objects a module wishes to expose
 * and a require function that modules can use to import the exports of other modules
 */

/* here we achieve compatibility with AMD and CommonJS using some boilerplate around the CommonJS module format*/
(function(define){
    define(function(require,exports){
         /*module contents*/
         var dep1 = require("foo");
         var dep2 = require("bar");
         exports.hello = function(){...};
         exports.world = function(){...};
    });
})( typeof define=="function" ? define : function(factory){ factory(require, exports) });

** Harmonious revelations: ES Harmony, the the successor to ECMAScript 5

/**
 * 1. static scoping
 * 2. simple
 * 3. reusable modules
 */

// Basic module
module SafeWidget {
    import alert from Widget;
    var _private ="someValue";

    // exports
    export var document = {
        write: function(txt) {
            alert('Out of luck, buck');
        },
        ...
    };
}

// Remote module
module JSONTest from 'http://json.org/modules/json2.js';

Альтернативные шаблоны для модулей

Модули регулярно используются в приложениях MVC, но есть и другие шаблоны, которые также могут упростить создание больших приложений. Помните, что в больших приложениях jQuery обычно играет меньшую роль, чем многие думают. Календарь 2nd.MD, код бронирования и портал чата могут легко работать без jQuery.

Фасад — высокоуровневые интерфейсы для больших массивов кода, которые скрывают БОЛЬШУЮ непростую сложность

«Когда вы возводите фасад, вы обычно создаете внешний вид, который скрывает другую реальность. Думайте об этом как об упрощении API, представленного другим разработчикам »

Основные шаблоны дизайна Javascript

  1. Упрощает использование через ограниченный, более простой API
  2. Скрывает внутреннюю работу библиотеки, делает реализацию менее важной
  3. Позволяет вам быть более креативным за кулисами
  4. Имеет много функциональных поведений для безопасности приложений
 var module = (function() {
    var _private = {
        i:5,
        get : function() {
            console.log('current value:' + this.i);
        },
        set : function( val ) {
            this.i = val;
        },
        run : function() {
            console.log('running');
        },
        jump: function(){
            console.log('jumping');
        }
    };

    /**
     * this part includes code imported above and provides an API to the returning module
     */
    return {
        facade : function( args ) {
            _private.set(args.val);
            _private.get();
            if ( args.run ) {
                _private.run();
            }
        }
    };
}());

module.facade({run: true, val:10}); //outputs current value: 10, running

Посредник — способствует слабой связи, устанавливая интерфейсы для событий, на которые модули могут подписаться:

  1. Позволяет модулям транслировать или прослушивать уведомления, не беспокоясь о системе или утомительных цепях обратного вызова.
  2. Уведомления могут обрабатываться асинхронно любым количеством модулей одновременно.
  3. Гораздо проще добавлять или удалять функции в любое время из-за слабосвязанной природы кода.
 var mediator = (function(){
    var subscribe = function(channel, fn){
        if (!mediator.channels)mediator.channels = [];
        mediator.channels.push({ context: this, callback:fn });
        return this;
    },
    publish = function(channel){
        if (!mediator.channels) return false;
        var args = Array.prototype.slice.call(arguments, 1);
        for (var i = 0, l = mediator.channels.length; i<l; i++) {
            var subscription = mediator.channels[i];
            subscription.callback.apply(subscription.context,args);
        }
        return this;
    };
    return {
        channels: {},
        publish: publish,
        subscribe: subscribe,
        installTo: function(obj){
            obj.subscribe = subscribe;
            obj.publish = publish;
        }
    };
}());

Это все! Помните, что то, как вы организуете свой код и разрабатываете свое приложение, может действительно упростить сложные программы до почти естественного инстинкта. Отточите свои навыки в этих подходах, и вы овладеете техникой, необходимой, чтобы действительно развиваться как разработчик!