Несколько маленьких полезных приемов в JavaScript

Несколько маленьких полезных приемов в 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;
}

}
}

 

Нашли для себя что-то полезное? Отлично! Есть, что добавить — пишите в комментариях.

Перевод статьи «10 Small Things You May Not Know About Javascript» специально для Временно.нет.

Расскажите друзьям

Оцените статью:
  • 1
  • 2
  • 3
  • 4
  • 5

Комментарии — 13

Порфирий
Пиздатенько, спасибо
#
Порфирий
Андрей Петруша
И правда спасибо, иногда ищешь какую-то маленькую фигню (вроде "int = ~~myVar") - хрен найдёшь.
gm1
для int есть parseInt.
Метки - совсем плохо
#
gm1
demy
Спасибо за то, что собрали все эти приемы в одном месте!
Буду наверняка сюда иногда заходить!
#
demy  
remal
1*value - это, разве, преобразование не к int?
А к double можно преобразовать при помощи 0.0+value

if (undefined_var) { ... } лично у меня никогда ошибок не вызывало. Насколько я помню, в таком простом случае оператор if проверяет в т.ч. и на существование переменной.
#
remal
Alexey
Для несуществующих переменных можно делать так:
myVar = myVar || {};

Ну или:
myVar = myVar || ;
#
Alexey  
Alexey
Эх, в последней строке вырезалась концовка:
myVar = myVar || значение-по-умолчанию;
#
Alexey  
a13ks3y
Спасибо, действительно полезно.
#
a13ks3y
Octane
Тут обычная конкатенация строк, так как myVar — строка:
	str     = ""+ myVar,//  в стринг     (string)


Это просто инициализатор массива, никакого приведения типов здесь нет, только создается новый массив с одним элементом:
	array   = [myVar];  //  в массив


С числами всё таки лучше работать по человечески:
var myVar = 3.14159,
    str = myVar.toString(), // приведение к типу string
    int = Math.round(myVar); // или Math.floor(…), округление до целых


string к number можно приводить следующим образом:
var myVar = "3.14159",
    num = +myVar; // или parseInt/parseFloat, приведение к типу number


Кстати, еще можно быстро получить timestapm:
var now = +new Date;


Все числа хранятся в формате float64, т.е. 8 байт с плавающей точкой.
Базовые типы: Строки, Числа, Boolean

Для определения наличия свойств объектов (в том числе и window), можно воспользоваться оператором in.

#
Octane
Kykyryzo
всё таки javascript очень неоднозначный язык. не знаю даже нравится мне он или нет))
vasa_c
document.createDocumentFragment()
Разве перерисовка будет вызвана не после завершения выполнения потока?
B@rmaley.e>
Octane, спасибо, очень интересный прием.
#
B@rmaley.e>
Алина
ага прием действительно супер

Новый комментарий

как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть
как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть

metin2 pvp metin2 pvp serverler pvp serverler