22 декабря 2015
22 февраля 2010
13
Несколько маленьких полезных приемов в JavaScript
Всем привет!
Сегодня мы рассмотрим несколько полезных приемов при программировании на JavaScript. Эти приемы даже сниппетами назвать сложно, ведь некоторые из ни состоят из
Итак, поехали!
Конвертирование переменных
Как ни странно, но иногда для конвертирования переменных одного типа в другой используют конструкторы объектов типа 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;
}
}
}
Нашли для себя что-то полезное? Отлично! Есть, что добавить — пишите в комментариях.
Перевод статьи «10 Small Things You May Not Know About Javascript» специально для Временно.нет.
Пиздатенько, спасибо
Метки - совсем плохо
Буду наверняка сюда иногда заходить!
А к double можно преобразовать при помощи 0.0+value
if (undefined_var) { ... } лично у меня никогда ошибок не вызывало. Насколько я помню, в таком простом случае оператор if проверяет в т.ч. и на существование переменной.
myVar = myVar || {};
Ну или:
myVar = myVar || ;
myVar = myVar || значение-по-умолчанию;
Это просто инициализатор массива, никакого приведения типов здесь нет, только создается новый массив с одним элементом:
С числами всё таки лучше работать по человечески:
string к number можно приводить следующим образом:
Кстати, еще можно быстро получить timestapm:
Все числа хранятся в формате float64, т.е. 8 байт с плавающей точкой.
Базовые типы: Строки, Числа, Boolean
Для определения наличия свойств объектов (в том числе и window), можно воспользоваться оператором in.
Разве перерисовка будет вызвана не после завершения выполнения потока?