Памятка часто используемых JavaScript функций

Дата публикации 23.06.2018

Несколько часто применяемых модулей на JavaScript. Ничего необычного, все широко известно, просто, чтобы были под руками. Описывается работа с Cookie, исключениями, адресной строкой.

1. Работа с Cookie.

Взято с javascript.ru. Оформил в виде класса.

class Cookie {
	
	constructor() {}

	get(name) {
		let matches = document.cookie.match(new RegExp(
		"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
		));
		return matches ? decodeURIComponent(matches[1]) : undefined;
	}

	/**
	* options is contains:
	* 	expires:
	* 		Digit - time of live at minutes.
	* 		Expire Date (past for delete, 0 for session)
	* 	path: default /
	* 	domain: default is current domain
	* 	secure: ssl only
	*/	
	set(name, value, options = {}) {
		let expires = options.expires;

		if (typeof expires == "number" && expires) {
			let d = new Date();
			d.setTime(d.getTime() + expires * 1000);
			expires = options.expires = d;
		}
		if (expires && expires.toUTCString) {
			options.expires = expires.toUTCString();
		}

		value = encodeURIComponent(value);

		let updatedCookie = `${name}=${value}`;

		for (let propName in options) {
			updatedCookie += `; ${propName}`;
			let propValue = options[propName];
			if (propValue !== true) {
				updatedCookie += `=${propValue}`;
			}
		}

		document.cookie = updatedCookie;
	}

	delete(name) {
	  this.set(name, "", {
		expires: -1
	  })
	}
}

2. Исключения

Вот так можно оформить обработку исключений. В результате в консоль выведется красивое человекопонятное описание.

customException - базовый класс. В производных классах задаем только свое имя исключения.

class customException  {
	constructor(name, message, e) {
		this.name = name;
		this.message = message;
		this.stack = e.stack;
		this.toString = () => {`Error: ${this.name}: ${this.message}\n${this.stack}`};
	}
}

class parserException extends customException  {
	constructor(message, e) {
		let name = 'Here is Exception Name';
		super(name, message, e);
	}
}

Использование:

try {
	someFunc();//undefined function
} catch(e) {
	throw new parserException('Exception Description', e);
}

3. Чтение строки запроса

Класс для работы с QueryString. Читает параметры запроса из адресной строки и помещвет их в объект Имя=Значение. Теперь можно читать нужные параметры, менять их значение, удалять. После изменений собирается новая строка запроса. Использовал, когда требовалось сделать фильтр по параметрам для каталога магазина.

	/**
	 * QueryString to Object:
	 * key:value => parametr-name:value
	 *  
	 */
	
	class queryStringObject {
		
		constructor(queryString = location.search.substring(1)) {
			this.queryString = queryString;
			this.queryObject = {};
			this._queryStringToObject(queryString);
		}

		_queryStringToObject(queryString) {
			if(!queryString) return false;		
			queryString = decodeURIComponent(queryString).split('&');	
			
			queryString.forEach(pair => {			
				pair = pair.split('=');
				let value = pair[1] || '';	
				this.queryObject[pair[0]] = value;	
			});			
		}		
		
		getQueryString() {
			let temp = [];
			for (let item in this.queryObject) {
				temp.push(item + '=' + this.queryObject[item]);
			}
			return temp.join("&");
		}
		
		getFieldsFilter() {
			return this.queryObject;
		}
		
		getParam(str) {
			if (typeof this.queryObject[str] != 'undefined') return this.queryObject[str];
			return false;
		}
		
		addParam(str, value) {
			if (!str.trim()) return false;
			this.queryObject[str] = value;
			return true;
		}

		deleteParam(name){
			if (typeof this.queryObject[name] != 'undefined') delete this.queryObject[name];
		}
		
		toString(){
			return  '?' + this.getQueryString();
		}
	}

Пример использования, показано добавление нового параметра и удаление. Методом toString() собирается новая строка запроса. Методом history.pushState обновляется ее отображение в адресной строке браузера.


let queryObject = new queryStringObject();//global query string object

queryObject.addParam(ParametrName, ParametrValue);//Add new parametr to QueryString

queryObject.deleteParam(ParametrName);//Delete


try {
	history.pushState(null, null, queryObject.toString()); //Modify Address Bar
} catch(e) {
	//do something
}

