Как вы пишите свои библиотеки?
Наверное каждый когда-либо писал свою библиотеку всяких нужных и не очень функций. Я изучаю 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, время: 07:51. |