Несколько маленьких полезных приемов в JavaScript
Сегодня мы рассмотрим несколько полезных приемов при программировании на JavaScript. Эти приемы даже сниппетами назвать сложно, ведь некоторые из ни состоят из 2-3 символов, хотя некоторые разработчики (в том числе я сам ;-) часто используют вместо них намного более громоздкие конструкции.
Итак, поехали!
Конвертирование переменных
Как ни странно, но иногда для конвертирования переменных одного типа в другой используют конструкторы объектов типа Array() или Number(). На самом деле правильнее и лучше (с точки зрения производительности) использовать примитивные типы данных:
var myVar = "3.14159",
str = ""+ myVar,// в стринг (string)
int = ~~myVar, // в интеджер (integer)
float = 1*myVar, // во флоат (float)
bool = !!myVar, // в булен - все непустые строки и числа кроме 0 будут true
array = [myVar]; // в массив
Конвертирование в даты (new Date(myVar)) и регулярные выражения (new RegExp(myVar)) нужно делать с использованием конструкторов. Всегда используйте структуру /регулярное_выражение/флаги при создании регулярных выражений.
Конвертирование из десятичной в шестнадцатеричную и восьмеричную системы, и наоборот
Вы пишите отдельные функции для этого? На самом деле все преобразование можно сделать стандартными методами:
(int).toString(16); // конвертирует десятичную (int) в шестнадцатеричную (hex): например, 12 => "C"
(int).toString(8); // конвертирует десятичную (int) в восьмеричную (octal): например, 12 => "14"
parseInt(string, 16) // конвертирует шестнадцатеричную (hex) в десятичную (int): например, "FF" => 255
parseInt(string, 8) // конвертирует восьмеричную (octal) в десятичную (int): например, "20" => 16
Замена всех вхождений подстроки в строку
Часто случается, что нужно заменить все вхождения какой-то строки в другую строку. Вместо громоздких конструкций лучше всего делать так:
var str = "foobarfoobar";
str.replace(/foo/g,"xxx");
// в итоге получиться str = "xxxbarxxxbar";
Еще несколько преобразований для числовых данных
В добавлении к предыдущим методам:
0xFF; // Объявление шестнадцатеричного, возвращает returns 255
020; // Объявление восьмеричного, возвращает 16
1e3; // Эскпоненциальный, тоже что 1 * Math.pow(10,3), возвращает 1000
(1000).toExponential(); // Противоположное предыдущему, возвращает 1e3
(3.1415).toFixed(3); // Округление значения, возвращает "3.142"
Определение версии JavaScript
Вы знаете какую версию JavaScript поддерживает ваш браузер? Если нет, то можно посмотреть в Википедии.
Вот небольшой скрипт для определения версии JavaScript:
var JS_ver = [];
(Number.prototype.toFixed)?JS_ver.push("1.5"):false;
([].indexOf && [].forEach)?JS_ver.push("1.6"):false;
((function(){try {[a,b] = [0,1];return true;}catch(ex) {return false;}})())?JS_ver.push("1.7"):false;
([].reduce && [].reduceRight && JSON)?JS_ver.push("1.8"):false;
("".trimLeft)?JS_ver.push("1.8.1"):false;
JS_ver.supports = function() {
if (arguments[0])
return (!!~this.join().indexOf(arguments[0] +",") +",");
else
return (this[this.length-1]);
}
alert("Последняя поддерживаемая версия JavaScript: "+ JS_ver.supports());
alert("Поддержка версии 1.7 : "+ JS_ver.supports("1.7"));
Использование window.name для простейшей сессии
Записывая строковые переменные в переменную window.name, вы можете сохранять это значение в текущем окне до тех пор, пока оно не закрыто. Это очень полезно, например, для переключения между режимами отладки и тестирования.
Определение наличия переменной
Эта проблема может появиться либо при определении, есть ли переменная в принципе, либо при определении ее типа. Рассмотрим код:
// ПЛОХО: Это вызовет ошибку в коде, если переменная foo неопределена
if (foo) {
doSomething();
}
// ХОРОШО: Это не вызовет ошибок, однако когда
// foo будет NULL или false, условие будет как true
if (typeof foo != "undefined") {
doSomething();
}
// ЛУЧШЕ: Опять же, никаких ошибок, и когда переменная
// будет NULL или false условие будет как false
if (window.foo) {
doSomething();
}
Однако, могут возникнуть ситуации, когда у нас есть более сложная структура и правильная проверка в этом случае должна выглядеть как-то так:
// УЖАСНО: нам нужно доказать наличие каждого объектаwe
// прежде чем мы будем уверены, что значение существует
if (window.oFoo && oFoo.oBar && oFoo.oBar.baz) {
doSomething();
}
Передача аргументов функции
Когда у какой-то функции есть как обязательные, так и необязательные аргументы, то ее вызов может выглядеть как-то так:
function doSomething(arg0, arg1, arg2, arg3, arg4) {
...
}
doSomething('', 'foo', 5, [], false);
Хотя на самом деле всегда проще передавать только один объект вместо нескольких обычных аргументов:
function doSomething() {
// Оставляем аргументы, если ничего не передано
if (!arguments[0]) {
return false;
}
var oArgs = arguments[0]
arg0 = oArgs.arg0 || "",
arg1 = oArgs.arg1 || "",
arg2 = oArgs.arg2 || 0,
arg3 = oArgs.arg3 || [],
arg4 = oArgs.arg4 || false;
}
doSomething({
arg1 : "foo",
arg2 : 5,
arg4 : false
});
Использование document.createDocumentFragment()
Часто возникает необходимость вставить несколько объектов в страницу. Однако, прямая их вставка в документ вызовет полную перерисовку всего документа, что плохо с точки зрения производительности. Вместо этого лучше использовать document.createDocumentFragment(), вызывая его только один раз в самом конце:
function createList() {
var aLI = ["first item", "second item", "third item",
"fourth item", "fith item"];
// Создаем фрагмент
var oFrag = document.createDocumentFragment();
while (aLI.length) {
var oLI = document.createElement("li");
// Берем первый элемент массива и добавляем
// как текстовый узел в элемент LI
oLI.appendChild(document.createTextNode(aLI.shift()));
oFrag.appendChild(oLI);
}
document.getElementById('myUL').appendChild(oFrag);
}
Передача функции в метод replace()
Бывают ситуации, когда нужно заменить специфичную часть строки на специфичные значения. Самый лучший способ сделать это — передать отдельную функцию для метода replace():
var sFlop = "Flop: [Ah] [Ks] [7c]";
var aValues = {"A":"Ace","K":"King",7:"Seven"};
var aSuits = {"h":"Hearts","s":"Spades",
"d":"Diamonds","c":"Clubs"};
sFlop = sFlop.replace(/[w+]/gi, function(match) {
match = match.replace(match[2], aSuits[match[2]]);
match = match.replace(match[1], aValues[match[1]] +" of ");
return match;
});
// строковая переменная sFlop теперь содержит:
// "Flop: [Ace of Hearts] [King of Spades] [Seven of Clubs]"
Метки внутри циклов
Иногда вы делает циклы внутри циклов, и вдруг возникает необходимость завершить цикл. Это можно сделать с помощью меток:
outerloop:
for (var iI=0;iI<5;iI++) {
if (somethingIsTrue()) {
// Останавливаем внешний цикл
break outerloop;
}
innerloop:
for (var iA=0;iA<5;iA++) {
if (somethingElseIsTrue()) {
// Останавливаем внутренний цикл
break innerloop;
}
}
}
Нашли для себя что-то полезное? Отлично! Есть, что добавить — пишите в комментариях.
Рекомендуем почитать