Skip to content

Instantly share code, notes, and snippets.

@shchegol
Last active March 16, 2021 14:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shchegol/eb0edc3bef55e341a24e886ecd2da039 to your computer and use it in GitHub Desktop.
Save shchegol/eb0edc3bef55e341a24e886ecd2da039 to your computer and use it in GitHub Desktop.
Design Patterns
Module
Branching - чтобы не вызывать каждый раз проверки каких-то параметров.
Cuггying
Memoization
Namespace
Private - приватные свойства в конструкторе
Self-exiting object - Для защиты глобального пространства имён
// Branching (Ветвление)
// Чтобы не вызывать каждый раз проверки каких-то параметров.
// interface
var utils = {
addListener: null,
removeListener: null
};
// realization
if (typeof window.addEventListener === 'function') {
utils.addListener = function (el, type, fn) {
el.addEventListener(type, fn, false);
};
utils.removeListener = function (el, type, fn) {
el.removeEventListener(type, fn, false);
};
} else if (typeof document.attachEvent === 'function') { // IE
utils.addListener = function (el, type, fn) {
el.attachEvent('on' + type, fn);
};
utils.removeListener = function (el, type, fn) {
el.detachEvent('on' + type, fn);
};
} else { // устаревшие броузеры
utils.addListener = function (el, type, fn) {
el['on' + type] = fn;
};
utils.removeListener = function (el, type, fn) {
el['on' + type] = null;
};
}
var arr = new MYAPP.utilities.Array(obj);
// Currying (Каррирование)
// Если обнаружится, что вы неоднократно вызываете одну и ту же функцию,
// передавая ей практически одни и те же параметры, эта функция
// наверняка является отличным кандидатом на каррирование.
// simple
function doSimpleCarring(x, y) {
if (typeof y === "undefined") {
return function (y) {
return x + y;
}
}
return x + y;
}
doSimpleCarring(1)(2);
// universal
function add(x, y) {
return x + y;
}
function doCarring(fn) {
var slice = Array.prototype.slice,
stored_args = slice.call(arguments, 1);
return function() {
var new_args = slice.call(arguments),
args = stored_args.concat(new_args);
return fn.apply(null, args);
}
}
doCarring(add, 3)(4);
// Memoization (мемоизация, кэширование)
// Сохранение сложных вычислений в замыкании
// simple
var myFunc = function (param) {
if (!myFunc.cache[param]) {
var result = {};
// ... продолжительные операции ...
myFunc.cache[param] = result;
}
return myFunc.cache[param];
};
// создание хранилища результатов
myFunc.cache = {};
// Один из примеров если аргументов много
var myFunc = function () {
var cachekey = JSON.stringify(Array.prototype.slice.call(arguments)),
result;
if (!myFunc.cache[cachekey]) {
result = {};
// ... продолжительные операции ...
myFunc.cache[cachekey] = result;
}
return myFunc.cache[cachekey];
};
// создание хранилища результатов
myFunc.cache = {};
// Обеспечивает все необходимое
// для создания независимых фрагментов программного кода, которые
// можно рассматривать как «черные ящики» и добавлять, заменять или
// удалять их из своей программы в соответствии с потребностями (воз-
// можно, изменяющимися с течением времени) вашей программы.
// Создание пространства имён из паттерна Namespace
MYAPP.namespace('MYAPP.utilities.array');
MYAPP.utilities.array = (function () {
// зависимости
var uobj = MYAPP.utilities.object,
ulang = MYAPP.utilities.lang,
// частные свойства
array_string = '[object Array]',
ops = Object.prototype.toString;
// частные методы
// ...
// конец инструкции var
// реализация необязательной процедуры инициализации
// ...
// общедоступные члены
return {
inArray: function (needle, haystack) {
for (var i = 0, max = haystack.length; i < max; i += 1) {
if (haystack[i] === needle) {
return true;
}
}
},
isArray: function (a) {
return ops.call(a) === array_string;
}
// ... другие методы и свойства
};
}());
#####################################
Шаблон открытия модуля
MYAPP.utilities.array = (function () {
// частные свойства
var array_string = “[object Array]”,
ops = Object.prototype.toString,
// частные методы
inArray = function (haystack, needle) {
for (var i = 0, max = haystack.length; i < max; i += 1) {
if (haystack[i] === needle) {
return i;
}
}
return -1;
},
isArray = function (a) {
return ops.call(a) === array_string;
};
// конец инструкции var
// открытие доступа к некоторым методам
return {
isArray: isArray,
indexOf: inArray
};
}());
#####################################
Модули, создающие конструкторы
MYAPP.namespace(‘MYAPP.utilities.Array’);
MYAPP.utilities.Array = (function () {
// зависимости
var uobj = MYAPP.utilities.object,
ulang = MYAPP.utilities.lang,
// частные свойства и методы...
Constr;
// конец инструкции var
// реализация необязательной процедуры инициализации
// ...
// общедоступные методы -- конструктор
Constr = function (o) {
this.elements = this.toArray(o);
};
// общедоступные методы -- прототип
Constr.prototype = {
constructor: MYAPP.utilities.Array,
version: “2.0”,
toArray: function (obj) {
for (var i = 0, a = [], len = obj.length; i < len; i += 1) {
a[i] = obj[i];
}
return a;
}
};
// вернуть конструктор,
// создающий новое пространство имен
return Constr;
}());
#####################################
Импортирование глобальных переменных в модули
MYAPP.utilities.module = (function (app, global) {
// ссылки на объект global
// и на глобальное пространство имен app
// теперь будут локальными переменными
}(MYAPP, this));
// Универсальная функция
// для создания пространства имен
var MYAPP = MYAPP || {};
MYAPP.namespace = function (ns_string) {
var parts = ns_string.split('.'),
parent = MYAPP,
i;
// отбросить начальный префикс – имя глобального объекта
if (parts[0] === 'MYAPP') {
parts = parts.slice(1);
}
for (i = 0; i < parts.length; i += 1) {
// создать свойство, если оно отсутствует
if (typeof parent[parts[i]] === “undefined”) {
parent[parts[i]] = {};
}
parent = parent[parts[i]];
}
return parent;
};
// Позволяет:
// присваивать возвращаемое значение локальной переменной
var module2 = MYAPP.namespace('MYAPP.modules.module2');
module2 === MYAPP.modules.module2; // true
// опускать начальный префикс 'MYAPP'
MYAPP.namespace('modules.module51');
// создавать глубоко вложенные пространства имен
MYAPP.namespace('once.upon.a.time.there.was.this.long.nested.property');
// Приватные свойства в конструкторе
function Gadget() {
var name = 'iPod';
this.getName = function () { // привилегированный метод
return name;
};
}
var toy = new Gadget();
console.log(toy.name); // undefined
console.log(toy.getName()); // 'iPod'
#####################################
// В литерале
var myobj = (function () {
var name = 'my, oh my';
return {
getName: function () {
return name;
}
};
}());
myobj.getName(); // 'my, oh my'
#####################################
// В прототипе
function Gadget() {
// частный член
var name = 'iPod';
// общедоступная функция
this.getName = function () {
return name;
};
}
Gadget.prototype = (function () {
// частный член
var browser = 'Mobile Webkit';
// общедоступные члены прототипа
return {
getBrowser: function () {
return browser;
}
};
}());
var toy = new Gadget();
console.log(toy.getName()); // “собственный” привилегированный метод
console.log(toy.getBrowser()); // привилегированный метод прототипа
#####################################
// Объявление частных функций
// общедоступными методами
var myarray;
(function () {
var astr = '[object Array]',
toString = Object.prototype.toString;
function isArray(a) {
return toString.call(a) === astr;
}
function indexOf(haystack, needle) {
var i = 0,
max = haystack.length;
for (; i < max; i += 1) {
if (haystack[i] === needle) {
return i;
}
}
return -1;
}
myarray = {
isArray: isArray,
indexOf: indexOf,
inArray: indexOf
};
}());
myarray.isArray([1,2]); // true
myarray.isArray({0: 1}); // false
myarray.indexOf(['a', 'b', 'z'], 'z'); // 2
myarray.inArray(['a', 'b', 'z'], 'z'); // 2
// Если теперь произойдет, например, что-то неожиданное с общедоступ-
// ным методом indexOf(), частный метод indexOf() останется нетронутым,
// благодаря чему метод inArray() сохранит свою работоспособность:
myarray.indexOf = null;
myarray.inArray(['a', 'b', 'z'], 'z'); // 2
// Self-exiting object (Немедленная инициализация объектов)
// Для защиты глобального пространства имён
// simple
({
prop1: 1,
prop2: 2,
sum: function() {
return this.prop1 + this.prop2;
},
init: function() {
console.log(this.sum());
}
}).init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment