Как вы пишите свои библиотеки?
Наверное каждый когда-либо писал свою библиотеку всяких нужных и не очень функций. Я изучаю js, поэтому тоже вот потихоньку пишу всякие плюшки и чета их стало много. Решил оформить все в виде библиотеки, чтобы не захламлять глобальное пространство. Выглядит это так:
var GLIB = (function(){ var $G = {}; $G.scroll = function(){ /*****/ }; $G.serialize = function(){ /*****/ }; // и т.д. и т.п... return $G; }()); Однако теперь столкнулся с проблемой захламления пространства самой библиотеки. Ну к примеру написал я некий модуль, который делает ajax запросы. У него есть настройки по дефолту, функция установки настроек, непосредственно функция отправки запросов и т.д... То есть модуль состоит из нескольких функций: var GLIB = (function(){ var $G = {}; /*** Ajax ***/ $G.ajax = function(){/* делает запросы и выполняет заданные функции */}; $G.ajaxSetup = function(){/* установка глобальных опций */}; $G.ajaxSetting = {/* дефолтные настройки */}; /*** Other ***/ $G.scroll = function(){/*****/}; $G.serialize = function(){/*****/}; // и т.д. и т.п... return $G; }()); Проблема в том, что в составе модуля не все функции должны быть расшарены наружу. Например объект $G.setting не должен быть доступен для прямой записи в него. Значит что? значит нужно // вместо $G.ajaxSetting = {}; //сделать var ajaxSetting = {}; Все, наружу эта переменная не доступна, но она теперь захламляет пространство внутри библиотеки... Короче я уже не знаю, как лучше оформить свою библиотеку, чтобы и имена переменных были короткие, и чтобы потом не было конфликтов внутри. |
PS да и к тому же навеное в своей библиотеке нужно отделить функции-одиночки от модулей, которые могут использовать эти самые функции-одиночки, чтобы потом можно было безболезненно выкидывать лишние модули
|
Ну, например, можно продолжать развивать в том же духе:) :
var GLIB = (function(){ var $G = {}; /*** Ajax ***/ $G.ajax = (function(){ var ajaxSetting = {/* дефолтные настройки */}; var ajax = function(){/* делает запросы и выполняет заданные функции */}; ajax.setup = function(){/* установка глобальных опций */}; return ajax }()); /*** Other ***/ $G.scroll = function(){/*****/}; $G.serialize = function(){/*****/}; // и т.д. и т.п... return $G; }()); |
Hapson, если есть модули и зависимости между ними, стоит прочитать, например, эту статью.
|
Sweet,
Сейчас почитаю. Немного не так, зависимостей между модулями нет. Есть ряд функций, входящих в состав библиотеки, которые абсолютно независимы. То есть примитивные функции - поиск значения или ключа в массиве/объекте, применение функции ко всем значениям массива, trim и подобные. А есть модули, которые мало того что состоят из нескольких функций, так они еще используют примитивные функции библиотеки. То есть библиотека делится на две части: обязательные функции и модули. Обязательные выкидывать нельзя, модули можно |
Aetae,
Ну да, что-то я об этом не подумал. Библиотека в библиотеке. Типа так: var GLIB = (function(){ var $G = {}; /*** Ajax ***/ $G.ajax = (function(){ var __setup = function(set){ set = typeof set == "object" ? set : {}; this.type = set.type || "GET"; this.url = set.url || window.location.href; this.param = set.param || null; this.async = typeof set.async == "undefined" ? true : set.async === false ? false : true; this.contentType = set.contentType || "application/x-www-form-urlencoded"; this.timeout = set.timeout || 3000; this.error = set.error || function(){}; this.success = set.success || function(){}; this.beforeSend = set.beforeSend || function(){}; this.afterSend = set.afterSend || function(){}; }; var setting = new __setup(); var ajax = function(set){ var xhr = $G.getXhr(); if(typeof set !== "object"){return xhr;} }; ajax.setup = function(set){ setting = new __setup(set); }; ajax.getSetting = function(){return setting;}; return ajax; }()); /*** Other ***/ $G.scroll = function(){/*****/}; $G.serialize = function(){/*****/}; // и т.д. и т.п... return $G; }()); Только вот непонятно. Вот в примере есть внутренние переменные: __setup и setting. Если они используются в других функциях, то они получается остаются жить после завершения работы функции обертки? |
Ну да. В этом вся суть замыкания. Я думал раз уж вы его используете для своей библиотеки, то понимаете что это такое...
|
Если твоя библиотека делится на модули, и они зависимы друг от друга, то ты можешь использовать паттерн "иньекция зависимости", вот держи братишка, я тебе иньектор принес:
var module = new function () { var modules = {}; function inject(factory) { var require = factory.toString() .match(/\(([\s\S]*?)\)/)[1] .match(/[\$\w]+/img) || []; return factory.apply(null, require.map(module)); } function module(name, factory) { if (!factory) { var module = modules[name]; return module.instance || (module.instance = inject(module.factory)); } modules[name] = { factory : factory, instance: null }; } return module; }; работает функция module так // описываем модуль module('http', function () { return { ololo: function () { alert('ololo!') } } }); // обращаемся к модулю var http = module('http'); http.ololo() // ololo! вторым аргументом передается функция "фабрика", тот обьект который она вертет он и будет модулем, и он будет возвращаться при module('http'). Все модули создаются только один раз, так что module('http') === module('http'). Если какой-то модуль зависит от другого модуля то мы можем в коде одного модуля обратиться к другому: module('http', function () { return { } }); module('ajax', function () { // обратились из одного модуля к другому var http = module('http'); return { } }); но лучше просто написать ИМЯ необходимого модуля в параметрах к функции фабрике) тогда туда ПО ИМЕНИ необходимй модуль и передастся. module('http', function () { return { } }); module('ajax', function (http) { http //модуль автоматически подключился по имени аргумента return { } }); Ну или если тебе не нужны всякие модули, иньекции, то используй просто такой шаблон: var myLibrary = new function () { function trim() { } function find() { } // функция которая не будет доступна извне, она является внутренней для библиотеки function select() { } // функции которые хотим сделать доступными пользователю return { trim: trim, find: find } }; |
Aetae,
Читал я про замыкания... много раз читал. Ну вроде как начал понимать, как это работает. Maxmaxmaximus12, Спасибо :) Интересный подход. |
Hapson, или к примеру, одна функция использует несколько служебных, тогда описывай так
var myLibrary = new function () { // утилитарная функция, которая может быть доступна всем функциям фреймворка // тут вверху помещай более общие функции, выполняющие рутиную работу. // начинается с одного подчеркивания, как символ того что она вспомогательная. function _getElement() { } // публичная функция this.trim = new function () { // служебная функция которая видна только функции trim function find() { } return function () { // код функции trim } }; // публичная функция this.ajax = new function () { // служебная переменная, которая видна только функции ajax var ajaxPort = 80; // служебная функция которая видна только функции ajax function ajaxSettings() { } return function () { // код функции ajax } }; }; а вообще лучше разбивать код на модули и пихать их в разные файлы, а потом делать сборку проекта в один файл с помощью прогарммы gulp |
Часовой пояс GMT +3, время: 01:47. |