Тот же класс, в котором преобразовывал строку в многоуровневый объект. Чисто академический интерес, на практике достаточно простого первого варианта.

	const PRICE_FILTER = 'price_filter';
	const FIELDS_FILTER = 'fields_filter';
	const ORDER_FILTER = 'order_filter';
	
	let isDef = (name) => typeof name == 'undefined' ? false : true;


	
	/**
	*	
	*
	*		@return queryStringObject = {
	*			param1: value,
	*			param2: value2,
	*			order_filter: {
	*				field_name: 1, //may be 1 or 0
	*			price_filter: {
	*				0: min_price //this subkeys may be 0 and 1
	*				1: max_price,
	*			fields_filter: {
	*				field_name: {
	*					field_id1: field_id1// subkeys 'field_id' may be an integer
	*					field_id2: field_id2
	*				}
	*			}
	*		}
	*		
	*/

	class queryStringObject {
		
		constructor(queryString = location.search.substring(1)) {
			this.queryString = queryString;
			this.queryObject = {};
			this._queryStringToObject(queryString);
		}

		_queryStringToObject(queryString) {
			if(!queryString) return false;		
			queryString = decodeURIComponent(queryString).split('&');	
			
			queryString.forEach(pair => {			
				pair = pair.split('=');
				let value = pair[1] || '';	
				this.addParamFromString	(pair[0], value);			
			});
		}
		
		getQueryString() {
			return this.serializetoQueryString()
		}
		
		getPriceFilter() {
			return this._getFilterType(PRICE_FILTER);
		}
		getFieldsFilter() {
			return this._getFilterType(FIELDS_FILTER);
		}
		getOrderFilter() {
			return this._getFilterType(ORDER_FILTER);
		}	
		
		addParamFromString(str, value) {
			let arr = str.replace(/]/g, '').split('[');	
			this.addParamFromArray(arr, value);
		}

		addParamFromArray(paramsArray, value) {
			let sz = paramsArray.length - 1;			
			let tmp = '';
			
			for (let i = 0; i <= sz; i++) {
				tmp += `['${paramsArray[i]}']`;
				new Function('result, tmp, last, value', 
							` if (typeof result${tmp} == 'undefined') result${tmp} = {}; 
							  if (last) result${tmp} = value;`
							)(this.queryObject, tmp, (i == sz ? true : false), value);
			}	
		}
		
		deleteParamFromSrting(name){
			let paramsArray = name.replace(/]/g, '').split('[');	
			let sz = paramsArray.length - 1;			
			let tmp = '';		
			
			for (let i = 0; i <= sz; i++) {				
				tmp += `['${paramsArray[i]}']`;				
				let def = new Function('result, tmp', 
							` if (typeof result${tmp} == 'undefined') return false;
							  else return true;`
							)(this.queryObject, tmp);
							
				if(!def) {
					return false;
				}				
			}
			new Function('queryObject, tmp', 
							` if (typeof queryObject${tmp} != 'undefined') delete queryObject${tmp}; `
							)(this.queryObject, tmp);
		}
		
		_getFilterType(param_name) {		
			if (isDef(this.queryObject[param_name])) {
				if (param_name == PRICE_FILTER) {
					return this.queryObject[param_name][PRICE_FILTER];
				} else {
					return this.queryObject[param_name];
				}
			}
			
			return false;
		}	
		
		serializetoQueryString() {
			let result = [];// temp array for parts of query_string storage
			
			/**
			* @param obj - object of property
			* @param rootKey - first-level property of queryObject. 
			* It's need because the first part of parameter is not wrapping by '[]'
			* @param tmpArray - for storage history of navigate throght object's hives
			*
			* @return query string of any parameter
			*/
			function iterator(obj, rootKey, tmpArray) {	
				for (let key in obj) {
					if (typeof obj[key] == 'object') {					
						tmpArray.push(key);
						iterator(obj[key], rootKey, tmpArray);					
					} else {
						tmpArray.push(key);
						result.push(`${rootKey}[${tmpArray.join('][')}]=${obj[key]}`);
						tmpArray.pop();
					}				
				}			
				tmpArray.pop();
			}		
			
			for(let key in this.queryObject) {
				if(typeof this.queryObject[key] == 'object'){
					iterator(this.queryObject[key], key, []);
				} else {
					result.push(`${key}=${this.queryObject[key]}`);				
				}			
			}
			
			return result.join('&');
		}
	}